bashbot-lib/README.md

8.6 KiB

bashbot-lib

bashbot-lib provides generic functionality for telegram bots made in bash

with this library you will be able to run a telegram bot with few dependencies

IMPORTANT: bashbot-lib uses the getUpdates method with tcp_keepalive, not webhooks

IMPORTANT: bashbot-lib is not made for asynchronous use, only one message is received at a time and is done so in order

[TOC2]

license

this program is licensed under the Affero GNU Public License v3, you can read the copy that comes along with this program or read it at gnu.org's website

dependencies

the following is all that's needed:

  • bash 4+
  • GNU coreutils (sed, grep, tail, head, etc.)
  • curl
  • a telegram API token

Bash 4+ is obligatory for this library to work as features introduced at this point are heavily used.

installation

drop it wherever you like, although I recommend either of these options:

  • copying the files to /usr/lib/bashbot-lib/
  • add it as a submodule in your project (git submodules are very annoying to deal with)
  • simply keep it in a subfolder in your project

usage

source the library, and optionally the viewer, in your bash shellscript

. /usr/lib/bashbot-lib/bashbot-lib.sh
. /usr/lib/bashbot-lib/viewer.sh

you will also need the following:

  • a variable named api_url with the following content (mind the trailing forward slash): api_url="https:/api.telegram.org/bot${YOUR_TOKEN_HERE}/"
  • the following files to read and write from: updates.txt sentmsgs.txt delmsgs.txt
    • these files must be placed in the same directory you run your bot from or in the directory defined in the following bullet poiint
  • (optional) a variable named bot_tmpdir with the following content (mind the trailing forward slash): bot_tmpdir="/some/directory/"
    • if you define this directory, it will hold the files from the previous bullet point
  • (optional) a bash associative array for use with the getmsg_content function: declare -A curmsg
  • (optional) I recommend adding the following at the beggining of your implementation to centralize error logs: exec 2>"${bot_tmpdir}error.log"

once you've got that set up, all that's left is using the functions provided to make your bot

getting updates

use the getupd function to request an update (singular) from telegram's servers, the output will be printed to updates.txt

if there is no updates for you, the connection will stall for 60 seconds waiting for one and return empty if there was none, this is done to minimize unnecesary network traffic; the code actually requests that the connection stay open for 300 seconds but telegram only does so for 60 anyways

with every update, getupd calculates the new offset required to request new updates after the last one so no repeated responses clutter updates.txt

getupd requires no additional arguments passed to it

reading message contents

use the getmsg_content function to parse the contents of a message and save them to a bash associative array

the getmsg_content receives two arguments:

  • the name (not a reference to) of a bash associative array
  • the filename of a file with telegram JSON responses formatted by this library's functions

IMPORANT: you must pass only the name of the associative array and not a reference to it

# wrong way
getmsg_content "${curmsg}" "updates.txt"
# right way
getmsg_content "curmsg" "updates.txt"

this is so because bash associative arrays can only be passed to functions as named references

the message is read from the last line of the file passed as second argument

the file will be either updates.txt or sentmsgs.txt most probably, although it will work with any file where the contents are telegram JSON responses formatted with this library's functions, so you can use it whoever you like in your implementation

the bash associative array will hold the following contents

key value
chat_id numbers, begins with - if it's a group
chat_title same as user_name if private message
user_id numbers, begins with - if it's a group
user_name may contain special symbols
username the user's @, may be empty
msg_id a number to reference this message
text may contain special symbols
callback callback_data, empty if there is none
timestamp timestamp in dd/mm/yy hh:mm format

if you sourced the viewer, you can view these contents with view_content "curmsg" where curmsg is the name of the bash associative array populated by getmsg_content

sending messages

use the sendmsg function to send messages and print the result to sentmsgs.txt

the sendmsg function takes up to three arguments

  • the chat_id of the chat to send the message to
  • the contents of the message (text only for this version, support for images and media will come in future versions)
  • (optional) an inline keyboard made with mkinline_kbd

IMPORTANT: you must URL % encode some special characters in the contents of the message or telegram won't accept them

# wrong way
sendmsg "${curmsg[chat_id]}" "message %% with ۖ special
characters"
# right way
sendmsg "${curmsg[chat_id]}" "message+%25%25+with+%E2%82%AC%C3%B1+special%0Acharacters"

replying to messages

use the replymsg function to reply to messages and print the result to sentmsgs.txt

the replymsg function takes up to four arguments:

  • the chat_id of the chat to send the message to
  • the msg_id of the message to reply to
  • the contents of the message (text only for this version, support for images and media will come in future versions)
  • (optional) an inline keyboard made with mkinline_kbd

the same warning about special characters done in the sending messages section applies

editing messages

use the replymsg function to edit messages and print the result to sentmsgs.txt

the editmsg function takes up to four arguments:

  • the chat_id of the chat to edit the message in
  • the msg_id of the message to edit
  • the new contents of the message (text only for this version, support for images and media will come in future versions)
  • (optional) an inline keyboard made with mkinline_kbd

note: the message content must differ from the current one

the same warning about special characters done in the sending messages section applies

deleting mesages

use the delmsg function to delete messages and print the result to delmsgs.txt

the delmsg function takes two arguments:

  • the chat_id of the chat where the message is
  • the msg_id of the message to delete

inline keyboards

use the mkinline_kbd function to make inline keyboards you can pass to the sendmsg, replymsg and editmsg functions

the mkinline_kbd function takes three arguments:

  • the name of a bash array with the ammount of columns in each row
  • the name of a bash array with the text to display in each button label
  • the name of a bash array with the callback_data each button label sends when pressed

the keyboard will have as many rows as there are members in the array of the first argument, and as many columns in each of them as the member says:

  • declare -a kbd_rows=( 1 ) will have 1 row with 1 column
  • declare -a kbd_rows=( 3 1 ) will have 2 rows, the first one with 3 columns and the second one with 1

the text and data are added in order left to right, up to down, on each column of the keyboard

this function may require an example to be better understood, so please take a look at the following

declare -a kbd_rows=( 1 3 3)
declare -a kbd_text=( "apple" "orange" "banana" "peach" "cherry" "pear" "lemon" )
declare -a kbd_data=( "red" "orange" "yellow" "orange" "red" "green" "yellow" )

mkinline_kbd "kbd_rows" "kbd_text" "kbd_data"

will result in

{"inline_keyboard":[[{"text":"apple","callback_data":"red"}],[{"text":"orange","callback_data":"orange"},{"text":"banana","callback_data":"yellow"},{"text":"peach","callback_data":"orange"}],[{"text":"cherry","callback_data":"red"},{"text":"pear","callback_data":"green"},{"text":"lemon","callback_data":"yellow"}]]}

if you use this with sendmsg, the keyboard will look like this

why are you blind

acknowledgements

bash manpage sed manpage grep manpage telegram bot api reference stackoverflow

bug-reporting

send me an email at celsochan@disroot.org with the contents of error.log and a description of your issue with reproduction steps if possible