mirror of
https://github.com/octoleo/telegram-bot-bash.git
synced 2024-12-01 03:13:52 +00:00
modules: factor out processUpdates.sh
This commit is contained in:
parent
7c748247d8
commit
c693ab5bb9
440
bashbot.sh
440
bashbot.sh
@ -30,7 +30,7 @@ BOTCOMMANDS="-h help init start stop status suspendback resumeback killb
|
|||||||
# 8 - curl/wget missing
|
# 8 - curl/wget missing
|
||||||
# 10 - not bash!
|
# 10 - not bash!
|
||||||
#
|
#
|
||||||
#### $$VERSION$$ v1.35-dev-31-ga3eec98
|
#### $$VERSION$$ v1.40-dev-3-g7c74824
|
||||||
##################################################################
|
##################################################################
|
||||||
|
|
||||||
# emmbeded system may claim bash but it is not
|
# emmbeded system may claim bash but it is not
|
||||||
@ -467,6 +467,7 @@ sendJson(){
|
|||||||
[ -n "${BASHBOT_EVENT_SEND[*]}" ] && event_send "send" "${@}" &
|
[ -n "${BASHBOT_EVENT_SEND[*]}" ] && event_send "send" "${@}" &
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# curl / wget specific functions
|
# curl / wget specific functions
|
||||||
#
|
#
|
||||||
@ -662,77 +663,8 @@ JsonDecode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
################
|
|
||||||
# processing of updates starts here
|
|
||||||
process_updates() {
|
|
||||||
local max num debug="$1"
|
|
||||||
max="$(grep -F ',"update_id"]' <<< "${UPDATE}" | tail -1 | cut -d , -f 2 )"
|
|
||||||
Json2Array 'UPD' <<<"${UPDATE}"
|
|
||||||
for ((num=0; num<=max; num++)); do
|
|
||||||
process_client "${num}" "${debug}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
process_client() {
|
|
||||||
local num="$1" debug="$2"
|
|
||||||
pre_process_message "${num}"
|
|
||||||
# log message on debug
|
|
||||||
[[ -n "${debug}" ]] && log_message "New Message ==========\n$(grep -F '["result",'"${num}" <<<"${UPDATE}")"
|
|
||||||
|
|
||||||
# check for users / groups to ignore
|
|
||||||
jssh_updateArray_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
|
||||||
[ -n "${USER[ID]}" ] && [[ -n "${BASHBOTBLOCKED[${USER[ID]}]}" || -n "${BASHBOTBLOCKED[${CHAT[ID]}]}" ]] && return
|
|
||||||
|
|
||||||
# process per message type
|
|
||||||
if [ -n "${iQUERY[ID]}" ]; then
|
|
||||||
process_inline_query "${num}" "${debug}"
|
|
||||||
printf "%(%c)T: Inline Query update received FROM=%s iQUERY=%s\n" -1\
|
|
||||||
"${iQUERY[USERNAME]:0:20} (${iQUERY[USER_ID]})" "${iQUERY[0]}" >>"${UPDATELOG}"
|
|
||||||
elif [ -n "${iBUTTON[ID]}" ]; then
|
|
||||||
process_inline_button "${num}" "${debug}"
|
|
||||||
printf "%(%c)T: Inline Button update received FROM=%s CHAT=%s CALLBACK=%s DATA:%s \n" -1\
|
|
||||||
"${iBUTTON[USERNAME]:0:20} (${iBUTTON[USER_ID]})" "${iBUTTON[CHAT_ID]}" "${iBUTTON[ID]}" "${iBUTTON[DATA]}" >>"${UPDATELOG}"
|
|
||||||
else
|
|
||||||
if grep -qs -e '\["result",'"${num}"',"edited_message"' <<<"${UPDATE}"; then
|
|
||||||
# edited message
|
|
||||||
UPDATE="${UPDATE//,${num},\"edited_message\",/,${num},\"message\",}"
|
|
||||||
Json2Array 'UPD' <<<"${UPDATE}"
|
|
||||||
MESSAGE[0]="/_edited_message "
|
|
||||||
fi
|
|
||||||
process_message "${num}" "${debug}"
|
|
||||||
printf "%(%c)T: update received FROM=%s CHAT=%s CMD=%s\n" -1 "${USER[USERNAME]:0:20} (${USER[ID]})"\
|
|
||||||
"${CHAT[USERNAME]:0:20}${CHAT[TITLE]:0:30} (${CHAT[ID]})"\
|
|
||||||
"${MESSAGE:0:30}${CAPTION:0:30}${URLS[*]:0:30}" >>"${UPDATELOG}"
|
|
||||||
fi
|
|
||||||
#####
|
|
||||||
# process inline and message events
|
|
||||||
# first classic command dispatcher
|
|
||||||
# shellcheck source=./commands.sh
|
|
||||||
{ source "${COMMANDS}" "${debug}"; } &
|
|
||||||
|
|
||||||
# then all registered addons
|
|
||||||
if [ -z "${iQUERY[ID]}" ]; then
|
|
||||||
event_message "${debug}"
|
|
||||||
else
|
|
||||||
event_inline "${debug}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# last count users
|
|
||||||
jssh_countKeyDB_async "${CHAT[ID]}" "${COUNTFILE}"
|
|
||||||
}
|
|
||||||
|
|
||||||
declare -Ax BASHBOT_EVENT_INLINE BASHBOT_EVENT_MESSAGE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLYTO BASHBOT_EVENT_FORWARD BASHBOT_EVENT_SEND
|
|
||||||
declare -Ax BASHBOT_EVENT_CONTACT BASHBOT_EVENT_LOCATION BASHBOT_EVENT_FILE BASHBOT_EVENT_TEXT BASHBOT_EVENT_TIMER BASHBOT_BLOCKED
|
|
||||||
|
|
||||||
start_timer(){
|
|
||||||
# send alarm every ~60 s
|
|
||||||
while :; do
|
|
||||||
sleep 59.5
|
|
||||||
kill -ALRM $$
|
|
||||||
done;
|
|
||||||
}
|
|
||||||
|
|
||||||
EVENT_SEND="0"
|
EVENT_SEND="0"
|
||||||
|
declare -Ax BASHBOT_EVENT_SEND
|
||||||
event_send() {
|
event_send() {
|
||||||
# max recursion level 5 to avoid fork bombs
|
# max recursion level 5 to avoid fork bombs
|
||||||
(( EVENT_SEND++ )); [ "${EVENT_SEND}" -gt "5" ] && return
|
(( EVENT_SEND++ )); [ "${EVENT_SEND}" -gt "5" ] && return
|
||||||
@ -743,364 +675,6 @@ event_send() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
EVENT_TIMER="0"
|
|
||||||
event_timer() {
|
|
||||||
local key timer debug="$1"
|
|
||||||
(( EVENT_TIMER++ ))
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_TIMER[@]}"
|
|
||||||
do
|
|
||||||
timer="${key##*,}"
|
|
||||||
[[ ! "${timer}" =~ ^-*[1-9][0-9]*$ ]] && continue
|
|
||||||
if [ "$(( EVENT_TIMER % timer ))" = "0" ]; then
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_TIMER[${key}]}" "timer" "${key}" "${debug}"
|
|
||||||
[ "$(( EVENT_TIMER % timer ))" -lt "0" ] && \
|
|
||||||
unset BASHBOT_EVENT_TIMER["${key}"]
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
event_inline() {
|
|
||||||
local key debug="$1"
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_INLINE[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_INLINE[${key}]}" "inline" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
event_message() {
|
|
||||||
local key debug="$1"
|
|
||||||
# ${MESSAEG[*]} event_message
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_MESSAGE[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_MESSAGE[${key}]}" "message" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
|
|
||||||
# ${TEXT[*]} event_text
|
|
||||||
if [ -n "${MESSAGE[0]}" ]; then
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_TEXT[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_TEXT[${key}]}" "text" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
|
|
||||||
# ${CMD[*]} event_cmd
|
|
||||||
if [ -n "${CMD[0]}" ]; then
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_CMD[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_CMD[${key}]}" "command" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
# ${REPLYTO[*]} event_replyto
|
|
||||||
if [ -n "${REPLYTO[UID]}" ]; then
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_REPLYTO[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_REPLYTO[${key}]}" "replyto" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ${FORWARD[*]} event_forward
|
|
||||||
if [ -n "${FORWARD[UID]}" ]; then
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_FORWARD[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function && "${BASHBOT_EVENT_FORWARD[${key}]}" "forward" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ${CONTACT[*]} event_contact
|
|
||||||
if [ -n "${CONTACT[FIRST_NAME]}" ]; then
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_CONTACT[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_CONTACT[${key}]}" "contact" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ${VENUE[*]} event_location
|
|
||||||
# ${LOCATION[*]} event_location
|
|
||||||
if [ -n "${LOCATION[LONGITUDE]}" ] || [ -n "${VENUE[TITLE]}" ]; then
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_LOCATION[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_LOCATION[${key}]}" "location" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ${URLS[*]} event_file
|
|
||||||
# NOTE: compare again #URLS -1 blanks!
|
|
||||||
if [[ "${URLS[*]}" != " " ]]; then
|
|
||||||
# shellcheck disable=SC2153
|
|
||||||
for key in "${!BASHBOT_EVENT_FILE[@]}"
|
|
||||||
do
|
|
||||||
_exec_if_function "${BASHBOT_EVENT_FILE[${key}]}" "file" "${key}" "${debug}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
|
||||||
pre_process_message(){
|
|
||||||
local num="$1"
|
|
||||||
# unset everything to not have old values
|
|
||||||
CMD=( ); iQUERY=( ); iBUTTON=(); MESSAGE=(); CHAT=(); USER=(); CONTACT=(); LOCATION=(); unset CAPTION
|
|
||||||
REPLYTO=( ); FORWARD=( ); URLS=(); VENUE=( ); SERVICE=( ); NEWMEMBER=( ); LEFTMEMBER=( ); PINNED=( ); MIGRATE=( )
|
|
||||||
iQUERY[ID]="${UPD["result,${num},inline_query,id"]}"
|
|
||||||
iBUTTON[ID]="${UPD["result,${num},callback_query,id"]}"
|
|
||||||
CHAT[ID]="${UPD["result,${num},message,chat,id"]}"
|
|
||||||
USER[ID]="${UPD["result,${num},message,from,id"]}"
|
|
||||||
[ -z "${CHAT[ID]}" ] && CHAT[ID]="${UPD["result,${num},edited_message,chat,id"]}"
|
|
||||||
[ -z "${USER[ID]}" ] && USER[ID]="${UPD["result,${num},edited_message,from,id"]}"
|
|
||||||
# always true
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
process_inline_query() {
|
|
||||||
local num="$1"
|
|
||||||
iQUERY[0]="$(JsonDecode "${UPD["result,${num},inline_query,query"]}")"
|
|
||||||
iQUERY[USER_ID]="${UPD["result,${num},inline_query,from,id"]}"
|
|
||||||
iQUERY[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,first_name"]}")"
|
|
||||||
iQUERY[LAST_NAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,last_name"]}")"
|
|
||||||
iQUERY[USERNAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,username"]}")"
|
|
||||||
# always true
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
process_inline_button() {
|
|
||||||
# debugging for impelemetation
|
|
||||||
local num="$1"
|
|
||||||
iBUTTON[DATA]="${UPD["result,${num},callback_query,data"]}"
|
|
||||||
iBUTTON[CHAT_ID]="${UPD["result,${num},callback_query,message,chat,id"]}"
|
|
||||||
iBUTTON[MESSAGE_ID]="${UPD["result,${num},callback_query,message,message_id"]}"
|
|
||||||
iBUTTON[MESSAGE]="$(JsonDecode "${UPD["result,${num},callback_query,message,text"]}")"
|
|
||||||
# XXX should we give back pressed button, all buttons or nothing?
|
|
||||||
iBUTTON[USER_ID]="${UPD["result,${num},callback_query,from,id"]}"
|
|
||||||
iBUTTON[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,first_name"]}")"
|
|
||||||
iBUTTON[LAST_NAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,last_name"]}")"
|
|
||||||
iBUTTON[USERNAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,username"]}")"
|
|
||||||
# always true
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
process_message() {
|
|
||||||
local num="$1"
|
|
||||||
# Message
|
|
||||||
MESSAGE[0]+="$(JsonDecode "${UPD["result,${num},message,text"]}" | sed 's|\\/|/|g')"
|
|
||||||
MESSAGE[ID]="${UPD["result,${num},message,message_id"]}"
|
|
||||||
|
|
||||||
# Chat ID is now parsed when update is received
|
|
||||||
CHAT[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,chat,last_name"]}")"
|
|
||||||
CHAT[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,chat,first_name"]}")"
|
|
||||||
CHAT[USERNAME]="$(JsonDecode "${UPD["result,${num},message,chat,username"]}")"
|
|
||||||
# set real name as username if empty
|
|
||||||
[ -z "${CHAT[USERNAME]}" ] && CHAT[USERNAME]="${CHAT[FIRST_NAME]} ${CHAT[LAST_NAME]}"
|
|
||||||
CHAT[TITLE]="$(JsonDecode "${UPD["result,${num},message,chat,title"]}")"
|
|
||||||
CHAT[TYPE]="$(JsonDecode "${UPD["result,${num},message,chat,type"]}")"
|
|
||||||
CHAT[ALL_ADMIN]="${UPD["result,${num},message,chat,all_members_are_administrators"]}"
|
|
||||||
|
|
||||||
# user ID is now parsed when update is received
|
|
||||||
USER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,first_name"]}")"
|
|
||||||
USER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,last_name"]}")"
|
|
||||||
USER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,from,username"]}")"
|
|
||||||
# set real name as username if empty
|
|
||||||
[ -z "${USER[USERNAME]}" ] && USER[USERNAME]="${USER[FIRST_NAME]} ${USER[LAST_NAME]}"
|
|
||||||
|
|
||||||
# in reply to message from
|
|
||||||
if [ -n "${UPD["result,${num},message,reply_to_message,from,id"]}" ]; then
|
|
||||||
REPLYTO[UID]="${UPD["result,${num},message,reply_to_message,from,id"]}"
|
|
||||||
REPLYTO[0]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,text"]}")"
|
|
||||||
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[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,last_name"]}")"
|
|
||||||
REPLYTO[USERNAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,username"]}")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# forwarded message from
|
|
||||||
if [ -n "${UPD["result,${num},message,forward_from,id"]}" ]; then
|
|
||||||
FORWARD[UID]="${UPD["result,${num},message,forward_from,id"]}"
|
|
||||||
FORWARD[ID]="${MESSAGE[ID]}" # same as message ID
|
|
||||||
FORWARD[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,first_name"]}")"
|
|
||||||
FORWARD[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,last_name"]}")"
|
|
||||||
FORWARD[USERNAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,username"]}")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# get file URL from telegram, check for any of them!
|
|
||||||
if grep -qs -e '\["result",'"${num}"',"message","[avpsd].*,"file_id"\]' <<<"${UPDATE}"; then
|
|
||||||
URLS[AUDIO]="$(get_file "${UPD["result,${num},message,audio,file_id"]}")"
|
|
||||||
URLS[DOCUMENT]="$(get_file "${UPD["result,${num},message,document,file_id"]}")"
|
|
||||||
URLS[PHOTO]="$(get_file "${UPD["result,${num},message,photo,0,file_id"]}")"
|
|
||||||
URLS[STICKER]="$(get_file "${UPD["result,${num},message,sticker,file_id"]}")"
|
|
||||||
URLS[VIDEO]="$(get_file "${UPD["result,${num},message,video,file_id"]}")"
|
|
||||||
URLS[VOICE]="$(get_file "${UPD["result,${num},message,voice,file_id"]}")"
|
|
||||||
fi
|
|
||||||
# Contact, must have phone_number
|
|
||||||
if [ -n "${UPD["result,${num},message,contact,phone_number"]}" ]; then
|
|
||||||
CONTACT[USER_ID]="$(JsonDecode "${UPD["result,${num},message,contact,user_id"]}")"
|
|
||||||
CONTACT[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,contact,first_name"]}")"
|
|
||||||
CONTACT[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,contact,last_name"]}")"
|
|
||||||
CONTACT[NUMBER]="${UPD["result,${num},message,contact,phone_number"]}"
|
|
||||||
CONTACT[VCARD]="${UPD["result,${num},message,contact,vcard"]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# venue, must have a position
|
|
||||||
if [ -n "${UPD["result,${num},message,venue,location,longitude"]}" ]; then
|
|
||||||
VENUE[TITLE]="$(JsonDecode "${UPD["result,${num},message,venue,title"]}")"
|
|
||||||
VENUE[ADDRESS]="$(JsonDecode "${UPD["result,${num},message,venue,address"]}")"
|
|
||||||
VENUE[LONGITUDE]="${UPD["result,${num},message,venue,location,longitude"]}"
|
|
||||||
VENUE[LATITUDE]="${UPD["result,${num},message,venue,location,latitude"]}"
|
|
||||||
VENUE[FOURSQUARE]="${UPD["result,${num},message,venue,foursquare_id"]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Caption
|
|
||||||
CAPTION="$(JsonDecode "${UPD["result,${num},message,caption"]}")"
|
|
||||||
|
|
||||||
# Location
|
|
||||||
LOCATION[LONGITUDE]="${UPD["result,${num},message,location,longitude"]}"
|
|
||||||
LOCATION[LATITUDE]="${UPD["result,${num},message,location,latitude"]}"
|
|
||||||
|
|
||||||
# service messages, group or channel only!
|
|
||||||
if [[ "${CHAT[ID]}" == "-"* ]] ; then
|
|
||||||
# new chat member
|
|
||||||
if [ -n "${UPD["result,${num},message,new_chat_member,id"]}" ]; then
|
|
||||||
SERVICE[NEWMEMBER]="${UPD["result,${num},message,new_chat_member,id"]}"
|
|
||||||
NEWMEMBER[ID]="${SERVICE[NEWMEMBER]}"
|
|
||||||
NEWMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,first_name"]}")"
|
|
||||||
NEWMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,last_name"]}")"
|
|
||||||
NEWMEMBER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,username"]}")"
|
|
||||||
NEWMEMBER[ISBOT]="${UPD["result,${num},message,new_chat_member,is_bot"]}"
|
|
||||||
[ -z "${MESSAGE[0]}" ] &&\
|
|
||||||
MESSAGE[0]="/_new_chat_member ${NEWMEMBER[ID]} ${NEWMEMBER[USERNAME]:=${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]}}"
|
|
||||||
fi
|
|
||||||
# left chat member
|
|
||||||
if [ -n "${UPD["result,${num},message,left_chat_member,id"]}" ]; then
|
|
||||||
SERVICE[LEFTMEMBER]="${UPD["result,${num},message,left_chat_member,id"]}"
|
|
||||||
LEFTMEMBER[ID]="${SERVICE[LEFTMEBER]}"
|
|
||||||
LEFTMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,first_name"]}")"
|
|
||||||
LEFTMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,last_name"]}")"
|
|
||||||
LEFTMEBER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,username"]}")"
|
|
||||||
LEFTMEMBER[ISBOT]="${UPD["result,${num},message,left_chat_member,is_bot"]}"
|
|
||||||
[ -z "${MESSAGE[0]}" ] &&\
|
|
||||||
MESSAGE[0]="/_left_chat_member ${LEFTMEMBER[ID]} ${LEFTMEMBER[USERNAME]:=${LEFTMEMBER[FIRST_NAME]} ${LEFTMEMBER[LAST_NAME]}}"
|
|
||||||
fi
|
|
||||||
# chat title / photo, check for any of them!
|
|
||||||
if grep -qs -e '\["result",'"${num}"',"message","new_chat_[tp]' <<<"${UPDATE}"; then
|
|
||||||
SERVICE[NEWTITLE]="$(JsonDecode "${UPD["result,${num},message,new_chat_title"]}")"
|
|
||||||
[ -z "${MESSAGE[0]}" ] && [ -n "${SERVICE[NEWTITLE]}" ] &&\
|
|
||||||
MESSAGE[0]="/_new_chat_title ${USER[ID]} ${SERVICE[NEWTITLE]}"
|
|
||||||
SERVICE[NEWPHOTO]="$(get_file "${UPD["result,${num},message,new_chat_photo,0,file_id"]}")"
|
|
||||||
[ -z "${MESSAGE[0]}" ] && [ -n "${SERVICE[NEWPHOTO]}" ] &&\
|
|
||||||
MESSAGE[0]="/_new_chat_photo ${USER[ID]} ${SERVICE[NEWPHOTO]}"
|
|
||||||
fi
|
|
||||||
# pinned message
|
|
||||||
if [ -n "${UPD["result,${num},message,pinned_message,message_id"]}" ]; then
|
|
||||||
SERVICE[PINNED]="${UPD["result,${num},message,pinned_message,message_id"]}"
|
|
||||||
PINNED[ID]="${SERVICE[PINNED]}"
|
|
||||||
PINNED[MESSAGE]="$(JsonDecode "${UPD["result,${num},message,pinned_message,text"]}")"
|
|
||||||
[ -z "${MESSAGE[0]}" ] &&\
|
|
||||||
MESSAGE[0]="/_new_pinned_message ${USER[ID]} ${PINNED[ID]} ${PINNED[MESSAGE]}"
|
|
||||||
fi
|
|
||||||
# migrate to super group
|
|
||||||
if [ -n "${UPD["result,${num},message,migrate_to_chat_id"]}" ]; then
|
|
||||||
MIGRATE[TO]="${UPD["result,${num},message,migrate_to_chat_id"]}"
|
|
||||||
MIGRATE[FROM]="${UPD["result,${num},message,migrate_from_chat_id"]}"
|
|
||||||
# CHAT is already migrated, so set new chat id
|
|
||||||
[ "${CHAT[ID]}" = "${MIGRATE[FROM]}" ] && CHAT[ID]="${MIGRATE[FROM]}"
|
|
||||||
SERVICE[MIGRATE]="${MIGRATE[FROM]} ${MIGRATE[TO]}"
|
|
||||||
[ -z "${MESSAGE[0]}" ] &&\
|
|
||||||
MESSAGE[0]="/_migrate_group ${SERVICE[MIGRATE]}"
|
|
||||||
fi
|
|
||||||
# set SERVICE to yes if a service message was received
|
|
||||||
[[ "${SERVICE[*]}" =~ ^[[:blank:]]*$ ]] || SERVICE[0]="yes"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# split message in command and args
|
|
||||||
[[ "${MESSAGE[0]}" == "/"* ]] && read -r CMD <<<"${MESSAGE[0]}" && CMD[0]="${CMD[0]%%@*}"
|
|
||||||
# everything went well
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#########################
|
|
||||||
# main get updates loop, should never terminate
|
|
||||||
declare -A BASHBOTBLOCKED
|
|
||||||
start_bot() {
|
|
||||||
local DEBUGMSG OFFSET=0
|
|
||||||
# adaptive sleep defaults
|
|
||||||
local nextsleep="100"
|
|
||||||
local stepsleep="${BASHBOT_SLEEP_STEP:-100}"
|
|
||||||
local maxsleep="${BASHBOT_SLEEP:-5000}"
|
|
||||||
# startup message
|
|
||||||
DEBUGMSG="Start BASHBOT updates in Mode \"${1:-normal}\" =========="
|
|
||||||
log_update "${DEBUGMSG}"
|
|
||||||
# redirect to Debug.log
|
|
||||||
[[ "$1" == *"debug" ]] && exec &>>"${DEBUGLOG}"
|
|
||||||
log_debug "${DEBUGMSG}"; DEBUGMSG="$1"
|
|
||||||
[[ "${DEBUGMSG}" == "xdebug"* ]] && set -x
|
|
||||||
# cleaup old pipes and empty logfiles
|
|
||||||
find "${DATADIR}" -type p -delete
|
|
||||||
find "${DATADIR}" -size 0 -name "*.log" -delete
|
|
||||||
# load addons on startup
|
|
||||||
for addons in "${ADDONDIR:-.}"/*.sh ; do
|
|
||||||
# shellcheck source=./modules/aliases.sh
|
|
||||||
[ -r "${addons}" ] && source "${addons}" "startbot" "${DEBUGMSG}"
|
|
||||||
done
|
|
||||||
# shellcheck source=./commands.sh
|
|
||||||
source "${COMMANDS}" "startbot"
|
|
||||||
# start timer events
|
|
||||||
if [ -n "${BASHBOT_START_TIMER}" ] ; then
|
|
||||||
# shellcheck disable=SC2064
|
|
||||||
trap "event_timer ${DEBUGMSG}" ALRM
|
|
||||||
start_timer &
|
|
||||||
# shellcheck disable=SC2064
|
|
||||||
trap "kill -9 $!; exit" EXIT INT HUP TERM QUIT
|
|
||||||
fi
|
|
||||||
# cleanup countfile on startup
|
|
||||||
jssh_deleteKeyDB "CLEAN_COUNTER_DATABASE_ON_STARTUP" "${COUNTFILE}"
|
|
||||||
[ -f "${COUNTFILE}.jssh.flock" ] && rm -f "${COUNTFILE}.jssh.flock"
|
|
||||||
# store start time and cleanup botconfig on startup
|
|
||||||
jssh_updateKeyDB "startup" "$(_date)" "${BOTCONFIG}"
|
|
||||||
[ -f "${BOTCONFIG}.jssh.flock" ] && rm -f "${BOTCONFIG}.jssh.flock"
|
|
||||||
# read blocked users
|
|
||||||
jssh_readDB_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
|
||||||
# inform botadmin about start
|
|
||||||
send_normal_message "$(getConfigKey "botadmin")" "Bot $(getConfigKey "botname") started ..." &
|
|
||||||
##########
|
|
||||||
# bot is ready, start processing updates ...
|
|
||||||
while true; do
|
|
||||||
# adaptive sleep in ms rounded to next 0.1 s
|
|
||||||
sleep "$(_round_float "${nextsleep}e-3" "1")"
|
|
||||||
# get next update
|
|
||||||
UPDATE="$(getJson "${URL}/getUpdates?offset=${OFFSET}" 2>/dev/null | "${JSONSHFILE}" -b -n 2>/dev/null | iconv -f utf-8 -t utf-8 -c)"
|
|
||||||
# did we get an response?
|
|
||||||
if [ -n "${UPDATE}" ]; then
|
|
||||||
# we got something, do processing
|
|
||||||
[ "${OFFSET}" = "-999" ] && [ "${nextsleep}" -gt "$((maxsleep*2))" ] &&\
|
|
||||||
log_error "Recovered from timeout/broken/no connection, continue with telegram updates"
|
|
||||||
# escape bash $ expansion bug
|
|
||||||
((nextsleep+= stepsleep , nextsleep= nextsleep>maxsleep ?maxsleep:nextsleep))
|
|
||||||
UPDATE="${UPDATE//$/\\$}"
|
|
||||||
# Offset
|
|
||||||
OFFSET="$(grep <<< "${UPDATE}" '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)"
|
|
||||||
((OFFSET++))
|
|
||||||
|
|
||||||
if [ "${OFFSET}" != "1" ]; then
|
|
||||||
nextsleep="100"
|
|
||||||
process_updates "${DEBUGMSG}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# oops, something bad happened, wait maxsleep*10
|
|
||||||
(( nextsleep=nextsleep*2 , nextsleep= nextsleep>maxsleep*10 ?maxsleep*10:nextsleep ))
|
|
||||||
# second time, report problem
|
|
||||||
if [ "${OFFSET}" = "-999" ]; then
|
|
||||||
log_error "Repeated timeout/broken/no connection on telegram update, sleep $(_round_float "${nextsleep}e-3")s"
|
|
||||||
# try to recover
|
|
||||||
if _is_function bashbotBlockRecover && [ -z "$(getJson "${ME_URL}")" ]; then
|
|
||||||
log_error "Try to recover, calling bashbotBlockRecover ..."
|
|
||||||
bashbotBlockRecover >>"${ERRORLOG}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
OFFSET="-999"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# fallback version, full version is in bin/bashbot_init.in.sh
|
# fallback version, full version is in bin/bashbot_init.in.sh
|
||||||
# initialize bot environment, user and permissions
|
# initialize bot environment, user and permissions
|
||||||
@ -1178,9 +752,9 @@ if [ -z "${SOURCE}" ]; then
|
|||||||
debug_checks "end outproc" "$@"
|
debug_checks "end outproc" "$@"
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
# finally starts the read update loop, internal use only1
|
# finally starts the read update loop, internal use only
|
||||||
"startbot" )
|
"startbot" )
|
||||||
start_bot "$2"
|
_exec_if_exist start_bot "$2"
|
||||||
debug_checks "end startbot" "$@"
|
debug_checks "end startbot" "$@"
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
@ -1221,6 +795,7 @@ if [ -z "${SOURCE}" ]; then
|
|||||||
|
|
||||||
# start bot as background job and check if bot is running
|
# start bot as background job and check if bot is running
|
||||||
"start")
|
"start")
|
||||||
|
if _is_function process_updates; then
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
SESSION="${ME:-_bot}-startbot"
|
SESSION="${ME:-_bot}-startbot"
|
||||||
BOTPID="$(proclist "${SESSION}")"
|
BOTPID="$(proclist "${SESSION}")"
|
||||||
@ -1229,6 +804,9 @@ if [ -z "${SOURCE}" ]; then
|
|||||||
nohup "${SCRIPT}" "startbot" "$2" "${SESSION}" &>/dev/null &
|
nohup "${SCRIPT}" "startbot" "$2" "${SESSION}" &>/dev/null &
|
||||||
printf "Session Name: %s\n" "${SESSION}"
|
printf "Session Name: %s\n" "${SESSION}"
|
||||||
sleep 1
|
sleep 1
|
||||||
|
else
|
||||||
|
printf "${ORANGE}Update processing disabled, bot can only send messages.${NN}"
|
||||||
|
fi
|
||||||
if [ -n "$(proclist "${SESSION}")" ]; then
|
if [ -n "$(proclist "${SESSION}")" ]; then
|
||||||
printf "${GREEN}Bot started successfully.${NN}"
|
printf "${GREEN}Bot started successfully.${NN}"
|
||||||
else
|
else
|
||||||
|
@ -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$$ v1.31-dev-13-g127cc85
|
#### $$VERSION$$ v1.40-dev-3-g7c74824
|
||||||
#
|
#
|
||||||
# source from commands.sh to use jsonDB functions
|
# source from commands.sh to use jsonDB functions
|
||||||
#
|
#
|
||||||
|
446
modules/processUpdates.sh
Normal file
446
modules/processUpdates.sh
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
##################################################################
|
||||||
|
#
|
||||||
|
# File: processUpdates.sh
|
||||||
|
# Note: DO NOT EDIT! this file will be overwritten on update
|
||||||
|
#
|
||||||
|
#### $$VERSION$$ v1.40-dev-3-g7c74824
|
||||||
|
##################################################################
|
||||||
|
|
||||||
|
################
|
||||||
|
# processing of updates starts here
|
||||||
|
process_updates() {
|
||||||
|
local max num debug="$1"
|
||||||
|
max="$(grep -F ',"update_id"]' <<< "${UPDATE}" | tail -1 | cut -d , -f 2 )"
|
||||||
|
Json2Array 'UPD' <<<"${UPDATE}"
|
||||||
|
for ((num=0; num<=max; num++)); do
|
||||||
|
process_client "${num}" "${debug}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
process_client() {
|
||||||
|
local num="$1" debug="$2"
|
||||||
|
pre_process_message "${num}"
|
||||||
|
# log message on debug
|
||||||
|
[[ -n "${debug}" ]] && log_message "New Message ==========\n$(grep -F '["result",'"${num}" <<<"${UPDATE}")"
|
||||||
|
|
||||||
|
# check for users / groups to ignore
|
||||||
|
jssh_updateArray_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
||||||
|
[ -n "${USER[ID]}" ] && [[ -n "${BASHBOTBLOCKED[${USER[ID]}]}" || -n "${BASHBOTBLOCKED[${CHAT[ID]}]}" ]] && return
|
||||||
|
|
||||||
|
# process per message type
|
||||||
|
if [ -n "${iQUERY[ID]}" ]; then
|
||||||
|
process_inline_query "${num}" "${debug}"
|
||||||
|
printf "%(%c)T: Inline Query update received FROM=%s iQUERY=%s\n" -1\
|
||||||
|
"${iQUERY[USERNAME]:0:20} (${iQUERY[USER_ID]})" "${iQUERY[0]}" >>"${UPDATELOG}"
|
||||||
|
elif [ -n "${iBUTTON[ID]}" ]; then
|
||||||
|
process_inline_button "${num}" "${debug}"
|
||||||
|
printf "%(%c)T: Inline Button update received FROM=%s CHAT=%s CALLBACK=%s DATA:%s \n" -1\
|
||||||
|
"${iBUTTON[USERNAME]:0:20} (${iBUTTON[USER_ID]})" "${iBUTTON[CHAT_ID]}" "${iBUTTON[ID]}" "${iBUTTON[DATA]}" >>"${UPDATELOG}"
|
||||||
|
else
|
||||||
|
if grep -qs -e '\["result",'"${num}"',"edited_message"' <<<"${UPDATE}"; then
|
||||||
|
# edited message
|
||||||
|
UPDATE="${UPDATE//,${num},\"edited_message\",/,${num},\"message\",}"
|
||||||
|
Json2Array 'UPD' <<<"${UPDATE}"
|
||||||
|
MESSAGE[0]="/_edited_message "
|
||||||
|
fi
|
||||||
|
process_message "${num}" "${debug}"
|
||||||
|
printf "%(%c)T: update received FROM=%s CHAT=%s CMD=%s\n" -1 "${USER[USERNAME]:0:20} (${USER[ID]})"\
|
||||||
|
"${CHAT[USERNAME]:0:20}${CHAT[TITLE]:0:30} (${CHAT[ID]})"\
|
||||||
|
"${MESSAGE:0:30}${CAPTION:0:30}${URLS[*]:0:30}" >>"${UPDATELOG}"
|
||||||
|
fi
|
||||||
|
#####
|
||||||
|
# process inline and message events
|
||||||
|
# first classic command dispatcher
|
||||||
|
# shellcheck disable=SC2153,SC1090
|
||||||
|
{ source "${COMMANDS}" "${debug}"; } &
|
||||||
|
|
||||||
|
# then all registered addons
|
||||||
|
if [ -z "${iQUERY[ID]}" ]; then
|
||||||
|
event_message "${debug}"
|
||||||
|
else
|
||||||
|
event_inline "${debug}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# last count users
|
||||||
|
jssh_countKeyDB_async "${CHAT[ID]}" "${COUNTFILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
pre_process_message(){
|
||||||
|
local num="$1"
|
||||||
|
# unset everything to not have old values
|
||||||
|
CMD=( ); iQUERY=( ); iBUTTON=(); MESSAGE=(); CHAT=(); USER=(); CONTACT=(); LOCATION=(); unset CAPTION
|
||||||
|
REPLYTO=( ); FORWARD=( ); URLS=(); VENUE=( ); SERVICE=( ); NEWMEMBER=( ); LEFTMEMBER=( ); PINNED=( ); MIGRATE=( )
|
||||||
|
iQUERY[ID]="${UPD["result,${num},inline_query,id"]}"
|
||||||
|
iBUTTON[ID]="${UPD["result,${num},callback_query,id"]}"
|
||||||
|
CHAT[ID]="${UPD["result,${num},message,chat,id"]}"
|
||||||
|
USER[ID]="${UPD["result,${num},message,from,id"]}"
|
||||||
|
[ -z "${CHAT[ID]}" ] && CHAT[ID]="${UPD["result,${num},edited_message,chat,id"]}"
|
||||||
|
[ -z "${USER[ID]}" ] && USER[ID]="${UPD["result,${num},edited_message,from,id"]}"
|
||||||
|
# always true
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
process_inline_query() {
|
||||||
|
local num="$1"
|
||||||
|
iQUERY[0]="$(JsonDecode "${UPD["result,${num},inline_query,query"]}")"
|
||||||
|
iQUERY[USER_ID]="${UPD["result,${num},inline_query,from,id"]}"
|
||||||
|
iQUERY[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,first_name"]}")"
|
||||||
|
iQUERY[LAST_NAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,last_name"]}")"
|
||||||
|
iQUERY[USERNAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,username"]}")"
|
||||||
|
# always true
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
process_inline_button() {
|
||||||
|
# debugging for impelemetation
|
||||||
|
local num="$1"
|
||||||
|
iBUTTON[DATA]="${UPD["result,${num},callback_query,data"]}"
|
||||||
|
iBUTTON[CHAT_ID]="${UPD["result,${num},callback_query,message,chat,id"]}"
|
||||||
|
iBUTTON[MESSAGE_ID]="${UPD["result,${num},callback_query,message,message_id"]}"
|
||||||
|
iBUTTON[MESSAGE]="$(JsonDecode "${UPD["result,${num},callback_query,message,text"]}")"
|
||||||
|
# XXX should we give back pressed button, all buttons or nothing?
|
||||||
|
iBUTTON[USER_ID]="${UPD["result,${num},callback_query,from,id"]}"
|
||||||
|
iBUTTON[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,first_name"]}")"
|
||||||
|
iBUTTON[LAST_NAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,last_name"]}")"
|
||||||
|
iBUTTON[USERNAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,username"]}")"
|
||||||
|
# always true
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
process_message() {
|
||||||
|
local num="$1"
|
||||||
|
# Message
|
||||||
|
MESSAGE[0]+="$(JsonDecode "${UPD["result,${num},message,text"]}" | sed 's|\\/|/|g')"
|
||||||
|
MESSAGE[ID]="${UPD["result,${num},message,message_id"]}"
|
||||||
|
|
||||||
|
# Chat ID is now parsed when update is received
|
||||||
|
CHAT[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,chat,last_name"]}")"
|
||||||
|
CHAT[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,chat,first_name"]}")"
|
||||||
|
CHAT[USERNAME]="$(JsonDecode "${UPD["result,${num},message,chat,username"]}")"
|
||||||
|
# set real name as username if empty
|
||||||
|
[ -z "${CHAT[USERNAME]}" ] && CHAT[USERNAME]="${CHAT[FIRST_NAME]} ${CHAT[LAST_NAME]}"
|
||||||
|
CHAT[TITLE]="$(JsonDecode "${UPD["result,${num},message,chat,title"]}")"
|
||||||
|
CHAT[TYPE]="$(JsonDecode "${UPD["result,${num},message,chat,type"]}")"
|
||||||
|
CHAT[ALL_ADMIN]="${UPD["result,${num},message,chat,all_members_are_administrators"]}"
|
||||||
|
|
||||||
|
# user ID is now parsed when update is received
|
||||||
|
USER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,first_name"]}")"
|
||||||
|
USER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,last_name"]}")"
|
||||||
|
USER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,from,username"]}")"
|
||||||
|
# set real name as username if empty
|
||||||
|
[ -z "${USER[USERNAME]}" ] && USER[USERNAME]="${USER[FIRST_NAME]} ${USER[LAST_NAME]}"
|
||||||
|
|
||||||
|
# in reply to message from
|
||||||
|
if [ -n "${UPD["result,${num},message,reply_to_message,from,id"]}" ]; then
|
||||||
|
REPLYTO[UID]="${UPD["result,${num},message,reply_to_message,from,id"]}"
|
||||||
|
REPLYTO[0]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,text"]}")"
|
||||||
|
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[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,last_name"]}")"
|
||||||
|
REPLYTO[USERNAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,username"]}")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# forwarded message from
|
||||||
|
if [ -n "${UPD["result,${num},message,forward_from,id"]}" ]; then
|
||||||
|
FORWARD[UID]="${UPD["result,${num},message,forward_from,id"]}"
|
||||||
|
FORWARD[ID]="${MESSAGE[ID]}" # same as message ID
|
||||||
|
FORWARD[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,first_name"]}")"
|
||||||
|
FORWARD[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,last_name"]}")"
|
||||||
|
FORWARD[USERNAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,username"]}")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# get file URL from telegram, check for any of them!
|
||||||
|
if grep -qs -e '\["result",'"${num}"',"message","[avpsd].*,"file_id"\]' <<<"${UPDATE}"; then
|
||||||
|
URLS[AUDIO]="$(get_file "${UPD["result,${num},message,audio,file_id"]}")"
|
||||||
|
URLS[DOCUMENT]="$(get_file "${UPD["result,${num},message,document,file_id"]}")"
|
||||||
|
URLS[PHOTO]="$(get_file "${UPD["result,${num},message,photo,0,file_id"]}")"
|
||||||
|
URLS[STICKER]="$(get_file "${UPD["result,${num},message,sticker,file_id"]}")"
|
||||||
|
URLS[VIDEO]="$(get_file "${UPD["result,${num},message,video,file_id"]}")"
|
||||||
|
URLS[VOICE]="$(get_file "${UPD["result,${num},message,voice,file_id"]}")"
|
||||||
|
fi
|
||||||
|
# Contact, must have phone_number
|
||||||
|
if [ -n "${UPD["result,${num},message,contact,phone_number"]}" ]; then
|
||||||
|
CONTACT[USER_ID]="$(JsonDecode "${UPD["result,${num},message,contact,user_id"]}")"
|
||||||
|
CONTACT[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,contact,first_name"]}")"
|
||||||
|
CONTACT[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,contact,last_name"]}")"
|
||||||
|
CONTACT[NUMBER]="${UPD["result,${num},message,contact,phone_number"]}"
|
||||||
|
CONTACT[VCARD]="${UPD["result,${num},message,contact,vcard"]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# venue, must have a position
|
||||||
|
if [ -n "${UPD["result,${num},message,venue,location,longitude"]}" ]; then
|
||||||
|
VENUE[TITLE]="$(JsonDecode "${UPD["result,${num},message,venue,title"]}")"
|
||||||
|
VENUE[ADDRESS]="$(JsonDecode "${UPD["result,${num},message,venue,address"]}")"
|
||||||
|
VENUE[LONGITUDE]="${UPD["result,${num},message,venue,location,longitude"]}"
|
||||||
|
VENUE[LATITUDE]="${UPD["result,${num},message,venue,location,latitude"]}"
|
||||||
|
VENUE[FOURSQUARE]="${UPD["result,${num},message,venue,foursquare_id"]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Caption
|
||||||
|
CAPTION="$(JsonDecode "${UPD["result,${num},message,caption"]}")"
|
||||||
|
|
||||||
|
# Location
|
||||||
|
LOCATION[LONGITUDE]="${UPD["result,${num},message,location,longitude"]}"
|
||||||
|
LOCATION[LATITUDE]="${UPD["result,${num},message,location,latitude"]}"
|
||||||
|
|
||||||
|
# service messages, group or channel only!
|
||||||
|
if [[ "${CHAT[ID]}" == "-"* ]] ; then
|
||||||
|
# new chat member
|
||||||
|
if [ -n "${UPD["result,${num},message,new_chat_member,id"]}" ]; then
|
||||||
|
SERVICE[NEWMEMBER]="${UPD["result,${num},message,new_chat_member,id"]}"
|
||||||
|
NEWMEMBER[ID]="${SERVICE[NEWMEMBER]}"
|
||||||
|
NEWMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,first_name"]}")"
|
||||||
|
NEWMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,last_name"]}")"
|
||||||
|
NEWMEMBER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,username"]}")"
|
||||||
|
NEWMEMBER[ISBOT]="${UPD["result,${num},message,new_chat_member,is_bot"]}"
|
||||||
|
[ -z "${MESSAGE[0]}" ] &&\
|
||||||
|
MESSAGE[0]="/_new_chat_member ${NEWMEMBER[ID]} ${NEWMEMBER[USERNAME]:=${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]}}"
|
||||||
|
fi
|
||||||
|
# left chat member
|
||||||
|
if [ -n "${UPD["result,${num},message,left_chat_member,id"]}" ]; then
|
||||||
|
SERVICE[LEFTMEMBER]="${UPD["result,${num},message,left_chat_member,id"]}"
|
||||||
|
LEFTMEMBER[ID]="${SERVICE[LEFTMEBER]}"
|
||||||
|
LEFTMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,first_name"]}")"
|
||||||
|
LEFTMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,last_name"]}")"
|
||||||
|
LEFTMEBER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,username"]}")"
|
||||||
|
LEFTMEMBER[ISBOT]="${UPD["result,${num},message,left_chat_member,is_bot"]}"
|
||||||
|
[ -z "${MESSAGE[0]}" ] &&\
|
||||||
|
MESSAGE[0]="/_left_chat_member ${LEFTMEMBER[ID]} ${LEFTMEMBER[USERNAME]:=${LEFTMEMBER[FIRST_NAME]} ${LEFTMEMBER[LAST_NAME]}}"
|
||||||
|
fi
|
||||||
|
# chat title / photo, check for any of them!
|
||||||
|
if grep -qs -e '\["result",'"${num}"',"message","new_chat_[tp]' <<<"${UPDATE}"; then
|
||||||
|
SERVICE[NEWTITLE]="$(JsonDecode "${UPD["result,${num},message,new_chat_title"]}")"
|
||||||
|
[ -z "${MESSAGE[0]}" ] && [ -n "${SERVICE[NEWTITLE]}" ] &&\
|
||||||
|
MESSAGE[0]="/_new_chat_title ${USER[ID]} ${SERVICE[NEWTITLE]}"
|
||||||
|
SERVICE[NEWPHOTO]="$(get_file "${UPD["result,${num},message,new_chat_photo,0,file_id"]}")"
|
||||||
|
[ -z "${MESSAGE[0]}" ] && [ -n "${SERVICE[NEWPHOTO]}" ] &&\
|
||||||
|
MESSAGE[0]="/_new_chat_photo ${USER[ID]} ${SERVICE[NEWPHOTO]}"
|
||||||
|
fi
|
||||||
|
# pinned message
|
||||||
|
if [ -n "${UPD["result,${num},message,pinned_message,message_id"]}" ]; then
|
||||||
|
SERVICE[PINNED]="${UPD["result,${num},message,pinned_message,message_id"]}"
|
||||||
|
PINNED[ID]="${SERVICE[PINNED]}"
|
||||||
|
PINNED[MESSAGE]="$(JsonDecode "${UPD["result,${num},message,pinned_message,text"]}")"
|
||||||
|
[ -z "${MESSAGE[0]}" ] &&\
|
||||||
|
MESSAGE[0]="/_new_pinned_message ${USER[ID]} ${PINNED[ID]} ${PINNED[MESSAGE]}"
|
||||||
|
fi
|
||||||
|
# migrate to super group
|
||||||
|
if [ -n "${UPD["result,${num},message,migrate_to_chat_id"]}" ]; then
|
||||||
|
MIGRATE[TO]="${UPD["result,${num},message,migrate_to_chat_id"]}"
|
||||||
|
MIGRATE[FROM]="${UPD["result,${num},message,migrate_from_chat_id"]}"
|
||||||
|
# CHAT is already migrated, so set new chat id
|
||||||
|
[ "${CHAT[ID]}" = "${MIGRATE[FROM]}" ] && CHAT[ID]="${MIGRATE[FROM]}"
|
||||||
|
SERVICE[MIGRATE]="${MIGRATE[FROM]} ${MIGRATE[TO]}"
|
||||||
|
[ -z "${MESSAGE[0]}" ] &&\
|
||||||
|
MESSAGE[0]="/_migrate_group ${SERVICE[MIGRATE]}"
|
||||||
|
fi
|
||||||
|
# set SERVICE to yes if a service message was received
|
||||||
|
[[ "${SERVICE[*]}" =~ ^[[:blank:]]*$ ]] || SERVICE[0]="yes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# split message in command and args
|
||||||
|
[[ "${MESSAGE[0]}" == "/"* ]] && read -r CMD <<<"${MESSAGE[0]}" && CMD[0]="${CMD[0]%%@*}"
|
||||||
|
# everything went well
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#########################
|
||||||
|
# main get updates loop, should never terminate
|
||||||
|
declare -A BASHBOTBLOCKED
|
||||||
|
start_bot() {
|
||||||
|
local DEBUGMSG OFFSET=0
|
||||||
|
# adaptive sleep defaults
|
||||||
|
local nextsleep="100"
|
||||||
|
local stepsleep="${BASHBOT_SLEEP_STEP:-100}"
|
||||||
|
local maxsleep="${BASHBOT_SLEEP:-5000}"
|
||||||
|
# startup message
|
||||||
|
DEBUGMSG="Start BASHBOT updates in Mode \"${1:-normal}\" =========="
|
||||||
|
log_update "${DEBUGMSG}"
|
||||||
|
# redirect to Debug.log
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
[[ "$1" == *"debug" ]] && exec &>>"${DEBUGLOG}"
|
||||||
|
log_debug "${DEBUGMSG}"; DEBUGMSG="$1"
|
||||||
|
[[ "${DEBUGMSG}" == "xdebug"* ]] && set -x
|
||||||
|
# cleaup old pipes and empty logfiles
|
||||||
|
find "${DATADIR}" -type p -delete
|
||||||
|
find "${DATADIR}" -size 0 -name "*.log" -delete
|
||||||
|
# load addons on startup
|
||||||
|
for addons in "${ADDONDIR:-.}"/*.sh ; do
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
[ -r "${addons}" ] && source "${addons}" "startbot" "${DEBUGMSG}"
|
||||||
|
done
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "${COMMANDS}" "startbot"
|
||||||
|
# start timer events
|
||||||
|
if [ -n "${BASHBOT_START_TIMER}" ] ; then
|
||||||
|
# shellcheck disable=SC2064
|
||||||
|
trap "event_timer ${DEBUGMSG}" ALRM
|
||||||
|
start_timer &
|
||||||
|
# shellcheck disable=SC2064
|
||||||
|
trap "kill -9 $!; exit" EXIT INT HUP TERM QUIT
|
||||||
|
fi
|
||||||
|
# cleanup countfile on startup
|
||||||
|
jssh_deleteKeyDB "CLEAN_COUNTER_DATABASE_ON_STARTUP" "${COUNTFILE}"
|
||||||
|
[ -f "${COUNTFILE}.jssh.flock" ] && rm -f "${COUNTFILE}.jssh.flock"
|
||||||
|
# store start time and cleanup botconfig on startup
|
||||||
|
jssh_updateKeyDB "startup" "$(_date)" "${BOTCONFIG}"
|
||||||
|
[ -f "${BOTCONFIG}.jssh.flock" ] && rm -f "${BOTCONFIG}.jssh.flock"
|
||||||
|
# read blocked users
|
||||||
|
jssh_readDB_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
||||||
|
# inform botadmin about start
|
||||||
|
send_normal_message "$(getConfigKey "botadmin")" "Bot $(getConfigKey "botname") started ..." &
|
||||||
|
##########
|
||||||
|
# bot is ready, start processing updates ...
|
||||||
|
while true; do
|
||||||
|
# adaptive sleep in ms rounded to next 0.1 s
|
||||||
|
sleep "$(_round_float "${nextsleep}e-3" "1")"
|
||||||
|
# get next update
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
UPDATE="$(getJson "${URL}/getUpdates?offset=${OFFSET}" 2>/dev/null | "${JSONSHFILE}" -b -n 2>/dev/null | iconv -f utf-8 -t utf-8 -c)"
|
||||||
|
# did we get an response?
|
||||||
|
if [ -n "${UPDATE}" ]; then
|
||||||
|
# we got something, do processing
|
||||||
|
[ "${OFFSET}" = "-999" ] && [ "${nextsleep}" -gt "$((maxsleep*2))" ] &&\
|
||||||
|
log_error "Recovered from timeout/broken/no connection, continue with telegram updates"
|
||||||
|
# escape bash $ expansion bug
|
||||||
|
((nextsleep+= stepsleep , nextsleep= nextsleep>maxsleep ?maxsleep:nextsleep))
|
||||||
|
UPDATE="${UPDATE//$/\\$}"
|
||||||
|
# Offset
|
||||||
|
OFFSET="$(grep <<< "${UPDATE}" '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)"
|
||||||
|
((OFFSET++))
|
||||||
|
|
||||||
|
if [ "${OFFSET}" != "1" ]; then
|
||||||
|
nextsleep="100"
|
||||||
|
process_updates "${DEBUGMSG}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# oops, something bad happened, wait maxsleep*10
|
||||||
|
(( nextsleep=nextsleep*2 , nextsleep= nextsleep>maxsleep*10 ?maxsleep*10:nextsleep ))
|
||||||
|
# second time, report problem
|
||||||
|
if [ "${OFFSET}" = "-999" ]; then
|
||||||
|
log_error "Repeated timeout/broken/no connection on telegram update, sleep $(_round_float "${nextsleep}e-3")s"
|
||||||
|
# try to recover
|
||||||
|
if _is_function bashbotBlockRecover && [ -z "$(getJson "${ME_URL}")" ]; then
|
||||||
|
log_error "Try to recover, calling bashbotBlockRecover ..."
|
||||||
|
bashbotBlockRecover >>"${ERRORLOG}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
OFFSET="-999"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
declare -Ax BASHBOT_EVENT_INLINE BASHBOT_EVENT_MESSAGE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLYTO BASHBOT_EVENT_FORWARD BASHBOT_EVENT_SEND
|
||||||
|
declare -Ax BASHBOT_EVENT_CONTACT BASHBOT_EVENT_LOCATION BASHBOT_EVENT_FILE BASHBOT_EVENT_TEXT BASHBOT_EVENT_TIMER BASHBOT_BLOCKED
|
||||||
|
|
||||||
|
start_timer(){
|
||||||
|
# send alarm every ~60 s
|
||||||
|
while :; do
|
||||||
|
sleep 59.5
|
||||||
|
kill -ALRM $$
|
||||||
|
done;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVENT_TIMER="0"
|
||||||
|
event_timer() {
|
||||||
|
local key timer debug="$1"
|
||||||
|
(( EVENT_TIMER++ ))
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_TIMER[@]}"
|
||||||
|
do
|
||||||
|
timer="${key##*,}"
|
||||||
|
[[ ! "${timer}" =~ ^-*[1-9][0-9]*$ ]] && continue
|
||||||
|
if [ "$(( EVENT_TIMER % timer ))" = "0" ]; then
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_TIMER[${key}]}" "timer" "${key}" "${debug}"
|
||||||
|
[ "$(( EVENT_TIMER % timer ))" -lt "0" ] && \
|
||||||
|
unset BASHBOT_EVENT_TIMER["${key}"]
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
event_inline() {
|
||||||
|
local key debug="$1"
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_INLINE[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_INLINE[${key}]}" "inline" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
event_message() {
|
||||||
|
local key debug="$1"
|
||||||
|
# ${MESSAEG[*]} event_message
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_MESSAGE[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_MESSAGE[${key}]}" "message" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# ${TEXT[*]} event_text
|
||||||
|
if [ -n "${MESSAGE[0]}" ]; then
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_TEXT[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_TEXT[${key}]}" "text" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# ${CMD[*]} event_cmd
|
||||||
|
if [ -n "${CMD[0]}" ]; then
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_CMD[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_CMD[${key}]}" "command" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# ${REPLYTO[*]} event_replyto
|
||||||
|
if [ -n "${REPLYTO[UID]}" ]; then
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_REPLYTO[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_REPLYTO[${key}]}" "replyto" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ${FORWARD[*]} event_forward
|
||||||
|
if [ -n "${FORWARD[UID]}" ]; then
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_FORWARD[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function && "${BASHBOT_EVENT_FORWARD[${key}]}" "forward" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ${CONTACT[*]} event_contact
|
||||||
|
if [ -n "${CONTACT[FIRST_NAME]}" ]; then
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_CONTACT[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_CONTACT[${key}]}" "contact" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ${VENUE[*]} event_location
|
||||||
|
# ${LOCATION[*]} event_location
|
||||||
|
if [ -n "${LOCATION[LONGITUDE]}" ] || [ -n "${VENUE[TITLE]}" ]; then
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_LOCATION[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_LOCATION[${key}]}" "location" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ${URLS[*]} event_file
|
||||||
|
# NOTE: compare again #URLS -1 blanks!
|
||||||
|
if [[ "${URLS[*]}" != " " ]]; then
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
for key in "${!BASHBOT_EVENT_FILE[@]}"
|
||||||
|
do
|
||||||
|
_exec_if_function "${BASHBOT_EVENT_FILE[${key}]}" "file" "${key}" "${debug}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user