8.2 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
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 |
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)
- (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 columndeclare -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