Merge pull request #118 from topkecleon/develop

0.94 pre release for wider testing
This commit is contained in:
Kay Marquardt 2020-05-15 18:14:46 +02:00 committed by GitHub
commit e721a1aaa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 769 additions and 340 deletions

View File

@ -223,6 +223,6 @@ It features background tasks and interactive chats, and can serve as an interfac
<p>@Gnadelwartz</p> <p>@Gnadelwartz</p>
<h2>That's it!</h2> <h2>That's it!</h2>
<p>If you feel that there's something missing or if you found a bug, feel free to submit a pull request!</p> <p>If you feel that there's something missing or if you found a bug, feel free to submit a pull request!</p>
<h4>$$VERSION$$ v0.94-dev2-0-g3d636f7</h4> <h4>$$VERSION$$ v0.94-pre-0-gac2ec02</h4>
</body> </body>
</html> </html>

View File

@ -180,4 +180,4 @@ This may happen if to many wrong requests are sent to api.telegram.org, e.g. usi
If you feel that there's something missing or if you found a bug, feel free to submit a pull request! If you feel that there's something missing or if you found a bug, feel free to submit a pull request!
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -253,4 +253,4 @@ tor proxy on your server you may uncomment the ```BASHBOT_CURL_ARGS``` line in
If you feel that there's something missing or if you found a bug, feel free to If you feel that there's something missing or if you found a bug, feel free to
submit a pull request! submit a pull request!
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -4,7 +4,7 @@
# this addon counts how many files, e.g. stickers, are sent to # this addon counts how many files, e.g. stickers, are sent to
# a chat and takes actions if threshold is reached # a chat and takes actions if threshold is reached
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-4-gd28f975
# used events: # used events:
# #
@ -99,7 +99,7 @@ if [[ "$1" = "start"* ]]; then
antiFlood_multievent(){ antiFlood_multievent(){
# not started # not started
[ "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" = "" ] && return [ -z "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ] && return
# count user flood text # count user flood text
if [ "$1" = "text" ]; then if [ "$1" = "text" ]; then
if [ "${#MESSAGE[0]}" -gt "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ]; then if [ "${#MESSAGE[0]}" -gt "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ]; then

View File

@ -4,7 +4,7 @@
# Addons can register to bashbot events at statup # Addons can register to bashbot events at statup
# by providing their name and a callback per event # by providing their name and a callback per event
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# #
# If an event occours each registered event function is called. # If an event occours each registered event function is called.
# #

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# description: Start or stop telegram-bash-bot # description: Start or stop telegram-bash-bot
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-11-gac9ca60
# shellcheck disable=SC2009 # shellcheck disable=SC2009
# shellcheck disable=SC2181 # shellcheck disable=SC2181
@ -76,6 +76,11 @@ case "$1" in
'suspendback'|'resumeback'|'killback') 'suspendback'|'resumeback'|'killback')
$runcmd "$start $1" $runcmd "$start $1"
RETVAL=$? RETVAL=$?
# kill inotifywait from runuser if long running bg scripts use it
KILLINOTIFY=""
if [ "$1" != "resumeback" ] && [ -n "${KILLINOTIFY}" ]; then
kill -9 "$(ps -u "$runas" | grep inotifywait | sed 's/ .*//')" >/dev/null 2>&1
fi
;; ;;
*) *)
echo "Usage: $0 { start | stop | restart | reload | restartback | suspendback | resumeback | killback }" echo "Usage: $0 { start | stop | restart | reload | restartback | suspendback | resumeback | killback }"

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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-4-gd28f975
# #
# Exit Codes: # Exit Codes:
# - 0 sucess (hopefully) # - 0 sucess (hopefully)
@ -23,7 +23,7 @@
# shellcheck disable=SC2140 # shellcheck disable=SC2140
# are we runnig in a terminal? # are we runnig in a terminal?
if [ -t 1 ] && [ "$TERM" != "" ]; then if [ -t 1 ] && [ -n "$TERM" ]; then
CLEAR='clear' CLEAR='clear'
RED='\e[31m' RED='\e[31m'
GREEN='\e[32m' GREEN='\e[32m'
@ -31,6 +31,23 @@ if [ -t 1 ] && [ "$TERM" != "" ]; then
NC='\e[0m' NC='\e[0m'
fi fi
# some important helper functions
# returns true if command exist
_exists()
{
[ "$(LC_ALL=C type -t "$1")" = "file" ]
}
# execute function if exists
_exec_if_function() {
[ "$(LC_ALL=C type -t "${1}")" != "function" ] || "$@"
}
# returns true if function exist
_is_function()
{
[ "$(LC_ALL=C type -t "$1")" = "function" ]
}
# get location and name of bashbot.sh # get location and name of bashbot.sh
SCRIPT="$0" SCRIPT="$0"
REALME="${BASH_SOURCE[0]}" REALME="${BASH_SOURCE[0]}"
@ -39,7 +56,7 @@ RUNDIR="$(dirname "$0")"
MODULEDIR="${SCRIPTDIR}/modules" MODULEDIR="${SCRIPTDIR}/modules"
# adjust locations based on source and real name
if [ "${SCRIPT}" != "${REALME}" ] || [ "$1" = "source" ]; then if [ "${SCRIPT}" != "${REALME}" ] || [ "$1" = "source" ]; then
SOURCE="yes" SOURCE="yes"
else else
@ -47,17 +64,17 @@ else
MODULEDIR="./$(basename "${MODULEDIR}")" MODULEDIR="./$(basename "${MODULEDIR}")"
fi fi
if [ "$BASHBOT_HOME" != "" ]; then if [ -n "$BASHBOT_HOME" ]; then
SCRIPTDIR="$BASHBOT_HOME" SCRIPTDIR="$BASHBOT_HOME"
[ "${BASHBOT_ETC}" = "" ] && BASHBOT_ETC="$BASHBOT_HOME" [ -z "${BASHBOT_ETC}" ] && BASHBOT_ETC="$BASHBOT_HOME"
[ "${BASHBOT_VAR}" = "" ] && BASHBOT_VAR="$BASHBOT_HOME" [ -z "${BASHBOT_VAR}" ] && BASHBOT_VAR="$BASHBOT_HOME"
fi fi
ADDONDIR="${BASHBOT_ETC:-./addons}" ADDONDIR="${BASHBOT_ETC:-./addons}"
RUNUSER="${USER}" # USER is overwritten by bashbot array RUNUSER="${USER}" # USER is overwritten by bashbot array
if [ "${SOURCE}" != "yes" ] && [ "$BASHBOT_HOME" = "" ] && ! cd "${RUNDIR}" ; then if [ "${SOURCE}" != "yes" ] && [ -z "$BASHBOT_HOME" ] && ! cd "${RUNDIR}" ; then
echo -e "${RED}ERROR: Can't change to ${RUNDIR} ...${NC}" echo -e "${RED}ERROR: Can't change to ${RUNDIR} ...${NC}"
exit 1 exit 1
else else
@ -69,62 +86,71 @@ if [ ! -w "." ]; then
ls -ld . ls -ld .
fi fi
#####################
# Setup and check environment if BOTTOKEN is NOT set
TOKENFILE="${BASHBOT_ETC:-.}/token" TOKENFILE="${BASHBOT_ETC:-.}/token"
if [ ! -f "${TOKENFILE}" ]; then BOTADMIN="${BASHBOT_ETC:-.}/botadmin"
if [ "${CLEAR}" = "" ] && [ "$1" != "init" ]; then BOTACL="${BASHBOT_ETC:-.}/botacl"
echo "Running headless, run ${SCRIPT} init first!" DATADIR="${BASHBOT_VAR:-.}/data-bot-bash"
# !!!!! DEPRECATED !!!!!
COUNTFILE="${BASHBOT_VAR:-.}/count"
# we assume everthing is already set up correctly if we have TOKEN
if [ -z "${BOTTOKEN}" ]; then
# BOTTOKEN empty read from file
if [ ! -f "${TOKENFILE}" ]; then
if [ -z "${CLEAR}" ] && [ "$1" != "init" ]; then
echo "Running headless, set BOTTOKEN or run ${SCRIPT} init first!"
exit 2 exit 2
else else
${CLEAR} ${CLEAR}
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 token read -r BOTTOKEN
printf '%s\n' "${token}" > "${TOKENFILE}" printf '%s\n' "${BOTTOKEN}" > "${TOKENFILE}"
fi fi
fi fi
[ -z "${BOTTOKEN}" ] && BOTTOKEN="$(< "${TOKENFILE}")"
BOTADMIN="${BASHBOT_ETC:-.}/botadmin" # setup botadmin file
if [ ! -f "${BOTADMIN}" ]; then if [ ! -f "${BOTADMIN}" ]; then
if [ "${CLEAR}" = "" ]; then if [ -z "${CLEAR}" ]; then
echo "Running headless, set botadmin to AUTO MODE!" echo "Running headless, set botadmin to AUTO MODE!"
printf '%s\n' '?' > "${BOTADMIN}" printf '%s\n' '?' > "${BOTADMIN}"
else else
${CLEAR} ${CLEAR}
echo -e "${RED}BOTADMIN MISSING.${NC}" echo -e "${RED}BOTADMIN MISSING.${NC}"
echo -e "${ORANGE}PLEASE WRITE YOUR TELEGRAM ID HERE OR ENTER '?'${NC}" echo -e "${ORANGE}PLEASE WRITE YOUR TELEGRAM ID HERE OR ENTER '?'${NC}"
echo -e "${ORANGE}TO MAKE FIRST USER TYPING '/start' TO BOTADMIN${NC}" echo -e "${ORANGE}TO MAKE FIRST USER TYPING '/start' TO BOTADMIN${NC}"
read -r admin read -r admin
[ "${admin}" = "" ] && admin='?' [ -z "${admin}" ] && admin='?'
printf '%s\n' "${admin}" > "${BOTADMIN}" printf '%s\n' "${admin}" > "${BOTADMIN}"
fi fi
fi fi
# setup botacl file
BOTACL="${BASHBOT_ETC:-.}/botacl" if [ ! -f "${BOTACL}" ]; then
if [ ! -f "${BOTACL}" ]; then
echo -e "${ORANGE}Create empty ${BOTACL} file.${NC}" echo -e "${ORANGE}Create empty ${BOTACL} file.${NC}"
printf '\n' >"${BOTACL}" printf '\n' >"${BOTACL}"
fi fi
# setup data dir file
DATADIR="${BASHBOT_VAR:-.}/data-bot-bash" if [ ! -d "${DATADIR}" ]; then
if [ ! -d "${DATADIR}" ]; then
mkdir "${DATADIR}" mkdir "${DATADIR}"
elif [ ! -w "${DATADIR}" ]; then elif [ ! -w "${DATADIR}" ]; then
echo -e "${RED}ERROR: Can't write to ${DATADIR}!.${NC}" echo -e "${RED}ERROR: Can't write to ${DATADIR}!.${NC}"
ls -ld "${DATADIR}" ls -ld "${DATADIR}"
exit 2 exit 2
fi fi
# setup count file !!!!! DEPRECATED !!!!!
COUNTFILE="${BASHBOT_VAR:-.}/count" if [ ! -f "${COUNTFILE}" ]; then
if [ ! -f "${COUNTFILE}" ]; then
printf '\n' >"${COUNTFILE}" printf '\n' >"${COUNTFILE}"
elif [ ! -w "${COUNTFILE}" ]; then elif [ ! -w "${COUNTFILE}" ]; then
echo -e "${RED}ERROR: Can't write to ${COUNTFILE}!.${NC}" echo -e "${RED}ERROR: Can't write to ${COUNTFILE}!.${NC}"
ls -l "${COUNTFILE}" ls -l "${COUNTFILE}"
exit 2 exit 2
fi
fi fi
BOTTOKEN="$(< "${TOKENFILE}")" ##################
# here we start with the real stuff
URL="${BASHBOT_URL:-https://api.telegram.org/bot}${BOTTOKEN}" URL="${BASHBOT_URL:-https://api.telegram.org/bot}${BOTTOKEN}"
ME_URL=$URL'/getMe' ME_URL=$URL'/getMe'
@ -136,10 +162,12 @@ declare -rx SCRIPT SCRIPTDIR MODULEDIR RUNDIR ADDONDIR TOKENFILE BOTADMIN BOTACL
declare -rx BOTTOKEN URL ME_URL UPD_URL GETFILE_URL declare -rx BOTTOKEN URL ME_URL UPD_URL GETFILE_URL
declare -ax CMD declare -ax CMD
declare -Ax UPD BOTSENT USER MESSAGE URLS CONTACT LOCATION CHAT FORWARD REPLYTO VENUE iQUERY declare -Ax UPD BOTSENT USER MESSAGE URLS CONTACT LOCATION CHAT FORWARD REPLYTO VENUE iQUERY SERVICE NEWMEMBER
export res CAPTION export res CAPTION
#################EW#
# read commamds file if we are not sourced
COMMANDS="${BASHBOT_ETC:-.}/commands.sh" COMMANDS="${BASHBOT_ETC:-.}/commands.sh"
if [ "${SOURCE}" != "yes" ]; then if [ "${SOURCE}" != "yes" ]; then
if [ ! -f "${COMMANDS}" ] || [ ! -r "${COMMANDS}" ]; then if [ ! -f "${COMMANDS}" ] || [ ! -r "${COMMANDS}" ]; then
@ -155,7 +183,7 @@ fi
# load modules # load modules
for modules in "${MODULEDIR:-.}"/*.sh ; do for modules in "${MODULEDIR:-.}"/*.sh ; do
# shellcheck source=./modules/aliases.sh # shellcheck source=./modules/aliases.sh
[ -r "${modules}" ] && source "${modules}" "source" if ! _is_function "$(basename "${modules}")" && [ -r "${modules}" ]; then source "${modules}" "source"; fi
done done
################# #################
@ -186,40 +214,24 @@ proclist() {
# $1 sting to search for proramm to kill # $1 sting to search for proramm to kill
killallproc() { killallproc() {
local procid; procid="$(proclist "$1")" local procid; procid="$(proclist "$1")"
if [ "${procid}" != "" ] ; then if [ -n "${procid}" ] ; then
# shellcheck disable=SC2046 # shellcheck disable=SC2046
kill $(proclist "$1") kill $(proclist "$1")
sleep 1 sleep 1
procid="$(proclist "$1")" procid="$(proclist "$1")"
# shellcheck disable=SC2046 # shellcheck disable=SC2046
[ "${procid}" != "" ] && kill $(proclist -9 "$1") [ -n "${procid}" ] && kill $(proclist -9 "$1")
fi fi
} }
# returns true if command exist
_exists()
{
[ "$(LC_ALL=C type -t "$1")" = "file" ]
}
# execute function if exists
_exec_if_function() {
[ "$(LC_ALL=C type -t "${1}")" != "function" ] || "$@"
}
# returns true if function exist
_is_function()
{
[ "$(LC_ALL=C type -t "$1")" = "function" ]
}
declare -xr DELETE_URL=$URL'/deleteMessage' declare -xr DELETE_URL=$URL'/deleteMessage'
delete_message() { delete_message() {
sendJson "${1}" '"message_id": '"${2}"'' "${DELETE_URL}" sendJson "${1}" '"message_id": '"${2}"'' "${DELETE_URL}"
} }
get_file() { get_file() {
[ "$1" = "" ] && return [ -z "$1" ] && return
sendJson "" '"file_id": "'"${1}"'"' "${GETFILE_URL}" sendJson "" '"file_id": "'"${1}"'"' "${GETFILE_URL}"
printf '%s\n' "${URL}"/"$(JsonGetString <<< "${res}" '"result","file_path"')" printf '%s\n' "${URL}"/"$(JsonGetString <<< "${res}" '"result","file_path"')"
} }
@ -228,7 +240,7 @@ get_file() {
TIMEOUT="${BASHBOT_TIMEOUT}" TIMEOUT="${BASHBOT_TIMEOUT}"
[[ "$TIMEOUT" =~ ^[0-9]+$ ]] || TIMEOUT="20" [[ "$TIMEOUT" =~ ^[0-9]+$ ]] || TIMEOUT="20"
if [ "${BASHBOT_WGET}" = "" ] && _exists curl ; then if [ -z "${BASHBOT_WGET}" ] && _exists curl ; then
# simple curl or wget call, output to stdout # simple curl or wget call, output to stdout
getJson(){ getJson(){
# shellcheck disable=SC2086 # shellcheck disable=SC2086
@ -237,18 +249,18 @@ if [ "${BASHBOT_WGET}" = "" ] && _exists curl ; then
# usage: sendJson "chat" "JSON" "URL" # usage: sendJson "chat" "JSON" "URL"
sendJson(){ sendJson(){
local chat=""; local chat="";
[ "${1}" != "" ] && chat='"chat_id":'"${1}"',' [ -n "${1}" ] && chat='"chat_id":'"${1}"','
# shellcheck disable=SC2086 # shellcheck disable=SC2086
res="$(curl -s ${BASHBOT_CURL_ARGS} -m "${TIMEOUT}" -d '{'"${chat} $(iconv -f utf-8 -t utf-8 -c <<<$2)"'}' -X POST "${3}" \ res="$(curl -s -k ${BASHBOT_CURL_ARGS} -m "${TIMEOUT}" -d '{'"${chat} $(iconv -f utf-8 -t utf-8 -c <<<$2)"'}' -X POST "${3}" \
-H "Content-Type: application/json" | "${JSONSHFILE}" -s -b -n )" -H "Content-Type: application/json" | "${JSONSHFILE}" -s -b -n )"
BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")" BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")"
BOTSENT[ID]="$(JsonGetValue '"result","message_id"' <<< "$res")" BOTSENT[ID]="$(JsonGetValue '"result","message_id"' <<< "$res")"
[ "${SOURCE}" != "yes" ] && [ "${BASHBOT_EVENT_SEND[*]}" != "" ] && event_send "send" "$@" & [ "${SOURCE}" != "yes" ] && [ -n "${BASHBOT_EVENT_SEND[*]}" ] && event_send "send" "$@" &
} }
#$1 Chat, $2 what , $3 file, $4 URL, $5 caption #$1 Chat, $2 what , $3 file, $4 URL, $5 caption
sendUpload() { sendUpload() {
[ "$#" -lt 4 ] && return [ "$#" -lt 4 ] && return
if [ "$5" != "" ]; then if [ -n "$5" ]; then
# shellcheck disable=SC2086 # shellcheck disable=SC2086
res="$(curl -s -k ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1" -F "$2=@$3;${3##*/}" -F "caption=$5" | "${JSONSHFILE}" -s -b -n )" res="$(curl -s -k ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1" -F "$2=@$3;${3##*/}" -F "caption=$5" | "${JSONSHFILE}" -s -b -n )"
else else
@ -256,7 +268,7 @@ if [ "${BASHBOT_WGET}" = "" ] && _exists curl ; then
res="$(curl -s -k ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1" -F "$2=@$3;${3##*/}" | "${JSONSHFILE}" -s -b -n )" res="$(curl -s -k ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1" -F "$2=@$3;${3##*/}" | "${JSONSHFILE}" -s -b -n )"
fi fi
BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")" BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")"
[ "${SOURCE}" != "yes" ] && [ "${BASHBOT_EVENT_SEND[*]}" != "" ] && event_send "upload" "$@" & [ "${SOURCE}" != "yes" ] && [ -n "${BASHBOT_EVENT_SEND[*]}" ] && event_send "upload" "$@" &
} }
else else
# simple curl or wget call outputs result to stdout # simple curl or wget call outputs result to stdout
@ -267,18 +279,18 @@ else
# usage: sendJson "chat" "JSON" "URL" # usage: sendJson "chat" "JSON" "URL"
sendJson(){ sendJson(){
local chat=""; local chat="";
[ "${1}" != "" ] && chat='"chat_id":'"${1}"',' [ -n "${1}" ] && chat='"chat_id":'"${1}"','
# shellcheck disable=SC2086 # shellcheck disable=SC2086
res="$(wget -t 2 -T "${TIMEOUT}" ${BASHBOT_WGET_ARGS} -qO - --post-data='{'"${chat} $(iconv -f utf-8 -t utf-8 -c <<<$2)"'}' \ res="$(wget --no-check-certificate -t 2 -T "${TIMEOUT}" ${BASHBOT_WGET_ARGS} -qO - --post-data='{'"${chat} $(iconv -f utf-8 -t utf-8 -c <<<$2)"'}' \
--header='Content-Type:application/json' "${3}" | "${JSONSHFILE}" -s -b -n )" --header='Content-Type:application/json' "${3}" | "${JSONSHFILE}" -s -b -n )"
BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")" BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")"
BOTSENT[ID]="$(JsonGetValue '"result","message_id"' <<< "$res")" BOTSENT[ID]="$(JsonGetValue '"result","message_id"' <<< "$res")"
[ "${SOURCE}" != "yes" ] && [ "${BASHBOT_EVENT_SEND[*]}" != "" ] && event_send "send" "$@" & [ "${SOURCE}" != "yes" ] && [ -n "${BASHBOT_EVENT_SEND[*]}" ] && event_send "send" "$@" &
} }
sendUpload() { sendUpload() {
sendJson "$1" '"text":"Sorry, wget does not support file upload"' "${MSG_URL}" sendJson "$1" '"text":"Sorry, wget does not support file upload"' "${MSG_URL}"
BOTSENT[OK]="false" BOTSENT[OK]="false"
[ "${SOURCE}" != "yes" ] && [ "${BASHBOT_EVENT_SEND[*]}" != "" ] && event_send "upload" "$@" & [ "${SOURCE}" != "yes" ] && [ -n "${BASHBOT_EVENT_SEND[*]}" ] && event_send "upload" "$@" &
} }
fi fi
@ -293,11 +305,11 @@ JsonEscape() {
# title caption description markup inlinekeyboard # title caption description markup inlinekeyboard
title2Json(){ title2Json(){
local title caption desc markup keyboard local title caption desc markup keyboard
[ "$1" != "" ] && title=',"title":"'$(JsonEscape "$1")'"' [ -n "$1" ] && title=',"title":"'$(JsonEscape "$1")'"'
[ "$2" != "" ] && caption=',"caption":"'$(JsonEscape "$2")'"' [ -n "$2" ] && caption=',"caption":"'$(JsonEscape "$2")'"'
[ "$3" != "" ] && desc=',"description":"'$(JsonEscape "$3")'"' [ -n "$3" ] && desc=',"description":"'$(JsonEscape "$3")'"'
[ "$4" != "" ] && markup=',"parse_mode":"'$(JsonEscape "$4")'"' [ -n "$4" ] && markup=',"parse_mode":"'$(JsonEscape "$4")'"'
[ "$5" != "" ] && keyboard=',"reply_markup":"'$(JsonEscape "$5")'"' [ -n "$5" ] && keyboard=',"reply_markup":"'$(JsonEscape "$5")'"'
echo "${title}${caption}${desc}${markup}${keyboard}" echo "${title}${caption}${desc}${markup}${keyboard}"
} }
@ -332,7 +344,7 @@ JsonGetValue() {
# $1 ARRAY name, must be declared with "declare -A ARRAY" before calling # $1 ARRAY name, must be declared with "declare -A ARRAY" before calling
Json2Array() { Json2Array() {
# shellcheck source=./commands.sh # shellcheck source=./commands.sh
[ "$1" = "" ] || source <( printf "$1"'=( %s )' "$(sed -E -n -e '/\["[-0-9a-zA-Z_,."]+"\]\t/ s/\t/=/gp' -e 's/=(true|false)/="\1"/')" ) [ -z "$1" ] || source <( printf "$1"'=( %s )' "$(sed -E -n -e '/\["[-0-9a-zA-Z_,."]+"\]\t/ s/\t/=/gp' -e 's/=(true|false)/="\1"/')" )
} }
# output ARRAY as JSON.sh style data # output ARRAY as JSON.sh style data
# $1 ARRAY name, must be declared with "declare -A ARRAY" before calling # $1 ARRAY name, must be declared with "declare -A ARRAY" before calling
@ -360,7 +372,7 @@ process_client() {
CMD=( ); iQUERY=( ) CMD=( ); iQUERY=( )
iQUERY[ID]="${UPD["result",${num},"inline_query","id"]}" iQUERY[ID]="${UPD["result",${num},"inline_query","id"]}"
[[ "${debug}" = *"debug"* ]] && cat <<< "$UPDATE" >>"MESSAGE.log" [[ "${debug}" = *"debug"* ]] && cat <<< "$UPDATE" >>"MESSAGE.log"
if [ "${iQUERY[ID]}" = "" ]; then if [ -z "${iQUERY[ID]}" ]; then
process_message "${num}" "${debug}" process_message "${num}" "${debug}"
else else
process_inline "${num}" "${debug}" process_inline "${num}" "${debug}"
@ -372,13 +384,14 @@ process_client() {
source "${COMMANDS}" "${debug}" & source "${COMMANDS}" "${debug}" &
# then all registered addons # then all registered addons
if [ "${iQUERY[ID]}" = "" ]; then if [ -z "${iQUERY[ID]}" ]; then
event_message "${debug}" event_message "${debug}"
else else
event_inline "${debug}" event_inline "${debug}"
fi fi
# last count users # last count users
# !!!!! DEPRECATED !!!!!
tmpcount="COUNT${CHAT[ID]}" tmpcount="COUNT${CHAT[ID]}"
grep -q "$tmpcount" <"${COUNTFILE}" &>/dev/null || cat <<< "$tmpcount" >>"${COUNTFILE}" grep -q "$tmpcount" <"${COUNTFILE}" &>/dev/null || cat <<< "$tmpcount" >>"${COUNTFILE}"
} }
@ -431,7 +444,6 @@ event_inline() {
done done
} }
event_message() { event_message() {
echo "${MESSAGE[0]}"
local key debug="$1" local key debug="$1"
# ${MESSAEG[*]} event_message # ${MESSAEG[*]} event_message
# shellcheck disable=SC2153 # shellcheck disable=SC2153
@ -441,7 +453,7 @@ echo "${MESSAGE[0]}"
done done
# ${TEXT[*]} event_text # ${TEXT[*]} event_text
if [ "${MESSAGE[0]}" != "" ]; then if [ -n "${MESSAGE[0]}" ]; then
# shellcheck disable=SC2153 # shellcheck disable=SC2153
for key in "${!BASHBOT_EVENT_TEXT[@]}" for key in "${!BASHBOT_EVENT_TEXT[@]}"
do do
@ -449,7 +461,7 @@ echo "${MESSAGE[0]}"
done done
# ${CMD[*]} event_cmd # ${CMD[*]} event_cmd
if [ "${CMD[0]}" != "" ]; then if [ -n "${CMD[0]}" ]; then
# shellcheck disable=SC2153 # shellcheck disable=SC2153
for key in "${!BASHBOT_EVENT_CMD[@]}" for key in "${!BASHBOT_EVENT_CMD[@]}"
do do
@ -458,7 +470,7 @@ echo "${MESSAGE[0]}"
fi fi
fi fi
# ${REPLYTO[*]} event_replyto # ${REPLYTO[*]} event_replyto
if [ "${REPLYTO[UID]}" != "" ]; then if [ -n "${REPLYTO[UID]}" ]; then
# shellcheck disable=SC2153 # shellcheck disable=SC2153
for key in "${!BASHBOT_EVENT_REPLYTO[@]}" for key in "${!BASHBOT_EVENT_REPLYTO[@]}"
do do
@ -467,7 +479,7 @@ echo "${MESSAGE[0]}"
fi fi
# ${FORWARD[*]} event_forward # ${FORWARD[*]} event_forward
if [ "${FORWARD[UID]}" != "" ]; then if [ -n "${FORWARD[UID]}" ]; then
# shellcheck disable=SC2153 # shellcheck disable=SC2153
for key in "${!BASHBOT_EVENT_FORWARD[@]}" for key in "${!BASHBOT_EVENT_FORWARD[@]}"
do do
@ -476,7 +488,7 @@ echo "${MESSAGE[0]}"
fi fi
# ${CONTACT[*]} event_contact # ${CONTACT[*]} event_contact
if [ "${CONTACT[FIRST_NAME]}" != "" ]; then if [ -n "${CONTACT[FIRST_NAME]}" ]; then
# shellcheck disable=SC2153 # shellcheck disable=SC2153
for key in "${!BASHBOT_EVENT_CONTACT[@]}" for key in "${!BASHBOT_EVENT_CONTACT[@]}"
do do
@ -486,7 +498,7 @@ echo "${MESSAGE[0]}"
# ${VENUE[*]} event_location # ${VENUE[*]} event_location
# ${LOCALTION[*]} event_location # ${LOCALTION[*]} event_location
if [ "${LOCATION[LONGITUDE]}" != "" ] || [ "${VENUE[TITLE]}" != "" ]; then if [ -n "${LOCATION[LONGITUDE]}" ] || [ -n "${VENUE[TITLE]}" ]; then
# shellcheck disable=SC2153 # shellcheck disable=SC2153
for key in "${!BASHBOT_EVENT_LOCATION[@]}" for key in "${!BASHBOT_EVENT_LOCATION[@]}"
do do
@ -538,7 +550,7 @@ process_message() {
# in reply to message from # in reply to message from
REPLYTO=( ) REPLYTO=( )
REPLYTO[UID]="${UPD["result",${num},"message","reply_to_message","from","id"]}" REPLYTO[UID]="${UPD["result",${num},"message","reply_to_message","from","id"]}"
if [ "${REPLYTO[UID]}" != "" ]; then if [ -n "${REPLYTO[UID]}" ]; then
REPLYTO[0]="$(JsonDecode "${UPD["result",${num},"message","reply_to_message","text"]}")" REPLYTO[0]="$(JsonDecode "${UPD["result",${num},"message","reply_to_message","text"]}")"
REPLYTO[ID]="${UPD["result",${num},"message","reply_to_message","message_id"]}" REPLYTO[ID]="${UPD["result",${num},"message","reply_to_message","message_id"]}"
REPLYTO[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","reply_to_message","from","first_name"]}")" REPLYTO[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","reply_to_message","from","first_name"]}")"
@ -549,7 +561,7 @@ process_message() {
# forwarded message from # forwarded message from
FORWARD=( ) FORWARD=( )
FORWARD[UID]="${UPD["result",${num},"message","forward_from","id"]}" FORWARD[UID]="${UPD["result",${num},"message","forward_from","id"]}"
if [ "${FORWARD[UID]}" != "" ]; then if [ -n "${FORWARD[UID]}" ]; then
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[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","forward_from","first_name"]}")"
FORWARD[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","forward_from","last_name"]}")" FORWARD[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","forward_from","last_name"]}")"
@ -572,7 +584,7 @@ process_message() {
# Contact # Contact
CONTACT=( ) CONTACT=( )
CONTACT[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","contact","first_name"]}")" CONTACT[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","contact","first_name"]}")"
if [ "${CONTACT[FIRST_NAME]}" != "" ]; then if [ -n "${CONTACT[FIRST_NAME]}" ]; then
CONTACT[USER_ID]="$(JsonDecode "${UPD["result",${num},"message","contact","user_id"]}")" CONTACT[USER_ID]="$(JsonDecode "${UPD["result",${num},"message","contact","user_id"]}")"
CONTACT[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","contact","last_name"]}")" CONTACT[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","contact","last_name"]}")"
CONTACT[NUMBER]="${UPD["result",${num},"message","contact","phone_number"]}" CONTACT[NUMBER]="${UPD["result",${num},"message","contact","phone_number"]}"
@ -582,7 +594,7 @@ process_message() {
# vunue # vunue
VENUE=( ) VENUE=( )
VENUE[TITLE]="$(JsonDecode "${UPD["result",${num},"message","venue","title"]}")" VENUE[TITLE]="$(JsonDecode "${UPD["result",${num},"message","venue","title"]}")"
if [ "${VENUE[TITLE]}" != "" ]; then if [ -n "${VENUE[TITLE]}" ]; then
VENUE[ADDRESS]="$(JsonDecode "${UPD["result",${num},"message","venue","address"]}")" VENUE[ADDRESS]="$(JsonDecode "${UPD["result",${num},"message","venue","address"]}")"
VENUE[LONGITUDE]="${UPD["result",${num},"message","venue","location","longitude"]}" VENUE[LONGITUDE]="${UPD["result",${num},"message","venue","location","longitude"]}"
VENUE[LATITUDE]="${UPD["result",${num},"message","venue","location","latitude"]}" VENUE[LATITUDE]="${UPD["result",${num},"message","venue","location","latitude"]}"
@ -596,9 +608,27 @@ process_message() {
LOCATION[LONGITUDE]="${UPD["result",${num},"message","location","longitude"]}" LOCATION[LONGITUDE]="${UPD["result",${num},"message","location","longitude"]}"
LOCATION[LATITUDE]="${UPD["result",${num},"message","location","latitude"]}" LOCATION[LATITUDE]="${UPD["result",${num},"message","location","latitude"]}"
# service messages
SERVICE=( ); NEWMEMBER=( )
SERVICE[NEWMEMBER]="${UPD["result",${num},"message","new_chat_member","id"]}"
if [ -n "${SERVICE[NEWMEMBER]}" ]; then
NEWMEMBER[ID]="${SERVICE[NEWMEMBER]}"
NEWMEMBER[FIRSTNAME]="${UPD["result",${num},"message","new_chat_member","first_name"]}"
NEWMEMBER[LASTNAME]="${UPD["result",${num},"message","new_chat_member","last_name"]}"
NEWMEMBER[USERNAME]="${UPD["result",${num},"message","new_chat_member","username"]}"
NEWMEMBER[ISBOT]="${UPD["result",${num},"message","new_chat_member","is_bot"]}"
fi
SERVICE[LEFTMEMBER]="${UPD["result",${num},"message","left_chat_member","id"]}"
SERVICE[NEWTILE]="${UPD["result",${num},"message","new_chat_title"]}"
SERVICE[NEWPHOTO]="${UPD["result",${num},"message","new_chat_photo"]}"
SERVICE[PINNED]="${UPD["result",${num},"message","pinned_message"]}"
# set SSERVICE to yes if a service message was recieved
[[ "${SERVICE[*]}" =~ ^[[:blank:]]+$ ]] || SERVICE[0]="yes"
# split message in command and args # split message in command and args
CMD=( ) CMD=( )
if [[ "${MESSAGE[0]}" = "/"* ]]; then if [[ "${MESSAGE[0]}" == "/"* ]]; then
set -f; unset IFS set -f; unset IFS
# shellcheck disable=SC2206 # shellcheck disable=SC2206
CMD=( ${MESSAGE[0]} ) CMD=( ${MESSAGE[0]} )
@ -616,7 +646,7 @@ start_bot() {
local addsleep="100" local addsleep="100"
local maxsleep="$(( ${BASHBOT_SLEEP:-5000} + 100 ))" local maxsleep="$(( ${BASHBOT_SLEEP:-5000} + 100 ))"
[[ "${DEBUG}" = *"debug" ]] && exec &>>"DEBUG.log" [[ "${DEBUG}" = *"debug" ]] && exec &>>"DEBUG.log"
[ "${DEBUG}" != "" ] && date && echo "Start BASHBOT in Mode \"${DEBUG}\"" [ -n "${DEBUG}" ] && date && echo "Start BASHBOT in Mode \"${DEBUG}\""
[[ "${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
@ -626,6 +656,8 @@ start_bot() {
# shellcheck source=./modules/aliases.sh # shellcheck source=./modules/aliases.sh
[ -r "${addons}" ] && source "${addons}" "startbot" "${DEBUG}" [ -r "${addons}" ] && source "${addons}" "startbot" "${DEBUG}"
done done
# shellcheck source=./commands.sh
source "${COMMANDS}" "startbot"
# start timer events # start timer events
if _is_function start_timer ; then if _is_function start_timer ; then
# shellcheck disable=SC2064 # shellcheck disable=SC2064
@ -658,6 +690,7 @@ bot_init() {
# upgrade from old version # upgrade from old version
local OLDTMP="${BASHBOT_VAR:-.}/tmp-bot-bash" local OLDTMP="${BASHBOT_VAR:-.}/tmp-bot-bash"
[ -d "${OLDTMP}" ] && { mv -n "${OLDTMP}/"* "${DATADIR}"; rmdir "${OLDTMP}"; } [ -d "${OLDTMP}" ] && { mv -n "${OLDTMP}/"* "${DATADIR}"; rmdir "${OLDTMP}"; }
# no more existing modules
[ -f "modules/inline.sh" ] && rm -f "modules/inline.sh" [ -f "modules/inline.sh" ] && rm -f "modules/inline.sh"
# load addons on startup # load addons on startup
for addons in "${ADDONDIR:-.}"/*.sh ; do for addons in "${ADDONDIR:-.}"/*.sh ; do
@ -668,14 +701,14 @@ bot_init() {
[[ "${UID}" -eq "0" ]] && RUNUSER="nobody" [[ "${UID}" -eq "0" ]] && RUNUSER="nobody"
echo -n "Enter User to run basbot [$RUNUSER]: " echo -n "Enter User to run basbot [$RUNUSER]: "
read -r TOUSER read -r TOUSER
[ "$TOUSER" = "" ] && TOUSER="$RUNUSER" [ -z "$TOUSER" ] && TOUSER="$RUNUSER"
if ! id "$TOUSER" &>/dev/null; then if ! id "$TOUSER" &>/dev/null; then
echo -e "${RED}User \"$TOUSER\" not found!${NC}" echo -e "${RED}User \"$TOUSER\" not found!${NC}"
exit 3 exit 3
else else
# shellcheck disable=SC2009 # shellcheck disable=SC2009
oldbot="$(ps -fu "$TOUSER" | grep startbot | grep -v -e 'grep' -e '\-startbot' )" oldbot="$(ps -fu "$TOUSER" | grep startbot | grep -v -e 'grep' -e '\-startbot' )"
[ "${oldbot}" != "" ] && \ [ -n "${oldbot}" ] && \
echo -e "${ORANGE}Warning: At least one not upgraded TMUX bot is running! You must stop it with kill command:${NC}\\n${oldbot}" echo -e "${ORANGE}Warning: At least one not upgraded TMUX bot is running! You must stop it with kill command:${NC}\\n${oldbot}"
echo "Adjusting user \"${TOUSER}\" files and permissions ..." echo "Adjusting user \"${TOUSER}\" files and permissions ..."
[ -w "bashbot.rc" ] && sed -i '/^[# ]*runas=/ s/runas=.*$/runas="'$TOUSER'"/' "bashbot.rc" [ -w "bashbot.rc" ] && sed -i '/^[# ]*runas=/ s/runas=.*$/runas="'$TOUSER'"/' "bashbot.rc"
@ -707,7 +740,7 @@ fi
if [ "${SOURCE}" != "yes" ] && [ "$1" != "init" ] && [ "$1" != "help" ]; then if [ "${SOURCE}" != "yes" ] && [ "$1" != "init" ] && [ "$1" != "help" ]; then
ME="$(getBotName)" ME="$(getBotName)"
if [ "$ME" = "" ]; then if [ -z "$ME" ]; then
echo -e "${RED}ERROR: Can't connect to Telegram! Your TOKEN is invalid or you are blocked by ${URL%/*} ...${NC}" echo -e "${RED}ERROR: Can't connect to Telegram! Your TOKEN is invalid or you are blocked by ${URL%/*} ...${NC}"
case "$1" in case "$1" in
"" | "stop" | "kill"* | "suspendb"* ) # warn, but do not exit "" | "stop" | "kill"* | "suspendb"* ) # warn, but do not exit
@ -726,10 +759,10 @@ 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 "outproc") # forward output from interactive and jobs to chat
[ "$3" = "" ] && echo "No file to read from" && exit 3 [ -z "$3" ] && echo "No file to read from" && exit 3
[ "$2" = "" ] && echo "No chat to send to" && exit 3 [ -z "$2" ] && echo "No chat to send to" && exit 3
while read -r line ;do while read -r line ;do
[ "$line" != "" ] && send_message "$2" "$line" [ -n "$line" ] && send_message "$2" "$line"
done done
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"
@ -752,11 +785,11 @@ if [ "${SOURCE}" != "yes" ]; then
BOTPID="$(proclist "${SESSION}")" BOTPID="$(proclist "${SESSION}")"
case "$1" in case "$1" in
"count") "count") # !!!!! DEPRECATED !!!!!
echo "A total of $(wc -l <"${COUNTFILE}") users used me." echo "A total of $(wc -l <"${COUNTFILE}") users used me."
exit exit
;; ;;
"broadcast") "broadcast") # !!!!! DEPRECATED !!!!!
NUMCOUNT="$(wc -l <"${COUNTFILE}")" NUMCOUNT="$(wc -l <"${COUNTFILE}")"
echo "Sending the broadcast $* to $NUMCOUNT users." echo "Sending the broadcast $* to $NUMCOUNT users."
[ "$NUMCOUNT" -gt "300" ] && sleep="sleep 0.5" [ "$NUMCOUNT" -gt "300" ] && sleep="sleep 0.5"
@ -764,7 +797,7 @@ if [ "${SOURCE}" != "yes" ]; then
while read -r f; do send_markdown_message "${f//COUNT}" "$*"; $sleep; done <"${COUNTFILE}" while read -r f; do send_markdown_message "${f//COUNT}" "$*"; $sleep; done <"${COUNTFILE}"
;; ;;
"status") "status")
if [ "${BOTPID}" != "" ]; then if [ -n "${BOTPID}" ]; then
echo -e "${GREEN}Bot is running.${NC}" echo -e "${GREEN}Bot is running.${NC}"
exit exit
else else
@ -775,10 +808,10 @@ if [ "${SOURCE}" != "yes" ]; then
"start") "start")
# shellcheck disable=SC2086 # shellcheck disable=SC2086
[ "${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}" echo "Session Name: ${SESSION}"
if [ "$(proclist "${SESSION}")" != "" ]; then if [ -n "$(proclist "${SESSION}")" ]; then
echo -e "${GREEN}Bot started successfully.${NC}" echo -e "${GREEN}Bot started successfully.${NC}"
else else
echo -e "${RED}An error occurred while starting the bot.${NC}" echo -e "${RED}An error occurred while starting the bot.${NC}"
@ -786,7 +819,7 @@ if [ "${SOURCE}" != "yes" ]; then
fi fi
;; ;;
"kill"|"stop") "kill"|"stop")
if [ "${BOTPID}" != "" ]; then if [ -n "${BOTPID}" ]; then
# shellcheck disable=SC2086 # shellcheck disable=SC2086
if kill ${BOTPID}; then if kill ${BOTPID}; then
echo -e "${GREEN}OK. Bot stopped successfully.${NC}" echo -e "${GREEN}OK. Bot stopped successfully.${NC}"

View File

@ -1,11 +1,21 @@
#!/bin/bash #!/bin/bash
# file: commands.sh # file: commands.sh
# do not edit this file, instead place all your commands in mycommands.sh
# _____ _______ _ _ _
# (____ \ _ (_______) | (_)_ | |
# _ \ \ ___ ____ ___ | |_ _____ _ | |_| |_ | |
# | | | / _ \ | _ \ / _ \| _) | ___) / || | | _)|_|
# | |__/ / |_| | | | | | |_| | |__ | |____( (_| | | |__ _
# |_____/ \___/ |_| |_|\___/ \___) |_______)____|_|\___)_|
#
# this file *MUST* not be edited! palce your config and commands in
# the file "mycommnds.sh". a clean version is provided as "mycommands.clean"
#
# 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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-7-g64efe96
# #
# adjust your language setting here, e.g.when run from other user or cron. # adjust your language setting here, e.g.when run from other user or cron.
@ -17,13 +27,17 @@ export 'LANGUAGE=C.UTF-8'
unset IFS unset IFS
# set -f # if you are paranoid use set -f to disable globbing # set -f # if you are paranoid use set -f to disable globbing
# to change the default info message overwrite bashbot_info in mycommands.sh #
# this file *MUST* not edited!
# copy "mycommands.sh.dist" to "mycommnds.sh" and change the strings there
bashbot_info='This is bashbot, the Telegram bot written entirely in bash. bashbot_info='This is bashbot, the Telegram bot written entirely in bash.
It features background tasks and interactive chats, and can serve as an interface for CLI programs. It features background tasks and interactive chats, and can serve as an interface for CLI programs.
It currently can send, recieve and forward messages, custom keyboards, photos, audio, voice, documents, locations and video files. It currently can send, recieve and forward messages, custom keyboards, photos, audio, voice, documents, locations and video files.
' '
# to change the default help messages overwrite in mycommands.sh #
# this file *MUST* not edited!
# copy "mycommands.sh.dist" to "mycommnds.sh" and change the strings there
bashbot_help='*Available commands*: bashbot_help='*Available commands*:
*• /start*: _Start bot and get this message_. *• /start*: _Start bot and get this message_.
*• /help*: _Get this message_. *• /help*: _Get this message_.
@ -37,17 +51,22 @@ Get the code in my [GitHub](http://github.com/topkecleon/telegram-bot-bash)
' '
# load modues on startup and always on on debug # load modues on startup and always on on debug
if [ "${1}" = "source" ] || [[ "${1}" = *"debug"* ]] ; then if [ -n "${1}" ]; then
# load all readable modules # load all readable modules
for modules in "${MODULEDIR:-.}"/*.sh ; do for modules in "${MODULEDIR:-.}"/*.sh ; do
if [[ "${1}" == *"debug"* ]] || ! _is_function "$(basename "${modules}")"; then
# shellcheck source=./modules/aliases.sh # shellcheck source=./modules/aliases.sh
[ -r "${modules}" ] && source "${modules}" "${1}" [ -r "${modules}" ] && source "${modules}" "${1}"
done fi
done
fi fi
#
# this file *MUST* not edited!
# copy "mycommands.sh.dist" to "mycommnds.sh" and change the values there
# defaults to no inline and nonsense home dir # defaults to no inline and nonsense home dir
export INLINE="0" export INLINE="0"
export FILE_REGEX='/home/user/allowed/.*' export FILE_REGEX="${BASHBOT_ETC}/.*"
# load mycommands # load mycommands
@ -55,10 +74,10 @@ export FILE_REGEX='/home/user/allowed/.*'
[ -r "${BASHBOT_ETC:-.}/mycommands.sh" ] && source "${BASHBOT_ETC:-.}/mycommands.sh" "${1}" [ -r "${BASHBOT_ETC:-.}/mycommands.sh" ] && source "${BASHBOT_ETC:-.}/mycommands.sh" "${1}"
if [ "${1}" != "source" ];then if [ -z "${1}" ] || [[ "${1}" == *"debug"* ]];then
# detect inline commands.... # detect inline commands....
# no default commands, all processing is done in myinlines() # no default commands, all processing is done in myinlines()
if [ "$INLINE" != "0" ] && [ "${iQUERY[ID]}" != "" ]; then if [ "$INLINE" != "0" ] && [ -n "${iQUERY[ID]}" ]; then
# forward iinline query to optional dispatcher # forward iinline query to optional dispatcher
_exec_if_function myinlines _exec_if_function myinlines
@ -75,6 +94,9 @@ if [ "${1}" != "source" ];then
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
case "${MESSAGE}" in case "${MESSAGE}" in
################################################ ################################################
# this file *MUST* not edited!
# copy "mycommands.sh.dist" to "mycommnds.sh" and change the values and add your commands there
#
# GLOBAL commands start here, edit messages only # GLOBAL commands start here, edit messages only
'/info'*) '/info'*)
send_markdown_message "${CHAT[ID]}" "${bashbot_info}" send_markdown_message "${CHAT[ID]}" "${bashbot_info}"

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# this has to run once atfer git clone # this has to run once atfer git clone
# and every time we create new hooks # and every time we create new hooks
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# magic to ensure that we're always inside the root of our application, # magic to ensure that we're always inside the root of our application,
# no matter from which directory we'll run script # no matter from which directory we'll run script

View File

@ -3,7 +3,7 @@
# #
# works together with git pre-push.sh and ADD all changed files since last push # works together with git pre-push.sh and ADD all changed files since last push
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# magic to ensure that we're always inside the root of our application, # magic to ensure that we're always inside the root of our application,
# no matter from which directory we'll run script # no matter from which directory we'll run script

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
############ ############
# NOTE: you MUST run install-hooks.sh again when updating this file! # NOTE: you MUST run install-hooks.sh again when updating this file!

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
############ ############
# NOTE: you MUST run install-hooks.sh again when updating this file! # NOTE: you MUST run install-hooks.sh again when updating this file!

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# this has to run once atfer git clone # this has to run once atfer git clone
# and every time we create new hooks # and every time we create new hooks
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# magic to ensure that we're always inside the root of our application, # magic to ensure that we're always inside the root of our application,
# no matter from which directory we'll run script # no matter from which directory we'll run script

View File

@ -2,7 +2,7 @@
# file: make-distribution.sh # file: make-distribution.sh
# creates files and arcchives to dirtribute bashbot # creates files and arcchives to dirtribute bashbot
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-12-gb1d569a
# magic to ensure that we're always inside the root of our application, # magic to ensure that we're always inside the root of our application,
# no matter from which directory we'll run script # no matter from which directory we'll run script
@ -17,7 +17,7 @@ VERSION="$(git describe --tags | sed -e 's/-[0-9].*//' -e 's/v//')"
DISTNAME="telegram-bot-bash" DISTNAME="telegram-bot-bash"
DISTDIR="./DIST/${DISTNAME}" DISTDIR="./DIST/${DISTNAME}"
DISTFILES="bashbot.rc bashbot.sh commands.sh mycommands.sh doc examples modules addons LICENSE README.md README.txt README.html" DISTFILES="bashbot.rc bashbot.sh commands.sh mycommands.sh mycommands.sh.clean doc examples modules addons LICENSE README.md README.txt README.html"
# run tests first! # run tests first!

View File

@ -5,7 +5,7 @@
# If you your bot is finished you can use make-standalone.sh to create the # 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! # the old all-in-one bashbot: bashbot.sh and commands.sh only!
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# magic to ensure that we're always inside the root of our application, # magic to ensure that we're always inside the root of our application,
# no matter from which directory we'll run script # no matter from which directory we'll run script

View File

@ -1,3 +1,4 @@
# list of additional files to check from shellcheck # list of additional files to check from shellcheck
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-7-g64efe96
bashbot.rc bashbot.rc
mycommands.sh.clean

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# shellcheck disable=SC2016 # shellcheck disable=SC2016
# #
# Easy Versioning in git: # Easy Versioning in git:

View File

@ -87,5 +87,5 @@ The old format is supported for backward compatibility, but may fail for corner
#### [Next Create Bot](1_firstbot.md) #### [Next Create Bot](1_firstbot.md)
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -65,5 +65,5 @@ group. This step is up to you actually.
#### [Prev Installation](0_install.md) #### [Prev Installation](0_install.md)
#### [Next Getting started](2_usage.md) #### [Next Getting started](2_usage.md)
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -17,9 +17,13 @@ Have FUN!
### Files ### Files
``` ```
. .
├── bashbot.sh # main bashbot script - do not edit ├── mycommands.sh # THIS is your bot, place logic and commands here!
├── commands.sh # command dispatcher - do not edit
├── mycommands.sh # place your functions and commands here! ├── mycommands.sh.clean # copy to "mycommands.sh" if you start devloping your bot
├── mycommands.sh.dist # example bot, also used for testing bashbot internally
├── bashbot.sh # main bashbot script - DO NOT EDIT!
├── commands.sh # command dispatcher - DO NOT EDIT!
├── JSON.sh # bashbots JSON parser, see https://github.com/dominictarr/JSON.sh ├── JSON.sh # bashbots JSON parser, see https://github.com/dominictarr/JSON.sh
├── modules # optional functions, sourced by commands.sh ├── modules # optional functions, sourced by commands.sh
@ -65,16 +69,13 @@ Start or Stop your Bot use the following commands:
``` ```
### User count ### User count
To count the total number of users that ever used the bot run the following command:
```bash deprecated, will be removed!
./bashbot.sh count
``` ```
### Sending broadcasts to all users ### Sending broadcasts to all users
To send a broadcast to all of users that ever used the bot run the following command:
```bash
./bashbot.sh broadcast "Hey! I just wanted to let you know that the bot's been updated!"
``` ```
deprecated, will be removed!
---- ----
@ -134,6 +135,22 @@ Evertime a Message is recieved, you can read incoming data using the following v
* ```${VENUE[LONGITUDE]}```: Longitude * ```${VENUE[LONGITUDE]}```: Longitude
* ```${VENUE[LATITUDE]}```: Latitude * ```${VENUE[LATITUDE]}```: Latitude
* ```${VENUE[FOURSQUARE]}```: Fouresquare ID * ```${VENUE[FOURSQUARE]}```: Fouresquare ID
* ```$SERVICE```: This array contains info abbout recived service messages.
* ```${SERVICE}```: set to "yes" when a service message is recived.
* ```${SERVICE[NEWMEMBER]```: New user's id
* ```${NEWMEMBER[ID]```: New user's id
* ```${NEWMEMBER[FIRSTNAME]```: New user's first name
* ```${NEWMEMBER[LASTNAME]```: New user's last name
* ```${NEWMEMBER[USERNAME]```: New user's username
* ```${NEWMEMBER[ISBOT]```: New user is a bot
* ```${SERVICE[LEFTMEMBER]```: Id of user left
* ```${SERVICE[NEWTILE]```: Text of new title
* ```${SERVICE[NEWPHOTO]```: New Chat Picture array
* ```${SERVICE[PINNED]```: Pinned Message structure
### Inline queries ### Inline queries
Evertime a Message is recieved, you can read incoming data using the following variables: Evertime a Message is recieved, you can read incoming data using the following variables:
@ -223,5 +240,5 @@ send_action "${CHAT[ID]}" "action"
#### [Prev Create Bot](1_firstbot.md) #### [Prev Create Bot](1_firstbot.md)
#### [Next Advanced Usage](3_advanced.md) #### [Next Advanced Usage](3_advanced.md)
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -180,5 +180,5 @@ See also [answer_inline_multi, answer_inline_compose](6_reference.md#answer_inli
#### [Prev Getting started](2_usage.md) #### [Prev Getting started](2_usage.md)
#### [Next Expert Use](4_expert.md) #### [Next Expert Use](4_expert.md)
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -348,5 +348,5 @@ for every poll until the maximum of BASHBOT_SLEEP ms.
#### [Prev Advanced Use](3_advanced.md) #### [Prev Advanced Use](3_advanced.md)
#### [Next Best Practice](5_practice.md) #### [Next Best Practice](5_practice.md)
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -152,5 +152,5 @@ The second warning is about an unused variable, this is true because in our exam
#### [Prev Best Practice](5_practice.md) #### [Prev Best Practice](5_practice.md)
#### [Next Functions Reference](6_reference.md) #### [Next Functions Reference](6_reference.md)
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -457,17 +457,22 @@ Usually message is automatically forwarded in 'commands.sh', but you can forwar
*usage:* send_interactive "${CHAT[ID]}" "message" *usage:* send_interactive "${CHAT[ID]}" "message"
*replaces:*' incproc *replaces:* incproc
---- ----
### jsshDB ### jsshDB
Since output generated by JSON.sh is so handy to use in bash, we use the format for a simple keys/value storage and providing Since output generated by JSON.sh is so handy to use in bash, we use the format for a simple keys/value storage and providing
fucntions to read and write JSON.sh style data from and to files. fucntions to read and write JSON.sh style data from and to files.
The file extions is '.jssh' and for security reasons location of jssh files is restricted to BASHBOT_ETC. The file extions is '.jssh' and for security reasons location of jssh files is restricted to BASHBOT_ETC and BASHBOT_DATA..
Note: File names containg '..' and absolute file names pointing outside BASHBOT_ETC are refused by jsshDB functions. Note: File names containg '..' and absolute file names pointing outside BASHBOT_ETC or BASHBOT_DATA are refused by jsshDB functions.
Note2: Since version 0.94 jsshDB functions support file locking with flock. Write / Update operations use flock to wait until
previous operations are finished. see "man flock" for more information. Bashbot uses a maximum timeout of 10 seconds for flock.
If you don't want atomic write / update operations use the *_async variant of jsshDB functions. If flock is not availible
the *_async variant is automatically used.
*Example:* for file name: *Example:* for file name:
```bash ```bash
@ -506,19 +511,6 @@ Something wrong with /home/someuser/myfile
Something wrong with data-bot-bash/../../../somevalues Something wrong with data-bot-bash/../../../somevalues
``` ```
##### jssh_readDB
Read content of a .jssh file in JSON.sh format into given ARRAY. ARRAY name must be delared with "declare -A ARRAY" before calling readDB.
*usage:* jssh_readDB "ARRAY" "filename"
*example:*
```bash
# read file data-bot-bash/somevalues.jssh into array SOMEVALUES
jssh_readDB "SOMEVALUES" "${DATADIR:-.}/somevalues"
print "${SOMEVALUES[*]}"
```
##### jssh_writeDB ##### jssh_writeDB
Write content of an ARRAY into jsshDB file. ARRAY name must be delared with "declare -A ARRAY" before calling writeDB. Write content of an ARRAY into jsshDB file. ARRAY name must be delared with "declare -A ARRAY" before calling writeDB.
"DB" file MUST exist or nothing is written. "DB" file MUST exist or nothing is written.
@ -527,6 +519,8 @@ Note: Existing content is overwritten.
*usage:* jssh_writeDB "ARRAY" "filename" *usage:* jssh_writeDB "ARRAY" "filename"
*usage:* jssh_writeDB_async "ARRAY" "filename"
*example:* *example:*
```bash ```bash
# Prepare array to store vaules # Prepare array to store vaules
@ -550,6 +544,28 @@ cat "${DATADIR:-}/myvalues.jssh"
["value2"] "a value" ["value2"] "a value"
["whynot","subindex2","text"] "This is an example content for pseudo multidimensional bash array" ["whynot","subindex2","text"] "This is an example content for pseudo multidimensional bash array"
["whynot","subindex2"] "whynot B" ["whynot","subindex2"] "whynot B"
["whynot","subindex1"] "whynot A"
```
##### jssh_printDB
Print content of an ARRAY to STDOUT. ARRAY name must be delared with "declare -A ARRAY" before calling printDB..
*usage:* jssh_printDB "ARRAY"
*example:*
```bash
# Prepare array to store vaules
declare -A PRINTVALUES
# read file data-bot-bash/myvalues.jssh into array READVALUES
jssh_readDB "PRINTVALUES" "${DATADIR:-}/myvalues"
# print DB to stdout
jssh_printDB READVALUES
["value1"] "example"
["value2"] "a value"
["whynot","subindex2","text"] "This is an example content for pseudo multidimensional bash array"
["whynot","subindex2"] "whynot B"
["whynot","subindex1"] "whynot A"``` ["whynot","subindex1"] "whynot A"```
``` ```
@ -561,6 +577,8 @@ Note: Existing content not in ARRAY is kept in file.
*usage:* jssh_updateDB "ARRAY" "filename" *usage:* jssh_updateDB "ARRAY" "filename"
*usage:* jssh_updateDB_async "ARRAY" "filename"
*example:* *example:*
```bash ```bash
# continued example from writeDB # continued example from writeDB
@ -586,37 +604,16 @@ cat "$DBfile"
``` ```
##### jssh_insertDB
Insert, update, append a key=value pair to a jsshDB file, key name is only allowed to contain '-a-zA-Z0-9,._'
*usage:* jssh_insertDB "key" "value" "filename"
*example:*
```bash
jssh_insertDB "newkey" "an other value" "${DATADIR:-.}/myvalues"
```
##### jssh_getDB
Read a key=value pair from a jsshDB file, key name is only allowed to contain '-a-zA-Z0-9,._'
*usage:* jssh_getDB "key" "filename"
*example:*
```bash
result="$(jssh_getDB "newvalue" "${DATADIR:-.}/myvalues")"
# lets see whats the value of key newvalue
echo "$result"
this is new
```
----
##### jssh_readDB ##### jssh_readDB
Read content of a file in JSON.sh format into given ARRAY. ARRAY name must be delared with "declare -A ARRAY" upfront, Read content of a file in JSON.sh format into given ARRAY. ARRAY name must be delared with "declare -A ARRAY" upfront,
*usage:* jssh_readDB "ARRAY" "filename" *usage:* jssh_readDB "ARRAY" "filename"
*usage:* jssh_readDB_async "ARRAY" "filename"
Note: readDB uses concurrent / shared locking from flock so multiple proceses can read from file, as long no process is writing.
Maximum timeour for reading is 1s to not block readers.
*example:* *example:*
```bash ```bash
# Prepare array to read vaules # Prepare array to read vaules
@ -627,17 +624,15 @@ jssh_readDB "READVALUES" "${DATADIR:-}/myvalues"
# sinple command to output values ONLY # sinple command to output values ONLY
printf "${READVALUES[*]}" printf "${READVALUES[*]}"
example a value This is an example content for pseudo multidimensional bash array whynot B whynot A
# print DB to stdout
# function to output key and value jssh_printDB READVALUES
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; } ["value1"] "example"
["value2"] "a value"
printarr READVALUES ["whynot","subindex2","text"] "This is an example content for pseudo multidimensional bash array"
value1=example ["whynot","subindex2"] "whynot B"
value2=a value ["whynot","subindex1"] "whynot A"
whynot,subindex2,text=This is an example content for pseudo multidimensional bash array
whynot,subindex2=whynot B
whynot,subindex1=whynot A
# access Arrray # access Arrray
@ -654,18 +649,49 @@ READVALUES["value3"]="new value"
READVALUES[whynot,subindex3]="new subindex value" READVALUES[whynot,subindex3]="new subindex value"
# new output # new output
printarr READVALUES jssh_printDB READVALUES
value1=example ["value1"] "example"
value2=this is a changed value ["value3"] "new value"
whynot,subindex2,text=This is an example content for pseudo multidimensional bash array ["value2"] "this is a changed value"
whynot,subindex3=new subindex value ["whynot","subindex2","text"] "This is an example content for pseudo multidimensional bash array"
whynot,subindex2=whynot B ["whynot","subindex3"] "new subindex value"
whynot,subindex1=whynot A ["whynot","subindex2"] "whynot B"
["whynot","subindex1"] "whynot A"
``` ```
##### jssh_insertDB
Insert, update, append a key=value pair to a jsshDB file, key name is only allowed to contain '-a-zA-Z0-9,._'
*usage:* jssh_insertDB "key" "value" "filename"
*usage:* jssh_insertDB_asnyc "key" "value" "filename"
Note: insertDB uses also excusiv write locking, but with a maximum timeout of 2s. insertDB is a "fast" operation, simply adding the value to the end of the file.
*example:*
```bash
jssh_insertDB "newkey" "an other value" "${DATADIR:-.}/myvalues"
```
##### jssh_deleteKeyDB
Deleted a key=value pair froma jsshDB file, key name is only allowed to contain '-a-zA-Z0-9,._'
*usage:* jssh_deleteKeyDB "key" "filename"
*usage:* jssh_deleteKeyDB_async "key" "filename"
*example:*
```bash
jssh_deleteKeyDB "delkey"" "${DATADIR:-.}/myvalues"
```
https://linuxhint.com/associative_array_bash/ https://linuxhint.com/associative_array_bash/
https://linuxconfig.org/how-to-use-arrays-in-bash-script https://linuxconfig.org/how-to-use-arrays-in-bash-script
----
### Aliases - shortcuts for often used funtions ### Aliases - shortcuts for often used funtions
Aliases are handy shortcuts for using in 'mycommands.sh', they avoid error prone typing of "${CHAT[ID]}" "${USER[ID]}" as much as possible. Aliases are handy shortcuts for using in 'mycommands.sh', they avoid error prone typing of "${CHAT[ID]}" "${USER[ID]}" as much as possible.
Do not use them in bashbot.sh, modules and addons. Do not use them in bashbot.sh, modules and addons.
@ -947,5 +973,5 @@ The name of your bot is availible as bash variable "$ME", there is no need to ca
#### [Prev Best Practice](5_practice.md) #### [Prev Best Practice](5_practice.md)
#### [Next Notes for Developers](7_develop.md) #### [Next Notes for Developers](7_develop.md)
#### $$VERSION$$ v0.94-dev2-1-g4f90215 #### $$VERSION$$ v0.94-pre-13-g52bde30

View File

@ -7,17 +7,24 @@ If you want to provide fixes or new features [fork bashbot on githup](https://he
### Debugging Bashbot ### Debugging Bashbot
Usually all bashbot output is discarded. Usually all bashbot output is discarded.
If you want to get error messages (and more) start bashbot in the current shell with ```./bashbot.sh startbot```. If you want to get error messages (and more) start bashbot ```./bashbot.sh startbot debug```.
In addition you can the change the level of verbosity by adding a 'debug' as third argument. you can the change the level of verbosity of the debug argument:
``` ```
"debug" all output is redirected to "DEBUG.log", in addtion every incomming message is logged in "MESSAGE.log" and "INLINE.log"
"xdebug" same as debug plus set bash option '-x' to log any executed command in "DEBUG.log"
use the command tail to watch your bot live, e.g. "tail -f DEBUG.log", to obtain more information place set -x; set +x in your code.
```
```
sometimes its useful to watch the bot live in the terminal:
"debugx" debug output and errors are sent to terminal "debugx" debug output and errors are sent to terminal
"xdebugx" same as debugx plus set bash option '-x' to show any executed command "xdebugx" same as debugx plus set bash option '-x' to show any executed command
"debug" all output is redirected to "DEBUG.log", in addtion every incomming message is logged in "MESSAGE.LOG" and "INLINE.log"
"xdebug" same as debug plus set bash option '-x' to log any executed command in "DEBUG.log"
``` ```
To stop bashhbot in debugging mode press CRTL+C. If this does not stop bashbot or you run it in background execute ```ps -uf | grep debug``` and kill all shown processes.
### Modules and Addons ### Modules and Addons
**Modules** resides in ```modules/*.sh``` and are colletions of optional bashbot functions grouped by functionality. Main reason for creating modules was **Modules** resides in ```modules/*.sh``` and are colletions of optional bashbot functions grouped by functionality. Main reason for creating modules was
@ -321,5 +328,5 @@ fi
#### [Prev Function Reference](6_reference.md) #### [Prev Function Reference](6_reference.md)
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-0-gac2ec02

View File

@ -55,6 +55,6 @@ convert existing bots.
**external-use** will contain some examples on how to send messages from external scripts to Telegram chats or users. **external-use** will contain some examples on how to send messages from external scripts to Telegram chats or users.
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a

View File

@ -4,7 +4,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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment

View File

@ -2,7 +2,7 @@
# file: run_filename # file: run_filename
# background job to display content of all new files in WATCHDIR # background job to display content of all new files in WATCHDIR
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment

View File

@ -2,7 +2,7 @@
# file: run_filename # file: run_filename
# background job to display all new files in WATCHDIR # background job to display all new files in WATCHDIR
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment

View File

@ -4,7 +4,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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment

View File

@ -2,7 +2,7 @@
# file. multibot.sh # file. multibot.sh
# description: run multiple telegram bots from one installation # description: run multiple telegram bots from one installation
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
if [ "${2}" = "" ] || [ "${2}" = "-h" ]; then if [ "${2}" = "" ] || [ "${2}" = "-h" ]; then
echo "Usage: $0 botname command" echo "Usage: $0 botname command"

View File

@ -7,7 +7,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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
SHELL=/bin/sh SHELL=/bin/sh

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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment

View File

@ -4,7 +4,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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment

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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment

View File

@ -1,7 +1,7 @@
# file: botacl # file: botacl
# a user not listed here, will return false from 'user_is_allowed' # a user not listed here, will return false from 'user_is_allowed'
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# Format: # Format:
# user:ressource:chat # user:ressource:chat

View File

@ -5,7 +5,7 @@
# to show how you can customize bashbot by only editing mycommands.sh # to show how you can customize bashbot by only editing mycommands.sh
# NOTE: this is not tested, simply copied from original source and reworked! # NOTE: this is not tested, simply copied from original source and reworked!
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# #
# shellcheck disable=SC2154 # shellcheck disable=SC2154
# shellcheck disable=SC2034 # shellcheck disable=SC2034

View File

@ -5,10 +5,13 @@
# 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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-2-gc0a633f
# #
# source from commands.sh to use the aliases # source from commands.sh to use the aliases
# source once magic, function named like file
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
# easy handling of users: # easy handling of users:
_is_botadmin() { _is_botadmin() {
user_is_botadmin "${USER[ID]}" user_is_botadmin "${USER[ID]}"

View File

@ -5,10 +5,13 @@
# 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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-2-gc0a633f
# source from commands.sh to use the inline functions # source from commands.sh to use the inline functions
# 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_query() {
@ -33,15 +36,15 @@ inline_query_compose(){
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) "photo") # photo ID photoURL (thumbURL title description caption)
[ "$4" = "" ] && tumb="$3" [ -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) "gif") # gif ID photoURL (thumbURL title caption)
[ "$4" = "" ] && tumb="$3" [ -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) "mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption)
[ "$4" != "" ] && tumb='","thumb_url":"'$4'"' [ -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) "video") # video ID videoURL mime thumbURL title (caption)
@ -60,13 +63,13 @@ inline_query_compose(){
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 (adress forsquare) "venue") # venue ID lat long title (adress forsquare)
[ "$6" = "" ] && addr="$5" [ -z "$6" ] && addr="$5"
[ "$7" != "" ] && fours=',"foursquare_id":"'$7'"' [ -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) "contact") # contact ID phone first (last thumb)
[ "$5" != "" ] && last=',"last_name":"'$5'"' [ -n "$5" ] && last=',"last_name":"'$5'"'
[ "$6" != "" ] && tumb='","thumb_url":"'$6'"' [ -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 # title2Json title caption description markup inlinekeyboard

View File

@ -5,10 +5,13 @@
# 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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-2-gc0a633f
# source from commands.sh if you want ro use interactive or background jobs # source from commands.sh if you want ro use interactive or background jobs
# source once magic, function named like file
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
###### ######
# interactive and background functions # interactive and background functions
@ -47,7 +50,7 @@ start_back() {
# $2 program # $2 program
# $3 prefix # $3 prefix
start_proc() { start_proc() {
[ "$2" = "" ] && return [ -z "$2" ] && return
[ -x "${2%% *}" ] || return 1 [ -x "${2%% *}" ] || return 1
local fifo; fifo="${DATADIR:-.}/$(procname "$1" "$3")" local fifo; fifo="${DATADIR:-.}/$(procname "$1" "$3")"
kill_proc "$1" "$3" kill_proc "$1" "$3"
@ -66,7 +69,7 @@ check_back() {
# $1 chatid # $1 chatid
# $2 prefix # $2 prefix
check_proc() { check_proc() {
[ "$(proclist "$(procname "$1" "$2")")" != "" ] [ -n "$(proclist "$(procname "$1" "$2")")" ]
# shellcheck disable=SC2034 # shellcheck disable=SC2034
res=$?; return $? res=$?; return $?
} }
@ -87,7 +90,7 @@ kill_proc() {
prid="$(proclist "${fifo}")" prid="$(proclist "${fifo}")"
fifo="${DATADIR:-.}/${fifo}" fifo="${DATADIR:-.}/${fifo}"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
[ "${prid}" != "" ] && kill ${prid} [ -n "${prid}" ] && kill ${prid}
[ -s "${fifo}.log" ] || rm -f "${fifo}.log" [ -s "${fifo}.log" ] || rm -f "${fifo}.log"
[ -p "${fifo}" ] && rm -f "${fifo}"; [ -p "${fifo}" ] && rm -f "${fifo}";
} }

View File

@ -5,7 +5,10 @@
# 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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-5-g6c6b312
# source once magic, function named like file
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
# source from commands.sh to use the member functions # source from commands.sh to use the member functions
@ -48,6 +51,7 @@ user_is_admin() {
user_is_botadmin() { user_is_botadmin() {
local admin; admin="$(head -n 1 "${BOTADMIN}")" local admin; admin="$(head -n 1 "${BOTADMIN}")"
[ "${admin}" = "${1}" ] && return 0 [ "${admin}" = "${1}" ] && return 0
[ "${admin}" = "${2}" ] && return 0
[[ "${admin}" = "@*" ]] && [[ "${admin}" = "${2}" ]] && return 0 [[ "${admin}" = "@*" ]] && [[ "${admin}" = "${2}" ]] && return 0
if [ "${admin}" = "?" ]; then printf '%s\n' "${1:-?}" >"${BOTADMIN}"; return 0; fi if [ "${admin}" = "?" ]; then printf '%s\n' "${1:-?}" >"${BOTADMIN}"; return 0; fi
return 1 return 1
@ -55,10 +59,10 @@ user_is_botadmin() {
user_is_allowed() { user_is_allowed() {
local acl="$1" local acl="$1"
[ "$1" = "" ] && return 1 [ -z "$1" ] && return 1
grep -F -xq "${acl}:*:*" <"${BOTACL}" && return 0 grep -F -xq "${acl}:*:*" <"${BOTACL}" && return 0
[ "$2" != "" ] && acl="${acl}:$2" [ -n "$2" ] && acl="${acl}:$2"
grep -F -xq "${acl}:*" <"${BOTACL}" && return 0 grep -F -xq "${acl}:*" <"${BOTACL}" && return 0
[ "$3" != "" ] && acl="${acl}:$3" [ -n "$3" ] && acl="${acl}:$3"
grep -F -xq "${acl}" <"${BOTACL}" grep -F -xq "${acl}" <"${BOTACL}"
} }

View File

@ -5,45 +5,72 @@
# 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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-13-g52bde30
# #
# source from commands.sh to use jsonDB functions # source from commands.sh to use jsonDB functions
# #
# jsonDB provides simple functions to read and store bash Arrays # jsonDB provides simple functions to read and store bash Arrays
# from to file in JSON.sh output format, its a simple key/value storage. # from to file in JSON.sh output format, its a simple key/value storage.
# read content of a file in JSON.sh format into given ARRAY
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
# $2 filename, must be relative to BASHBOT_ETC, and not contain '..'
jssh_readDB() {
local DB; DB="$(jssh_checkDB "$2")"
[ "${DB}" = "" ] && return 1
[ ! -f "${DB}" ] && return 2
Json2Array "$1" <"${DB}"
}
# write ARRAY content to a file in JSON.sh format # source once magic, function named like file
# Warning: old content is overwritten eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..' # new feature: serialize / atomic operations:
jssh_writeDB() { # updates will be done atomic with flock
local DB; DB="$(jssh_checkDB "$2")" # flock should flock should be availible on all system as its part of busybox
[ "${DB}" = "" ] && return 1 # tinybox
[ ! -f "${DB}" ] && return 2
Array2Json "$1" >"${DB}" # lockfile filename.flock is persistent and will be testet with flock for active lock (file open)
} export BASHBOT_LOCKNAME=".flock"
if _exists flock; then
###############
# we have flock
# use flock for atomic operations
# read content of a file in JSON.sh format into given ARRAY
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
# $2 filename, must be relative to BASHBOT_ETC, and not contain '..'
jssh_readDB() {
local DB; DB="$(jssh_checkDB "$2")"
[ -z "${DB}" ] && return 1
[ ! -f "${DB}" ] && return 2
# shared lock, many processes can read, maximum wait 1s
{ flock -s -w 1 200; Json2Array "$1" <"${DB}"; } 200>"${DB}${BASHBOT_LOCKNAME}"
}
# write ARRAY content to a file in JSON.sh format
# Warning: old content is overwritten
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_writeDB() {
local DB; DB="$(jssh_checkDB "$2")"
[ -z "${DB}" ] && return 1
[ ! -f "${DB}" ] && return 2
# exclusive lock, no other process can read or write, maximum wait to get lock is 10s
{ flock -e -w 10 200; Array2Json "$1" >"${DB}"; } 200>"${DB}${BASHBOT_LOCKNAME}"
}
# update/write ARRAY content in file without deleting keys not in ARRAY
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_updateDB() {
# for atomic update we cant use read/writeDB
local DB; DB="$(jssh_checkDB "$2")"
[ -z "${DB}" ] && return 1
[ ! -f "${DB}" ] && return 2
# update/write ARRAY content in file without deleting keys not in ARRAY
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_updateDB() {
declare -n ARRAY="$1" declare -n ARRAY="$1"
[ "${ARRAY[*]}" = "" ] && return 1 [ -z "${ARRAY[*]}" ] && return 1
declare -A oldARR newARR declare -A oldARR newARR
jssh_readDB "oldARR" "$2" || return "$?"
if [ "${oldARR[*]}" = "" ]; then # start atomic update here, exclusive max wait 10s
{ flock -e -w 10 200
Json2Array "oldARR" <"${DB}"
if [ -z "${oldARR[*]}" ]; then
# no old content # no old content
jssh_writeDB "$1" "$2" Array2Json "$1" >"${DB}"
else else
# merge arrays # merge arrays
local o1 o2 n1 n2 local o1 o2 n1 n2
@ -53,23 +80,78 @@ jssh_updateDB() {
#shellcheck disable=SC2034,SC2190,SC2206 #shellcheck disable=SC2034,SC2190,SC2206
newARR=( ${o2:0:${#o2}-1} ${n2:0:${#n2}-1} ) newARR=( ${o2:0:${#o2}-1} ${n2:0:${#n2}-1} )
set +f set +f
jssh_writeDB "newARR" "$2" Array2Json "newARR" >"${DB}"
fi fi
} } 200>"${DB}${BASHBOT_LOCKNAME}"
}
# insert, update, apped key/value to jsshDB # insert, update, apped key/value to jsshDB
# $1 key name, can onyl contain -a-zA-Z0-9,._ # $1 key name, can onyl contain -a-zA-Z0-9,._
# $2 key value # $2 key value
# $3 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..' # $3 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_insertDB() { jssh_insertDB() {
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3 [[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
local key="$1" value="$2" local key="$1" value="$2"
local DB; DB="$(jssh_checkDB "$3")" local DB; DB="$(jssh_checkDB "$3")"
[ "${DB}" = "" ] && return 1 [ -z "${DB}" ] && return 1
[ ! -f "${DB}" ] && return 2 [ ! -f "${DB}" ] && return 2
# its append, but last one counts, its a simple DB ... # start atomic update here, exclusive max wait 2si, it's append, not overwrite
printf '["%s"]\t"%s"\n' "${key//,/\",\"}" "${value//\"/\\\"}" >>"${DB}" { flock -e -w 2 200
# it's append, but last one counts, its a simple DB ...
printf '["%s"]\t"%s"\n' "${key//,/\",\"}" "${value//\"/\\\"}" >>"${DB}"
} 200>"${DB}${BASHBOT_LOCKNAME}"
}
# delete key/value from jsshDB
# $1 key name, can onyl contain -a-zA-Z0-9,._
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_deleteKeyDB() {
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
declare -A oldARR
# start atomic delete here, exclusive max wait 10s
{ flock -e -w 10 200
Json2Array "oldARR" <"${DB}"
if [[ -v "oldAR[$1]" ]] ; then
unset oldARR["$1"]
Array2Json "oldARR" >"${DB}"
fi
} 200>"${DB}${BASHBOT_LOCKNAME}"
}
else
#########
# we have no flock, use "old" not atomic functions
jssh_readDB() {
jssh_readDB_async "$@"
}
jssh_writeDB() {
jssh_writeDB_async "$@"
}
jssh_updateDB() {
jssh_updateDB_async "$@"
}
jssh_insertDB() {
jssh_insertDB_async "$@"
}
jssh_deleteKeyDB() {
jssh_deleteKeyDB_async "$@"
}
fi
##############
# no need for atomic
# print ARRAY content to stdout instead of file
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
jssh_printDB() {
Array2Json "$1"
} }
# get key/value from jsshDB # get key/value from jsshDB
@ -87,7 +169,7 @@ jssh_getDB() {
# $1 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..' # $1 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_newDB() { jssh_newDB() {
local DB; DB="$(jssh_checkDB "$1")" local DB; DB="$(jssh_checkDB "$1")"
[ "${DB}" = "" ] && return 1 [ -z "${DB}" ] && return 1
[ -f "${DB}" ] && return 2 # already exist, do not zero out [ -f "${DB}" ] && return 2 # already exist, do not zero out
printf '\n' >"${DB}" printf '\n' >"${DB}"
} }
@ -95,10 +177,72 @@ jssh_newDB() {
# $1 filename, check filename, it must be relative to BASHBOT_ETC, and not contain '..' # $1 filename, check filename, it must be relative to BASHBOT_ETC, and not contain '..'
# returns real path to DB file if everything is ok # returns real path to DB file if everything is ok
jssh_checkDB(){ jssh_checkDB(){
[ "$1" = "" ] && return 1 [ -z "$1" ] && return 1
local DB="${BASHBOT_ETC:-.}/$1.jssh" local DB="${BASHBOT_ETC:-.}/$1.jssh"
[[ "$1" = "${BASHBOT_ETC:-.}"* ]] && DB="$1.jssh" if [[ "$1" = "${BASHBOT_ETC:-.}"* ]] || [[ "$1" = "${BASHBOT_DATA:-.}"* ]]; then
DB="$1.jssh"
fi
[[ "$1" = *'..'* ]] && return 2 [[ "$1" = *'..'* ]] && return 2
printf '%s\n' "${DB}" printf '%s\n' "${DB}"
} }
######################
# "old" implementations as non atomic functions
# can be used explictitly or as fallback if flock is not availible
jssh_readDB_async() {
local DB; DB="$(jssh_checkDB "$2")"
[ -z "${DB}" ] && return 1
[ ! -f "${DB}" ] && return 2
Json2Array "$1" <"${DB}"
}
jssh_writeDB_async() {
local DB; DB="$(jssh_checkDB "$2")"
[ -z "${DB}" ] && return 1
[ ! -f "${DB}" ] && return 2
Array2Json "$1" >"${DB}"
}
jssh_updateDB_async() {
declare -n ARRAY="$1"
[ -z "${ARRAY[*]}" ] && return 1
declare -A oldARR newARR
jssh_readDB_async "oldARR" "$2" || return "$?"
if [ -z "${oldARR[*]}" ]; then
# no old content
jssh_writeDB_async "$1" "$2"
else
# merge arrays
local o1 o2 n1 n2
o1="$(declare -p oldARR)"; o2="${o1#*\(}"
n1="$(declare -p ARRAY)"; n2="${n1#*\(}"
unset IFS; set -f
#shellcheck disable=SC2034,SC2190,SC2206
newARR=( ${o2:0:${#o2}-1} ${n2:0:${#n2}-1} )
set +f
jssh_writeDB_async "newARR" "$2"
fi
}
jssh_insertDB_async() {
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
local key="$1" value="$2"
local DB; DB="$(jssh_checkDB "$3")"
[ -z "${DB}" ] && return 1
[ ! -f "${DB}" ] && return 2
# its append, but last one counts, its a simple DB ...
printf '["%s"]\t"%s"\n' "${key//,/\",\"}" "${value//\"/\\\"}" >>"${DB}"
}
jssh_deleteKeyDB_async() {
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
declare -A oldARR
jssh_readDB_async "oldARR" "$2" || return "$?"
if [[ -v "oldAR[$1]" ]] ; then
unset oldARR["$1"]
jssh_writeDB_async "oldARR" "$2"
fi
}

View File

@ -5,7 +5,10 @@
# 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.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-8-g284172f
# source once magic, function named like file
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
# source from commands.sh to use the sendMessage functions # source from commands.sh to use the sendMessage functions
@ -22,7 +25,7 @@ ACTION_URL=$URL'/sendChatAction'
FORWARD_URL=$URL'/forwardMessage' FORWARD_URL=$URL'/forwardMessage'
send_normal_message() { send_normal_message() {
local text="$(JsonEscape "${2}")" local text; text="$(JsonEscape "${2}")"
until [ -z "${text}" ]; do until [ -z "${text}" ]; do
sendJson "${1}" '"text":"'"${text:0:4096}"'"' "${MSG_URL}" sendJson "${1}" '"text":"'"${text:0:4096}"'"' "${MSG_URL}"
text="${text:4096}" text="${text:4096}"
@ -30,7 +33,7 @@ send_normal_message() {
} }
send_markdown_message() { send_markdown_message() {
local text="$(JsonEscape "${2}")" local text; text="$(JsonEscape "${2}")"
until [ -z "${text}" ]; do until [ -z "${text}" ]; do
sendJson "${1}" '"text":"'"${text:0:4096}"'","parse_mode":"markdown"' "${MSG_URL}" sendJson "${1}" '"text":"'"${text:0:4096}"'","parse_mode":"markdown"' "${MSG_URL}"
text="${text:4096}" text="${text:4096}"
@ -38,7 +41,7 @@ send_markdown_message() {
} }
send_html_message() { send_html_message() {
local text="$(JsonEscape "${2}")" local text; text="$(JsonEscape "${2}")"
until [ -z "${text}" ]; do until [ -z "${text}" ]; do
sendJson "${1}" '"text":"'"${text:0:4096}"'","parse_mode":"html"' "${MSG_URL}" sendJson "${1}" '"text":"'"${text:0:4096}"'","parse_mode":"html"' "${MSG_URL}"
text="${text:4096}" text="${text:4096}"
@ -46,7 +49,7 @@ send_html_message() {
} }
old_send_keyboard() { old_send_keyboard() {
local text='"text":"'$(JsonEscape "${2}")'"' local text; text='"text":"'$(JsonEscape "${2}")'"'
shift 2 shift 2
local keyboard="init" local keyboard="init"
OLDIFS="$IFS" OLDIFS="$IFS"
@ -64,24 +67,24 @@ sendEmpty() {
} }
send_keyboard() { send_keyboard() {
if [[ "$3" != *'['* ]]; then old_send_keyboard "${@}"; return; fi if [[ "$3" != *'['* ]]; then old_send_keyboard "${@}"; return; fi
local text='"text":"'$(JsonEscape "${2}")'"'; [ "${2}" = "" ] && text='"text":"'"${ISEMPTY}"'"' local text; text='"text":"'$(JsonEscape "${2}")'"'; [ -z "${2}" ] && text='"text":"'"${ISEMPTY}"'"'
local one_time=', "one_time_keyboard":true' && [ "$4" != "" ] && one_time="" local one_time=', "one_time_keyboard":true' && [ -n "$4" ] && one_time=""
sendEmpty "${1}" "${text}"', "reply_markup": {"keyboard": [ '"${3}"' ] '"${one_time}"'}' "$MSG_URL" sendEmpty "${1}" "${text}"', "reply_markup": {"keyboard": [ '"${3}"' ] '"${one_time}"'}' "$MSG_URL"
# '"text":"$2", "reply_markup": {"keyboard": [ ${3} ], "one_time_keyboard": true}' # '"text":"$2", "reply_markup": {"keyboard": [ ${3} ], "one_time_keyboard": true}'
} }
remove_keyboard() { remove_keyboard() {
local text='"text":"'$(JsonEscape "${2}")'"'; [ "${2}" = "" ] && text='"text":"'"${ISEMPTY}"'"' local text; text='"text":"'$(JsonEscape "${2}")'"'; [ -z "${2}" ] && text='"text":"'"${ISEMPTY}"'"'
sendEmpty "${1}" "${text}"', "reply_markup": {"remove_keyboard":true}' "$MSG_URL" sendEmpty "${1}" "${text}"', "reply_markup": {"remove_keyboard":true}' "$MSG_URL"
#JSON='"text":"$2", "reply_markup": {"remove_keyboard":true}' #JSON='"text":"$2", "reply_markup": {"remove_keyboard":true}'
} }
send_inline_keyboard() { send_inline_keyboard() {
local text='"text":"'$(JsonEscape "${2}")'"'; [ "${2}" = "" ] && text='"text":"'"${ISEMPTY}"'"' local text; text='"text":"'$(JsonEscape "${2}")'"'; [ -z "${2}" ] && text='"text":"'"${ISEMPTY}"'"'
sendEmpty "${1}" "${text}"', "reply_markup": {"inline_keyboard": [ '"${3}"' ]}' "$MSG_URL" sendEmpty "${1}" "${text}"', "reply_markup": {"inline_keyboard": [ '"${3}"' ]}' "$MSG_URL"
# JSON='"text":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}' # JSON='"text":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}'
} }
send_button() { send_button() {
send_inline_keyboard "${1}" "${2}" '[ {"text":"'$(JsonEscape "${3}")'", "url":"'"${4}"'"}]' send_inline_keyboard "${1}" "${2}" '[ {"text":"'"$(JsonEscape "${3}")"'", "url":"'"${4}"'"}]'
} }
@ -90,7 +93,7 @@ UPLOADDIR="${BASHBOT_UPLOAD:-${DATADIR}/upload}"
# for now this can only send local files with curl! # for now this can only send local files with curl!
# extend to allow send files by URL or telegram ID # extend to allow send files by URL or telegram ID
send_file() { send_file() {
[ "$2" = "" ] && return [ -z "$2" ] && return
[[ "$2" = "http"* ]] && return # currently we do not support URL [[ "$2" = "http"* ]] && return # currently we do not support URL
upload_file "${@}" upload_file "${@}"
} }
@ -114,7 +117,7 @@ upload_file(){
WHAT="audio" WHAT="audio"
STATUS="upload_audio" STATUS="upload_audio"
;; ;;
png|jpg|jpeg|gif) png|jpg|jpeg|gif|pic)
CUR_URL="$PHO_URL" CUR_URL="$PHO_URL"
WHAT="photo" WHAT="photo"
STATUS="upload_photo" STATUS="upload_photo"
@ -147,25 +150,25 @@ upload_file(){
# 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 # 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() { send_action() {
[ "$2" = "" ] && return [ -z "$2" ] && return
sendJson "${1}" '"action": "'"${2}"'"' "$ACTION_URL" sendJson "${1}" '"action": "'"${2}"'"' "$ACTION_URL" &
} }
send_location() { send_location() {
[ "$3" = "" ] && return [ -z "$3" ] && return
sendJson "${1}" '"latitude": '"${2}"', "longitude": '"${3}"'' "$LOCATION_URL" sendJson "${1}" '"latitude": '"${2}"', "longitude": '"${3}"'' "$LOCATION_URL"
} }
send_venue() { send_venue() {
local add="" local add=""
[ "$5" = "" ] && return [ -z "$5" ] && return
[ "$6" != "" ] && add=', "foursquare_id": '"$6"'' [ -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"
} }
forward_message() { forward_message() {
[ "$3" = "" ] && return [ -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() { # backward compatibility
@ -173,7 +176,7 @@ forward() { # backward compatibility
} }
send_message() { send_message() {
[ "$2" = "" ] && return [ -z "$2" ] && return
local text keyboard btext burl no_keyboard file lat long title address sent local text keyboard btext burl no_keyboard file lat long title address sent
text="$(sed <<< "${2}" 's/ mykeyboardend.*//;s/ *my[kfltab][a-z]\{2,13\}startshere.*//')$(sed <<< "${2}" -n '/mytextstartshere/ s/.*mytextstartshere//p')" text="$(sed <<< "${2}" 's/ mykeyboardend.*//;s/ *my[kfltab][a-z]\{2,13\}startshere.*//')$(sed <<< "${2}" -n '/mytextstartshere/ s/.*mytextstartshere//p')"
text="$(sed <<< "${text}" 's/ *mynewlinestartshere */\r\n/g')" text="$(sed <<< "${text}" 's/ *mynewlinestartshere */\r\n/g')"
@ -188,27 +191,27 @@ send_message() {
title="$(sed <<< "${2}" '/mytitlestartshere /!d;s/.*mytitlestartshere //;s/ *my[kfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')" 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.*//')" address="$(sed <<< "${2}" '/myaddressstartshere /!d;s/.*myaddressstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
} }
if [ "$no_keyboard" != "" ]; then if [ -n "$no_keyboard" ]; then
remove_keyboard "$1" "$text" remove_keyboard "$1" "$text"
sent=y sent=y
fi fi
if [ "$keyboard" != "" ]; then if [ -n "$keyboard" ]; then
if [[ "$keyboard" != *"["* ]]; then # pre 0.60 style if [[ "$keyboard" != *"["* ]]; then # pre 0.60 style
keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]" keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]"
fi fi
send_keyboard "$1" "$text" "$keyboard" send_keyboard "$1" "$text" "$keyboard"
sent=y sent=y
fi fi
if [ "$btext" != "" ] && [ "$burl" != "" ]; then if [ -n "$btext" ] && [ -n "$burl" ]; then
send_button "$1" "$text" "$btext" "$burl" send_button "$1" "$text" "$btext" "$burl"
sent=y sent=y
fi fi
if [ "$file" != "" ]; then if [ -n "$file" ]; then
send_file "$1" "$file" "$text" send_file "$1" "$file" "$text"
sent=y sent=y
fi fi
if [ "$lat" != "" ] && [ "$long" != "" ]; then if [ -n "$lat" ] && [ -n "$long" ]; then
if [ "$address" != "" ] && [ "$title" != "" ]; then if [ -n "$address" ] && [ -n "$title" ]; then
send_venue "$1" "$lat" "$long" "$title" "$address" send_venue "$1" "$lat" "$long" "$title" "$address"
else else
send_location "$1" "$lat" "$long" send_location "$1" "$lat" "$long"

View File

@ -1,16 +1,22 @@
#!/bin/bash #!/bin/bash
# files: mycommands.sh.dist #########
# copy to mycommands.sh and add all your commands and functions here ...
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 # files: mycommands.sh.dist
#
# this is an out of the box test and example file to show what you can do in mycommands.sh
#
# #### if you start to develop your own bot, use the clean version of this file:
# #### mycommands.clean
#
#### $$VERSION$$ v0.94-pre-7-g64efe96
# #
# uncomment the following lines to overwrite info and help messages # uncomment the following lines to overwrite info and help messages
# bashbot_info='This is bashbot, the Telegram bot written entirely in bash. # export bashbot_info='This is bashbot, the Telegram bot written entirely in bash.
#' #'
# bashbot_help='*Available commands*: # export bashbot_help='*Available commands*:
#' #'
res="" export res=""
# Set INLINE to 1 in order to receive inline queries. # Set INLINE to 1 in order to receive inline queries.
# To enable this option in your bot, send the /setinline command to @BotFather. # To enable this option in your bot, send the /setinline command to @BotFather.
@ -19,15 +25,44 @@ export INLINE="0"
# NOTE: this is a regex, not shell globbing! you must use a valid egex, # NOTE: this is a regex, not shell globbing! you must use a valid egex,
# '.' matches any charater and '.*' matches all remaining charatcers! # '.' matches any charater and '.*' matches all remaining charatcers!
# additionally you must escape special charaters with '\', e.g. '\. \? \[ \*" to match them literally # additionally you must escape special charaters with '\', e.g. '\. \? \[ \*" to match them literally
export FILE_REGEX='^/home/user/allowed/.*' export FILE_REGEX="${BASHBOT_ETC}/.*"
# example: run bashbot over TOR # example: run bashbot over TOR
# export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1:9050" # export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1:9050"
if [ "$1" != "source" ];then # set to "yes" and give your bot admin privilegs to remove service messaes from groups
# your additional bahsbot commands export SILENCER="no"
if [ "$1" = "startbot" ];then
###################
# this function is run once after startup when the first message is recieved
my_startup(){
# send message ito first user on startup
send_normal_message "${CHAT[ID]}" "Hi, you was the first one after startup!"
}
# reminde bot that it was started
touch .mystartup
else
# here we call the function above when the mesage arrives
# things to do only at soure, eg. after startup
[ -f .mystartup ] && rm -f .mystartup && _exec_if_function my_startup
#############################
# your own bashbot commands
# NOTE: command can have @botname attached, you must add * in case tests... # NOTE: command can have @botname attached, you must add * in case tests...
mycommands() { mycommands() {
##############
# a service Message was recieved
# add your own stuff here
if [ -n "${SERVICE}" ]; then
# example: delete every service message
if [ "${SILENCER}" = "yes" ]; then
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
fi
fi
case "${MESSAGE}" in case "${MESSAGE}" in
################## ##################
# example commands, replace thm by your own # example commands, replace thm by your own

123
mycommands.sh.clean Normal file
View File

@ -0,0 +1,123 @@
#!/bin/bash
########
#
# files: mycommands.sh.clean
# copy to mycommands.sh and add all your commands and functions here ...
#
#### $$VERSION$$ v0.94-pre-7-g64efe96
#
##########
# edit the following lines to fit your bot usage
export bashbot_info='This is bashbot, the Telegram bot written entirely in bash.
'
export bashbot_help='*Available commands*:
'
export res=""
# Set INLINE to 1 in order to receive inline queries.
# To enable this option in your bot ypu must also send the /setinline command to @BotFather.
export INLINE="0"
# NOTE: this is a regex, not shell globbing! you must use a valid egex,
# '.' matches any charater and '.*' matches all remaining charatcers!
# additionally you must escape special charaters with '\', e.g. '\. \? \[ \*" to match them literally
# do NOT set to .* as this allow sending files from all locations!
export FILE_REGEX="${BASHBOT_ETC}/.*"
# set to "yes" and give your bot admin privilegs to remove service messaes from groups
export SILENCER="no"
########
# special network setups may require to provide additional ARGS to curl
#
# example: run bashbot over TOR or SOCKS proxy
# export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1:9050" # TOR
# export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1" # regular SOCKS
if [ "$1" = "startbot" ];then
# run once after startup when the first message is recieved
my_startup(){
:
}
touch .mystartup
else
# here we call the function above when the mesage arrives
# things to do only at soure, eg. after startup
[ -f .mystartup ] && rm -f .mystartup && _exec_if_function my_startup
#############################
# your own bashbot commands
# NOTE: command can have @botname attached, you must add * in case tests...
mycommands() {
##############
# a service Message was recieved
# add your own stuff here
if [ -n "${SERVICE}" ]; then
# example: delete every service message
if [ "${SILENCER}" = "yes" ]; then
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
fi
fi
case "${MESSAGE}" in
##################
# example command, replace them by your own
'/echo'*) # example echo command
send_normal_message "${CHAT[ID]}" "$MESSAGE"
;;
##########
# command overwrite examples
# return 0 -> run default command afterwards
# return 1 -> skip possible default commands
'/info'*) # output date in front of regular info
send_normal_message "${CHAT[ID]}" "$(date)"
return 0
;;
'/kickme'*) # this will replace the /kickme command
send_markdown_mesage "${CHAT[ID]}" "*This bot will not kick you!*"
return 1
;;
esac
}
myinlines() {
#######################
# this fuinction is called only if you has set INLINE=1 !!
# shellcheck disable=SC2128
iQUERY="${iQUERY,,}"
case "${iQUERY}" in
##################
# example inline command, replace it by your own
"image "*) # search images with yahoo
local search="${iQUERY#* }"
answer_inline_multi "${iQUERY[ID]}" "$(my_image_search "${search}")"
;;
esac
}
#####################
# place your processing functions here
# example inline processing function, not really useful
# $1 search parameter
my_image_search(){
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/</\n</g' | grep "<img src=")"
while read -r image; do
[ "$count" -gt "20" ] && break
image="${image#* src=\'}"; image="${image%%&pid=*}"
[[ "${image}" = *"src="* ]] && continue
echo "${sep}"; inline_query_compose "$RANDOM" "photo" "${image}"; sep=","
count=$(( count + 1 ))
done <<<"${result}"
}
fi

View File

@ -2,7 +2,7 @@
# #
# ADD a new test skeleton to test dir, but does not activate test # ADD a new test skeleton to test dir, but does not activate test
# #
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# magic to ensure that we're always inside the root of our application, # magic to ensure that we're always inside the root of our application,
# no matter from which directory we'll run script # no matter from which directory we'll run script

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-4-gd28f975
# common variables # common variables
export TESTME DIRME TESTDIR LOGFILE REFDIR TESTNAME export TESTME DIRME TESTDIR LOGFILE REFDIR TESTNAME

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
../dev/hooks/pre-commit.sh ../dev/hooks/pre-commit.sh

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# file: b-example-test.sh # file: b-example-test.sh
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# include common functions and definitions # include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh # shellcheck source=test/ALL-tests.inc.sh

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-4-gd28f975
# include common functions and definitions # include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh # shellcheck source=test/ALL-tests.inc.sh

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# include common functions and definitions # include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh # shellcheck source=test/ALL-tests.inc.sh

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# include common functions and definitions # include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh # shellcheck source=test/ALL-tests.inc.sh

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-10-g23a3d4b
# include common functions and definitions # include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh # shellcheck source=test/ALL-tests.inc.sh

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-pre-10-g23a3d4b
# include common functions and definitions # include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh # shellcheck source=test/ALL-tests.inc.sh

View File

@ -1,4 +1,4 @@
chat:123456 JSON:"text":"# test for text only output" chat:123456 JSON:"text":"\# test for text only output"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":"This is a normal text" chat:123456 JSON:"text":"This is a normal text"
@ -8,21 +8,21 @@ chat:123456 JSON:"text":"This is a normal text
with a line break" with a line break"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":" This is a <b>HTML</b> text","parse_mode":"html" chat:123456 JSON:"text":" This is a <b>HTML<\/b> text","parse_mode":"html"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":" This is a <b>HTML</b> text chat:123456 JSON:"text":" This is a <b>HTML<\/b> text
with a line break","parse_mode":"html" with a line break","parse_mode":"html"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":" This is a *MARKDOWN* text","parse_mode":"markdown" chat:123456 JSON:"text":" This is a \*MARKDOWN\* text","parse_mode":"markdown"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":" This is a *MARKDOWN* text chat:123456 JSON:"text":" This is a \*MARKDOWN\* text
with a line break","parse_mode":"markdown" with a line break","parse_mode":"markdown"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":"# test for keyboard, file, venue output" chat:123456 JSON:"text":"\# test for keyboard\, file\, venue output"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":"Text plus keyboard will appear in chat", "reply_markup": {"keyboard": [ [ "Yep, sure" , "No, highly unlikely" ] ] , "one_time_keyboard":true} chat:123456 JSON:"text":"Text plus keyboard will appear in chat", "reply_markup": {"keyboard": [ [ "Yep, sure" , "No, highly unlikely" ] ] , "one_time_keyboard":true}
@ -34,31 +34,31 @@ URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashb
chat:123456 JSON:"latitude": la10, "longitude": lo20, "address": "Diagon Alley N. 37", "title": "my home" chat:123456 JSON:"latitude": la10, "longitude": lo20, "address": "Diagon Alley N. 37", "title": "my home"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendVenue URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendVenue
chat:123456 JSON:"text":"# test for new inline button" chat:123456 JSON:"text":"\# test for new inline button"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":"Text plus keyboard will appear in chat", "reply_markup": {"inline_keyboard": [ [ {"text":"Button Text", "url":"https://www..."}] ]} chat:123456 JSON:"text":"Text plus keyboard will appear in chat", "reply_markup": {"inline_keyboard": [ [ {"text":"Button Text", "url":"https://www..."}] ]}
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":"STABILO 88/240 Fineliner point 88 chat:123456 JSON:"text":"STABILO 88\/240 Fineliner point 88
[https://images-na.ssl-images-amazon.com/images/I/41oypA3kmHL.l_SX300.jpg] [https:\/\/images\-na.ssl\-images\-amazon.com\/images\/I\/41oypA3kmHL.l_SX300.jpg]
second part of text second part of text
plus newline.", "reply_markup": {"inline_keyboard": [ [ {"text":"Bei Amazon ansehen ...", "url":"https://www.amazon.de/dp/B014TN3JYW"}] ]} plus newline.", "reply_markup": {"inline_keyboard": [ [ {"text":"Bei Amazon ansehen ...", "url":"https://www.amazon.de/dp/B014TN3JYW"}] ]}
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"text":"# test for sendfile" chat:123456 JSON:"text":"\# test for sendfile"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendMessage
chat:123456 JSON:"action": "upload_photo"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendChatAction
chat:123456 JSON:"photo":"/tmp/allowed/this_is_my.gif","caption":"Text plus absolute file will appear in chat" chat:123456 JSON:"photo":"/tmp/allowed/this_is_my.gif","caption":"Text plus absolute file will appear in chat"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendPhoto URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendPhoto
chat:123456 JSON:"action": "upload_document" chat:123456 JSON:"action": "upload_photo"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendChatAction URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendChatAction
chat:123456 JSON:"document":"/tmp/allowed/this_is_my.doc","caption":"Text plus absolute file will appear in chat" chat:123456 JSON:"document":"/tmp/allowed/this_is_my.doc","caption":"Text plus absolute file will appear in chat"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendDocument URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendDocument
chat:123456 JSON:"action": "upload_document"
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?bashbottestscript/sendChatAction

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# include common functions and definitions # include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh # shellcheck source=test/ALL-tests.inc.sh

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### $$VERSION$$ v0.94-dev2-0-g3d636f7 #### $$VERSION$$ v0.94-dev3-0-geef955a
# include common functions and definitions # include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh # shellcheck source=test/ALL-tests.inc.sh