161 lines
8.0 KiB
Markdown
161 lines
8.0 KiB
Markdown
|
# bashbot-lib
|
||
|
bashbot-lib provides generic functionality for telegram bots made in bash<br>
|
||
|
with this library you will be able to run a telegram bot with few dependencies<br>
|
||
|
**IMPORTANT**: bashbot-lib uses the getUpdates method with tcp_keepalive, not webhooks<br>
|
||
|
**IMPORTANT**: bashbot-lib is not made for asynchronous use, only one message is received at a time and is done so in order<br>
|
||
|
|
||
|
## 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](http://www.gnu.org/licenses/agpl-3.0.html)
|
||
|
|
||
|
## 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 |
|
||
|
|
||
|
### 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](https://www.w3schools.com/tags/ref_urlencode.ASP) 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](./images/example1.png "example 1 image")
|