telegram-bot-bash/modules/sendMessage.sh

359 lines
11 KiB
Bash
Raw Normal View History

#!/bin/bash
# file: modules/message.sh
# do not edit, this file will be overwritten on update
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#
2020-11-29 14:34:00 +00:00
# shellcheck disable=SC1117
#### $$VERSION$$ v1.25-dev-14-g2fe6d4b
2020-06-14 18:56:46 +00:00
# will be automatically sourced from bashbot
2020-05-14 17:47:37 +00:00
# source once magic, function named like file
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
# source from commands.sh to use the sendMessage functions
2021-01-04 22:08:09 +00:00
MSG_URL=${URL}'/sendMessage'
EDIT_URL=${URL}'/editMessageText'
PHO_URL=${URL}'/sendPhoto'
AUDIO_URL=${URL}'/sendAudio'
DOCUMENT_URL=${URL}'/sendDocument'
STICKER_URL=${URL}'/sendSticker'
VIDEO_URL=${URL}'/sendVideo'
VOICE_URL=${URL}'/sendVoice'
LOCATION_URL=${URL}'/sendLocation'
VENUE_URL=${URL}'/sendVenue'
ACTION_URL=${URL}'/sendChatAction'
FORWARD_URL=${URL}'/forwardMessage'
ALBUM_URL=${URL}'/sendMediaGroup'
2020-12-13 15:23:03 +00:00
#
# send/edit message variants ------------------
#
# $1 CHAT $2 message
send_normal_message() {
local len text; text="$(JsonEscape "$2")"
2020-12-13 16:19:52 +00:00
text="${text//$'\n'/\\n}"
until [ -z "${text}" ]; do
if [ "${#text}" -le 4096 ]; then
sendJson "$1" '"text":"'"${text}"'"' "${MSG_URL}"
2020-12-13 16:19:52 +00:00
break
else
len=4095
[ "${text:4095:2}" != "\n" ] &&\
len="${text:0:4096}" && len="${len%\\n*}" && len="${#len}"
sendJson "$1" '"text":"'"${text:0:${len}}"'"' "${MSG_URL}"
2020-12-13 16:19:52 +00:00
text="${text:$((len+2))}"
fi
done
2020-12-13 15:23:03 +00:00
}
# $1 CHAT $2 message
send_markdown_message() {
_format_message_url "$1" "$2" ',"parse_mode":"markdown"' "${MSG_URL}"
2020-12-13 15:23:03 +00:00
}
# $1 CHAT $2 message
send_markdownv2_message() {
_markdownv2_message_url "$1" "$2" ',"parse_mode":"markdownv2"' "${MSG_URL}"
2020-12-13 15:23:03 +00:00
}
# $1 CHAT $2 message
send_html_message() {
_format_message_url "$1" "$2" ',"parse_mode":"html"' "${MSG_URL}"
2020-12-13 15:23:03 +00:00
}
2020-12-13 16:19:52 +00:00
# $1 CHAT $2 msg-id $3 message
edit_normal_message() {
_format_message_url "$1" "$3" ',"message_id":'"$2"'' "${EDIT_URL}"
2020-12-13 16:19:52 +00:00
}
2020-12-13 15:23:03 +00:00
2020-12-13 16:25:44 +00:00
# $1 CHAT $2 msg-id $3 message
2020-12-13 16:19:52 +00:00
edit_markdown_message() {
_format_message_url "$1" "$3" ',"message_id":'"$2"',"parse_mode":"markdown"' "${EDIT_URL}"
2020-12-13 16:19:52 +00:00
}
2020-12-13 16:25:44 +00:00
# $1 CHAT $2 msg-id $3 message
2020-12-13 16:19:52 +00:00
edit_markdownv2_message() {
_markdownv2_message_url "$1" "$3" ',"message_id":'"$2"',"parse_mode":"markdownv2"' "${EDIT_URL}"
}
2020-12-13 16:25:44 +00:00
# $1 CHAT $2 msg-id $3 message
2020-12-13 16:19:52 +00:00
edit_html_message() {
_format_message_url "$1" "$3" ',"message_id":'"$2"',"parse_mode":"html"' "${EDIT_URL}"
2020-12-13 16:19:52 +00:00
}
2020-12-13 15:23:03 +00:00
# internal function, send/edit formatted message with parse_mode and URL
2020-12-13 16:19:52 +00:00
# $1 CHAT $2 message $3 action $4 URL
2020-12-13 17:25:46 +00:00
_format_message_url(){
local text; text="$(JsonEscape "$2")"
text="${text//$'\n'/\\n}"
2020-12-13 15:23:03 +00:00
[ "${#text}" -ge 4096 ] && log_error "Warning: html/markdown message longer than 4096 characters, message is rejected if formatting crosses 4096 border."
until [ -z "${text}" ]; do
sendJson "$1" '"text":"'"${text:0:4096}"'"'"$3"'' "$4"
text="${text:4096}"
done
}
2020-12-13 15:23:03 +00:00
# internal function, send/edit markdownv2 message with URL
2020-12-13 16:19:52 +00:00
# $1 CHAT $2 message $3 action $4 URL
2020-12-13 15:23:03 +00:00
_markdownv2_message_url() {
local text; text="$(JsonEscape "$2")"
text="${text//$'\n'/\\n}"
2020-12-13 15:23:03 +00:00
[ "${#text}" -ge 4096 ] && log_error "Warning: markdownv2 message longer than 4096 characters, message is rejected if formatting crosses 4096 border."
# markdown v2 needs additional double escaping!
2021-01-04 22:08:09 +00:00
text="$(sed -E -e 's|([_|~`>+=#{}()!.-])|\\\1|g' <<< "${text}")"
until [ -z "${text}" ]; do
sendJson "$1" '"text":"'"${text:0:4096}"'"'"$3"'' "$4"
text="${text:4096}"
done
}
2020-12-13 15:23:03 +00:00
#
# send keyboard, buttons, files ---------------
#
# $1 CHAT $2 message $3 keyboard
send_keyboard() {
if [[ "$3" != *'['* ]]; then old_send_keyboard "${@}"; return; fi
local text='"text":"'"Keyboard:"'"'
if [ -n "$2" ]; then
text="$(JsonEscape "$2")"
text='"text":"'"${text//$'\n'/\\n}"'"'
fi
local one_time=', "one_time_keyboard":true' && [ -n "$4" ] && one_time=""
sendJson "$1" "${text}"', "reply_markup": {"keyboard": [ '"$3"' ] '"${one_time}"'}' "${MSG_URL}"
# '"text":"$2", "reply_markup": {"keyboard": [ $3 ], "one_time_keyboard": true}'
}
# $1 CHAT $2 message $3 remove
remove_keyboard() {
local text='"text":"'"remove custom keyboard ..."'"'
if [ -n "$2" ]; then
text="$(JsonEscape "$2")"
text='"text":"'"${text//$'\n'/\\n}"'"'
fi
sendJson "$1" "${text}"', "reply_markup": {"remove_keyboard":true}' "${MSG_URL}"
# delete message if no message or $3 not empty
[[ -z "$2" || -n "$3" ]] && delete_message "$1" "${BOTSENT[ID]}" "nolog"
#JSON='"text":"$2", "reply_markup": {"remove_keyboard":true}'
}
# $1 CHAT $2 message $3 keyboard
send_inline_keyboard() {
local text; text='"text":"'$(JsonEscape "$2")'"'; [ -z "$2" ] && text='"text":"'"Keyboard:"'"'
sendJson "$1" "${text}"', "reply_markup": {"inline_keyboard": [ '"$3"' ]}' "${MSG_URL}"
# JSON='"text":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}'
}
# $1 CHAT $2 message $3 button text $4 URL
send_button() {
send_inline_keyboard "$1" "$2" '[ {"text":"'"$(JsonEscape "$3")"'", "url":"'"$4"'"}]'
}
if [ -z "${BASHBOT_WGET}" ] && _exists curl ; then
# there are no checks if URL or ID exists
# $1 chat $3 ... $n URL or ID
send_album(){
[ -z "$1" ] && return 1
[ -z "$3" ] && return 2 # minimum 2 files
local CHAT JSON IMAGE; CHAT="$1"; shift
for IMAGE in "$@"
do
[ -n "${JSON}" ] && JSON+=","
JSON+='{"type":"photo","media":"'${IMAGE}'"}'
done
# shellcheck disable=SC2086
res="$("${BASHBOT_CURL}" -s -k ${BASHBOT_CURL_ARGS} "${ALBUM_URL}" -F "chat_id=${CHAT}"\
-F "media=[${JSON}]" | "${JSONSHFILE}" -s -b -n 2>/dev/null )"
sendJsonResult "${res}" "send_album (curl)" "${CHAT}" "$@"
[[ -z "${SOURCE}" && -n "${BASHBOT_EVENT_SEND[*]}" ]] && event_send "album" "$@" &
}
else
send_album(){
2020-06-27 10:49:20 +00:00
log_error "Sorry, wget Album upload not yet implemented"
BOTSENT[OK]="false"
[[ -z "${SOURCE}" && -n "${BASHBOT_EVENT_SEND[*]}" ]] && event_send "album" "$@" &
}
fi
2020-12-28 12:09:28 +00:00
UPLOADDIR="${BASHBOT_UPLOAD:-${DATADIR}/upload}"
# for now this can only send local files with curl!
# extend to allow send files by URL or telegram ID
send_file() {
local err
upload_file "${@}"; err="$?"
# fake Telegram response to provide error
if [ "${err}" != "0" ]; then
BOTSENT=()
BOTSENT[OK]="false"
2021-01-04 22:08:09 +00:00
case "${err}" in
2020-12-28 12:09:28 +00:00
1) BOTSENT[ERROR]="Path to file $2 contains to much '../' or starts with '.'";;
2) BOTSENT[ERROR]="Path to file $2 does not match regex: ${FILE_REGEX} ";;
3) if [[ "$2" == "/"* ]];then
BOTSENT[ERROR]="File not found: $2"
else
BOTSENT[ERROR]="File not found: ${UPLOADDIR}/$2"
fi;;
esac
[ -n "${BASHBOTDEBUG}" ] && log_message "Error in upload_file: ${BOTSENT[ERROR]}"
fi
}
2019-05-20 15:26:21 +00:00
upload_file(){
2020-12-24 17:20:39 +00:00
local CUR_URL WHAT STATUS text=$3 file="$2"
2019-05-13 10:47:03 +00:00
# file access checks ...
2021-01-04 22:08:09 +00:00
[[ "${file}" = *'..'* ]] && return 1 # no directory traversal
[[ "${file}" = '.'* ]] && return 1 # no hidden or relative files
if [[ "${file}" = '/'* ]] ; then
[[ ! "${file}" =~ ${FILE_REGEX} ]] && return 2 # absolute must match REGEX
2019-05-13 10:47:03 +00:00
else
file="${UPLOADDIR:-NOUPLOADDIR}/${file}" # othiers must be in UPLOADDIR
fi
2021-01-04 22:08:09 +00:00
[ ! -r "${file}" ] && return 3 # and file must exits of course
2019-05-13 10:47:03 +00:00
2021-01-04 22:08:09 +00:00
case "${file##*.}" in
mp3|flac)
2021-01-04 22:08:09 +00:00
CUR_URL="${AUDIO_URL}"
WHAT="audio"
STATUS="upload_audio"
;;
2020-05-14 11:04:57 +00:00
png|jpg|jpeg|gif|pic)
2021-01-04 22:08:09 +00:00
CUR_URL="${PHO_URL}"
WHAT="photo"
STATUS="upload_photo"
;;
webp)
2021-01-04 22:08:09 +00:00
CUR_URL="${STICKER_URL}"
WHAT="sticker"
STATUS="upload_photo"
;;
mp4)
2021-01-04 22:08:09 +00:00
CUR_URL="${VIDEO_URL}"
WHAT="video"
STATUS="upload_video"
;;
ogg)
2021-01-04 22:08:09 +00:00
CUR_URL="${VOICE_URL}"
WHAT="voice"
STATUS="upload_audio"
;;
*)
2021-01-04 22:08:09 +00:00
CUR_URL="${DOCUMENT_URL}"
WHAT="document"
STATUS="upload_document"
;;
esac
send_action "$1" "${STATUS}"
2020-12-24 19:02:01 +00:00
sendUpload "$1" "${WHAT}" "${file}" "${CUR_URL}" "${text//\\n/$'\n'}"
}
# typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_audio or upload_audio for audio files, upload_document for general files, find_location for location
send_action() {
[ -z "$2" ] && return
sendJson "$1" '"action": "'"$2"'"' "${ACTION_URL}" &
}
# $1 CHAT $2 lat $3 long
send_location() {
[ -z "$3" ] && return
sendJson "$1" '"latitude": '"$2"', "longitude": '"$3"'' "${LOCATION_URL}"
}
# $1 CHAT $2 lat $3 long $4 title $5 address $6 foursquard id
send_venue() {
local add=""
[ -z "$5" ] && return
[ -n "$6" ] && add=', "foursquare_id": '"$6"''
sendJson "$1" '"latitude": '"$2"', "longitude": '"$3"', "address": "'"$5"'", "title": "'"$4"'"'"${add}" "${VENUE_URL}"
}
2020-12-13 15:23:03 +00:00
#
# other send message variants ---------------------------------
#
# $1 CHAT $2 from chat $3 from msg id
forward_message() {
[ -z "$3" ] && return
sendJson "$1" '"from_chat_id": '"$2"', "message_id": '"$3"'' "${FORWARD_URL}"
}
forward() { # backward compatibility
forward_message "$@" || return
}
# $1 CHAT $2 bashbot formatted message, see manual advanced usage
send_message() {
[ -z "$2" ] && return
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')"
2020-06-20 11:19:45 +00:00
#shellcheck disable=SC2001
2020-12-24 17:20:39 +00:00
text="$(sed <<< "${text}" 's/ *mynewlinestartshere */\n/g')"
2020-12-25 19:08:29 +00:00
text="${text//$'\n'/\\n}"
[ "$3" != "safe" ] && {
no_keyboard="$(sed <<< "$2" '/mykeyboardendshere/!d;s/.*mykeyboardendshere.*/mykeyboardendshere/')"
keyboard="$(sed <<< "$2" '/mykeyboardstartshere /!d;s/.*mykeyboardstartshere *//;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
btext="$(sed <<< "$2" '/mybtextstartshere /!d;s/.*mybtextstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
burl="$(sed <<< "$2" '/myburlstartshere /!d;s/.*myburlstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//g;s/ *mykeyboardendshere.*//g')"
file="$(sed <<< "$2" '/myfile[^s]*startshere /!d;s/.*myfile[^s]*startshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
lat="$(sed <<< "$2" '/mylatstartshere /!d;s/.*mylatstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
long="$(sed <<< "$2" '/mylongstartshere /!d;s/.*mylongstartshere //;s/ *my[nkfltab][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.*//')"
}
2021-01-04 22:08:09 +00:00
if [ -n "${no_keyboard}" ]; then
remove_keyboard "$1" "${text}"
sent=y
fi
2021-01-04 22:08:09 +00:00
if [ -n "${keyboard}" ]; then
if [[ "${keyboard}" != *"["* ]]; then # pre 0.60 style
keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]"
fi
2021-01-04 22:08:09 +00:00
send_keyboard "$1" "${text}" "${keyboard}"
sent=y
fi
2021-01-04 22:08:09 +00:00
if [ -n "${btext}" ] && [ -n "${burl}" ]; then
send_button "$1" "${text}" "${btext}" "${burl}"
sent=y
fi
2021-01-04 22:08:09 +00:00
if [ -n "${file}" ]; then
send_file "$1" "${file}" "${text}"
sent=y
fi
2021-01-04 22:08:09 +00:00
if [ -n "${lat}" ] && [ -n "${long}" ]; then
if [ -n "${address}" ] && [ -n "${title}" ]; then
send_venue "$1" "${lat}" "${long}" "${title}" "${address}"
else
2021-01-04 22:08:09 +00:00
send_location "$1" "${lat}" "${long}"
fi
sent=y
fi
2021-01-04 22:08:09 +00:00
if [ "${sent}" != "y" ];then
send_text_mode "$1" "${text}"
fi
}
# $1 CHAT $2 message starting possibly with html_parse_mode or markdown_parse_mode
# not working, fix or remove after 1.0!!
2020-12-29 10:02:28 +00:00
send_text_mode() {
case "$2" in
'html_parse_mode'*)
send_html_message "$1" "${2//html_parse_mode}"
;;
'markdown_parse_mode'*)
send_markdown_message "$1" "${2//markdown_parse_mode}"
;;
*)
send_normal_message "$1" "$2"
;;
esac
}