From 28255be349404192be016c4dd17f22fe179c1eae Mon Sep 17 00:00:00 2001 From: celso Date: Tue, 21 Mar 2023 16:37:41 -0300 Subject: [PATCH] initial commit --- bashbot-lib.sh | 145 +++++++++++++++++++++++++++++++++++++++++++++++++ viewer.sh | 20 +++++++ 2 files changed, 165 insertions(+) create mode 100755 bashbot-lib.sh create mode 100755 viewer.sh diff --git a/bashbot-lib.sh b/bashbot-lib.sh new file mode 100755 index 0000000..bd6c8fc --- /dev/null +++ b/bashbot-lib.sh @@ -0,0 +1,145 @@ +#!/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}updates.txt" | grep -om1\ + "\"message\":{\"message_id\":[0-9]\+" | grep -om1 "[0-9]\+" +} + +getusr_id() { + tail -n1 "${bot_tmpdir}updates.txt" | grep -om1\ + "\"from\":{\"id\":[0-9]\+" | grep -om1 "[0-9]\+" +} + +getchat_id() { + tail -n1 "${bot_tmpdir}updates.txt" | 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}updates.txt" | grep -om1\ + '\("text"\|"caption"\):"\(\\"\|[^"]*\)*"\(,\|}\)' | 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}updates.txt" | 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}updates.txt" | grep -om1\ + '"username":"\(\\"\|[^"]*\)*","language_code"' | head -n1)" + utf-16-surrogate-pair-decode "${username:12:-17}" +} + +getchat_title(){ + local chat_title="$(tail -n 1 "${bot_tmpdir}updates.txt" | grep -om1\ + '"title":"\(\\"\|[^"]*\)*","type":"group"' | head -n1)" + [ ! -z "${chat_title}" ] && utf-16-surrogate-pair-decode "${chat_title:9:-16}"\ + || getusr_name +} + +get_cbks() { + local callbacks="$(tail -n 1 "${bot_tmpdir}updates.txt"\ + | 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)" + _REF[user_name]="$(getusr_name)" + _REF[username]="$(getusrname)" + _REF[chat_id]="$(getchat_id)" + _REF[chat_title]="$(getchat_title)" + _REF[msg_id]="$(getmsg_id)" + _REF[text]="$(gettext)" +} diff --git a/viewer.sh b/viewer.sh new file mode 100755 index 0000000..c62ce79 --- /dev/null +++ b/viewer.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# this is just a library +# you will need to provide the following in the implementation: +# 1. a bash associative array populated by the library's functions + +print_dashes(){ + term_cols="$(tput cols)" + for ((i = 0; i < "${term_cols}"; i++)); do + printf -- "-" + done +} + +view_content(){ + local -n _REF="${1}" + print_dashes; printf "\n" + for i in "${!_REF[@]}"; do + [ ! -z "${_REF[${i}]}" ] && printf "[%s] \t=\t%s\n" "${i}" "${_REF[${i}]}" + done +}