#!/bin/bash # this is just a library # you will need to provide the following in the implementation: # 1. the api url with it's corresponding token as # api_url="api.telegram.org/bot[insert your api token]/" # pay attention to the trailing forward slash # 2. the bot id as # bot_id="[insert your bot_id]" # 3. the following files to read and write from # updates.txt # sentmessages.txt # callbacks.txt # pay attention to the trailing forward slash # 4. (optional) a directory for the bot's files as # bot_tmpdir="/some/path/" # pay attention to the trailing forward slash # IMPORTANT: this library is not asynchronous, only one message # is read at a time and is done so in order # IMPORTANT: this library uses the getUpdates method with # tcp_keepalive,NOT webhooks calc_offset() { local current="$(bc -l <<< "$(tail -n 1 "${bot_tmpdir}updates.txt" | \ grep -om1 "\"update_id\":[0-9]\+" | \ grep -om1 "[0-9]\+") + 1" 2>/dev/null)" [ ! -z "${current}" ] && printf "%d" "${current}" } getupd() { local offset="$(calc_offset)" local update="$(curl -sX GET --keepalive-time 300 "${api_url}getUpdates" -d "offset=${offset}" \ -d "limit=1" -d "timeout=300"\ | sed 's/{"ok":true,"result":\[\]}\|^{"ok":false.*\|^{"ok":true,"result":\[{\?//g;:a;N;$!ba;s/\n//g;s/}\]}$//g;')" printf "%s" ${update} [ ! -z "${update}" ] && printf "%s\n" "${update}" >> "${bot_tmpdir}updates.txt" } getmsg_id() { tail -n1 "${bot_tmpdir}${1}" | grep -om1\ "\"message\":{\"message_id\":[0-9]\+\|^\"message_id\":[0-9]\+" | grep -om1 "[0-9]\+" } getusr_id() { tail -n1 "${bot_tmpdir}${1}" | grep -om1\ "\"from\":{\"id\":[0-9]\+" | grep -om1 "[0-9]\+" } getchat_id() { tail -n1 "${bot_tmpdir}${1}" | grep -om1\ "\"chat\":{\"id\":-\?[0-9]\+" | grep -om1 "\-\?[0-9]\+" } utf-16-surrogate-pair-decode() { # shamelessly stolen from stackoverflow local out="$1" local remain="" local regexp='(.*)\\u[dD]([0-9a-fA-F]{3})\\u[dD]([0-9a-fA-F]{3})(.*)' while [[ "${out}" =~ $regexp ]] ; do # match 2 \udxxx hex values, calculate new U, then split and replace local W1="$(( ( 0xd${BASH_REMATCH[2]} & 0x3ff) <<10 ))" local W2="$(( 0xd${BASH_REMATCH[3]} & 0x3ff ))" U="$(( ( W1 | W2 ) + 0x10000 ))" remain="$(printf '\\U%8.8x' "${U}")${BASH_REMATCH[4]}${remain}" out="${BASH_REMATCH[1]}" done echo -e "${out}${remain}" } gettext() { local text="$(tail -n 1 "${bot_tmpdir}${1}" | grep -om1\ '{\?\("text"\|"caption"\):"\(\\"\|[^"]*\)*"\(,\|}\)' | grep -v "^{" | tail -n1)" grep "^\"text\"" <<< "${text}" >/dev/null && utf-16-surrogate-pair-decode "${text:8:-2}"\ || { grep "^\"caption\"" <<< "${text}" >/dev/null && utf-16-surrogate-pair-decode "${text:11:-2}" } } getusr_name(){ local user_name="$(tail -n 1 "${bot_tmpdir}${1}" | grep -om1\ '"first_name":"\(\\"\|[^"]*\)*",\("username"\|"language_code"\)' | head -n1)" grep "\"username\"$" <<< "${user_name}" >/dev/null && utf-16-surrogate-pair-decode "${user_name:14:-12}"\ || { grep "\"language_code\"$" <<< "${user_name}" >/dev/null && utf-16-surrogate-pair-decode "${user_name:14:-17}" } } getusrname(){ local username="$(tail -n 1 "${bot_tmpdir}${1}" | grep -om1\ '"username":"\(\\"\|[^"]*\)*"\(,"language_code"\|},"chat"\)' | head -n1)" grep "\"language_code\"$" <<< "${username}" >/dev/null && utf-16-surrogate-pair-decode "${user_name:12:-17}"\ || { grep "},\"chat\"$" <<< "${username}" >/dev/null && utf-16-surrogate-pair-decode "${username:12:-9}" } } getchat_title(){ local chat_title="$(tail -n 1 "${bot_tmpdir}${1}" | grep -om1\ '"title":"\(\\"\|[^"]*\)*","type":"group"' | head -n1)" [ ! -z "${chat_title}" ] && utf-16-surrogate-pair-decode "${chat_title:9:-16}"\ || getusr_name "${1}" } get_cbks() { local callbacks="$(tail -n 1 "${bot_tmpdir}${1}"\ | grep "\"callback_query\"" | grep "\"callback_data\":\"recheck\"")" [ ! -z "${callbacks}" ] && is_callback=0 && printf "%s\n" "${callbacks}"\ >> "${bot_tmpdir}callbacks.txt" } sendmsg() { sentmsg="$(curl -sX GET "${api_url}sendMessage" -d "chat_id=${1}" \ -d "text=${2}" \ -d 'reply_markup={"inline_keyboard":[[{"text":"check again","callback_data":"recheck"}]]}')" \ && [ ! -z "${sentmsg}" ] && printf "%s\n" "${sentmsg}"\ | sed 's/^{"ok":false.*\|^{"ok":true,"result":{\|}$//g'\ >> "${bot_tmpdir}sentmsgs.txt" } replymsg() { sentmsg="$(curl -sX GET "${api_url}sendMessage" -d "chat_id=${curmsg[chat_id]}" -d "reply_to_message_id=${curmsg[message_id]}" \ -d "text=${curmsg[text]}" \ && [ ! -z "${sentmsg}" ] && printf "%s\n" "${sentmsg}"\ | sed 's/^{"ok":false.*\|^{"ok":true,"result":{\|}$//g'\ >> "${bot_tmpdir}sentmsgs.txt" } # TODO #editmsg() { # curl -sX GET "${api_url}editMessageText" -d "chat_id=${1}" -d "message_id=${2}" \ # -d "text=${3}" #} # #delmsg() { # curl -sX GET "${api_url}deleteMessage" -d "chat_id=${1}"\ # -d "message_id=${2}" #} getmsg_content(){ local -n _REF="${1}" _REF[user_id]="$(getusr_id "${2}")" _REF[user_name]="$(getusr_name "${2}")" _REF[username]="$(getusrname "${2}")" _REF[chat_id]="$(getchat_id "${2}")" _REF[chat_title]="$(getchat_title "${2}")" _REF[msg_id]="$(getmsg_id "${2}")" _REF[text]="$(gettext "${2}")" }