2019-05-12 15:51:52 +00:00
#!/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
2021-01-05 15:17:34 +00:00
#### $$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] } " ) (){ :; } "
2019-05-12 15:51:52 +00:00
# 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'
2019-05-12 15:51:52 +00:00
2020-12-13 15:23:03 +00:00
#
# send/edit message variants ------------------
#
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 message
2019-05-12 15:51:52 +00:00
send_normal_message( ) {
2021-01-05 15:17:34 +00:00
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
2021-01-05 15:17:34 +00:00
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 } "
2021-01-05 15:17:34 +00:00
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( ) {
2021-01-05 15:17:34 +00:00
_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( ) {
2021-01-05 15:17:34 +00:00
_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( ) {
2021-01-05 15:17:34 +00:00
_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( ) {
2021-01-05 15:17:34 +00:00
_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( ) {
2021-01-05 15:17:34 +00:00
_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( ) {
2021-01-05 15:17:34 +00:00
_markdownv2_message_url " $1 " " $3 " ',"message_id":' " $2 " ',"parse_mode":"markdownv2"' " ${ EDIT_URL } "
2019-05-12 15:51: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_html_message( ) {
2021-01-05 15:17:34 +00:00
_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( ) {
2021-01-05 15:17:34 +00:00
local text; text = " $( JsonEscape " $2 " ) "
2020-08-15 07:47:16 +00:00
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."
2020-05-20 13:18:23 +00:00
until [ -z " ${ text } " ] ; do
2021-01-05 15:17:34 +00:00
sendJson " $1 " '"text":"' " ${ text : 0 : 4096 } " '"' " $3 " '' " $4 "
2020-05-20 13:18:23 +00:00
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( ) {
2021-01-05 15:17:34 +00:00
local text; text = " $( JsonEscape " $2 " ) "
2020-08-15 07:47:16 +00:00
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."
2020-05-20 13:18:23 +00:00
# markdown v2 needs additional double escaping!
2021-01-04 22:08:09 +00:00
text = " $( sed -E -e 's|([_|~`>+=#{}()!.-])|\\\1|g' <<< " ${ text } " ) "
2019-05-12 15:51:52 +00:00
until [ -z " ${ text } " ] ; do
2021-01-05 15:17:34 +00:00
sendJson " $1 " '"text":"' " ${ text : 0 : 4096 } " '"' " $3 " '' " $4 "
2019-05-12 15:51:52 +00:00
text = " ${ text : 4096 } "
done
}
2020-12-13 15:23:03 +00:00
#
# send keyboard, buttons, files ---------------
#
2019-05-12 15:51:52 +00:00
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 message $3 keyboard
2019-05-12 15:51:52 +00:00
send_keyboard( ) {
if [ [ " $3 " != *'[' * ] ] ; then old_send_keyboard " ${ @ } " ; return ; fi
2020-08-15 07:47:16 +00:00
local text = '"text":"' "Keyboard:" '"'
2021-01-05 15:17:34 +00:00
if [ -n " $2 " ] ; then
text = " $( JsonEscape " $2 " ) "
2020-08-15 07:47:16 +00:00
text = '"text":"' " ${ text // $'\n' / \\ n } " '"'
fi
2020-05-14 18:33:30 +00:00
local one_time = ', "one_time_keyboard":true' && [ -n " $4 " ] && one_time = ""
2021-01-05 15:17:34 +00:00
sendJson " $1 " " ${ text } " ', "reply_markup": {"keyboard": [ ' " $3 " ' ] ' " ${ one_time } " '}' " ${ MSG_URL } "
# '"text":"$2", "reply_markup": {"keyboard": [ $3 ], "one_time_keyboard": true}'
2019-05-12 15:51:52 +00:00
}
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 message $3 remove
2019-05-12 15:51:52 +00:00
remove_keyboard( ) {
2020-08-15 07:47:16 +00:00
local text = '"text":"' "remove custom keyboard ..." '"'
2021-01-05 15:17:34 +00:00
if [ -n " $2 " ] ; then
text = " $( JsonEscape " $2 " ) "
2020-08-15 07:47:16 +00:00
text = '"text":"' " ${ text // $'\n' / \\ n } " '"'
fi
2021-01-05 15:17:34 +00:00
sendJson " $1 " " ${ text } " ', "reply_markup": {"remove_keyboard":true}' " ${ MSG_URL } "
2020-08-15 07:47:16 +00:00
# delete message if no message or $3 not empty
2021-01-05 15:17:34 +00:00
[ [ -z " $2 " || -n " $3 " ] ] && delete_message " $1 " " ${ BOTSENT [ID] } " "nolog"
2019-05-12 15:51:52 +00:00
#JSON='"text":"$2", "reply_markup": {"remove_keyboard":true}'
}
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 message $3 keyboard
2019-05-12 15:51:52 +00:00
send_inline_keyboard( ) {
2021-01-05 15:17:34 +00:00
local text; text = '"text":"' $( JsonEscape " $2 " ) '"' ; [ -z " $2 " ] && text = '"text":"' "Keyboard:" '"'
sendJson " $1 " " ${ text } " ', "reply_markup": {"inline_keyboard": [ ' " $3 " ' ]}' " ${ MSG_URL } "
2019-05-12 15:51:52 +00:00
# JSON='"text":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}'
}
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 message $3 button text $4 URL
2019-05-12 15:51:52 +00:00
send_button( ) {
2021-01-05 15:17:34 +00:00
send_inline_keyboard " $1 " " $2 " '[ {"text":"' " $( JsonEscape " $3 " ) " '", "url":"' " $4 " '"}]'
2019-05-12 15:51:52 +00:00
}
2020-06-26 06:26:52 +00:00
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( ) {
2021-01-05 15:17:34 +00:00
[ -z " $1 " ] && return 1
[ -z " $3 " ] && return 2 # minimum 2 files
local CHAT JSON IMAGE; CHAT = " $1 " ; shift
2020-06-26 06:26:52 +00:00
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"
2020-06-26 06:26:52 +00:00
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
2019-05-12 15:51:52 +00:00
mp3| flac)
2021-01-04 22:08:09 +00:00
CUR_URL = " ${ AUDIO_URL } "
2019-05-14 13:25:15 +00:00
WHAT = "audio"
STATUS = "upload_audio"
2019-05-12 15:51:52 +00:00
; ;
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 } "
2019-05-14 13:25:15 +00:00
WHAT = "photo"
STATUS = "upload_photo"
2019-05-12 15:51:52 +00:00
; ;
webp)
2021-01-04 22:08:09 +00:00
CUR_URL = " ${ STICKER_URL } "
2019-05-14 13:25:15 +00:00
WHAT = "sticker"
STATUS = "upload_photo"
2019-05-12 15:51:52 +00:00
; ;
mp4)
2021-01-04 22:08:09 +00:00
CUR_URL = " ${ VIDEO_URL } "
2019-05-14 13:25:15 +00:00
WHAT = "video"
STATUS = "upload_video"
2019-05-12 15:51:52 +00:00
; ;
ogg)
2021-01-04 22:08:09 +00:00
CUR_URL = " ${ VOICE_URL } "
2019-05-14 13:25:15 +00:00
WHAT = "voice"
STATUS = "upload_audio"
2019-05-12 15:51:52 +00:00
; ;
*)
2021-01-04 22:08:09 +00:00
CUR_URL = " ${ DOCUMENT_URL } "
2019-05-14 13:25:15 +00:00
WHAT = "document"
STATUS = "upload_document"
2019-05-12 15:51:52 +00:00
; ;
esac
2021-01-05 15:17:34 +00:00
send_action " $1 " " ${ STATUS } "
2020-12-24 19:02:01 +00:00
sendUpload " $1 " " ${ WHAT } " " ${ file } " " ${ CUR_URL } " " ${ text // \\ n / $'\n' } "
2019-05-12 15:51:52 +00:00
}
# 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( ) {
2020-05-14 18:33:30 +00:00
[ -z " $2 " ] && return
2021-01-05 15:17:34 +00:00
sendJson " $1 " '"action": "' " $2 " '"' " ${ ACTION_URL } " &
2019-05-12 15:51:52 +00:00
}
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 lat $3 long
2019-05-12 15:51:52 +00:00
send_location( ) {
2020-05-14 18:33:30 +00:00
[ -z " $3 " ] && return
2021-01-05 15:17:34 +00:00
sendJson " $1 " '"latitude": ' " $2 " ', "longitude": ' " $3 " '' " ${ LOCATION_URL } "
2019-05-12 15:51:52 +00:00
}
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 lat $3 long $4 title $5 address $6 foursquard id
2019-05-12 15:51:52 +00:00
send_venue( ) {
local add = ""
2020-05-14 18:33:30 +00:00
[ -z " $5 " ] && return
[ -n " $6 " ] && add = ', "foursquare_id": ' " $6 " ''
2021-01-05 15:17:34 +00:00
sendJson " $1 " '"latitude": ' " $2 " ', "longitude": ' " $3 " ', "address": "' " $5 " '", "title": "' " $4 " '"' " ${ add } " " ${ VENUE_URL } "
2019-05-12 15:51:52 +00:00
}
2020-12-13 15:23:03 +00:00
#
# other send message variants ---------------------------------
#
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 from chat $3 from msg id
2019-05-12 15:51:52 +00:00
forward_message( ) {
2020-05-14 18:33:30 +00:00
[ -z " $3 " ] && return
2021-01-05 15:17:34 +00:00
sendJson " $1 " '"from_chat_id": ' " $2 " ', "message_id": ' " $3 " '' " ${ FORWARD_URL } "
2019-05-12 15:51:52 +00:00
}
forward( ) { # backward compatibility
forward_message " $@ " || return
}
2020-08-15 07:47:16 +00:00
# $1 CHAT $2 bashbot formatted message, see manual advanced usage
2019-05-12 15:51:52 +00:00
send_message( ) {
2020-05-14 18:33:30 +00:00
[ -z " $2 " ] && return
2019-05-12 15:51:52 +00:00
local text keyboard btext burl no_keyboard file lat long title address sent
2021-01-05 15:17:34 +00:00
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 } "
2019-05-12 15:51:52 +00:00
[ " $3 " != "safe" ] && {
2021-01-05 15:17:34 +00:00
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.*//' ) "
2019-05-12 15:51:52 +00:00
}
2021-01-04 22:08:09 +00:00
if [ -n " ${ no_keyboard } " ] ; then
remove_keyboard " $1 " " ${ text } "
2019-05-12 15:51:52 +00:00
sent = y
fi
2021-01-04 22:08:09 +00:00
if [ -n " ${ keyboard } " ] ; then
if [ [ " ${ keyboard } " != *"[" * ] ] ; then # pre 0.60 style
2019-05-12 15:51:52 +00:00
keyboard = " [ ${ keyboard // \" \" / \" \] , \[ \" } ] "
fi
2021-01-04 22:08:09 +00:00
send_keyboard " $1 " " ${ text } " " ${ keyboard } "
2019-05-12 15:51:52 +00:00
sent = y
fi
2021-01-04 22:08:09 +00:00
if [ -n " ${ btext } " ] && [ -n " ${ burl } " ] ; then
send_button " $1 " " ${ text } " " ${ btext } " " ${ burl } "
2019-05-12 15:51:52 +00:00
sent = y
fi
2021-01-04 22:08:09 +00:00
if [ -n " ${ file } " ] ; then
send_file " $1 " " ${ file } " " ${ text } "
2019-05-12 15:51:52 +00:00
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 } "
2019-05-12 15:51:52 +00:00
else
2021-01-04 22:08:09 +00:00
send_location " $1 " " ${ lat } " " ${ long } "
2019-05-12 15:51:52 +00:00
fi
sent = y
fi
2021-01-04 22:08:09 +00:00
if [ " ${ sent } " != "y" ] ; then
send_text_mode " $1 " " ${ text } "
2019-05-12 15:51:52 +00:00
fi
}
2020-08-15 07:47:16 +00:00
# $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( ) {
2019-05-12 15:51:52 +00:00
case " $2 " in
2020-06-19 16:50:55 +00:00
'html_parse_mode' *)
2019-05-12 15:51:52 +00:00
send_html_message " $1 " " ${ 2 //html_parse_mode } "
; ;
2020-06-19 16:50:55 +00:00
'markdown_parse_mode' *)
2019-05-12 15:51:52 +00:00
send_markdown_message " $1 " " ${ 2 //markdown_parse_mode } "
; ;
*)
send_normal_message " $1 " " $2 "
; ;
esac
}