improve develop and event documentation

This commit is contained in:
Kay Marquardt (Gnadelwartz) 2019-06-06 16:04:42 +02:00
parent ce605551c9
commit a7769add6a
2 changed files with 121 additions and 82 deletions

View File

@ -274,8 +274,6 @@ fi
----
### Inline Queries - answer direct queries to bot
You must include ```source modules/inline.sh``` in 'commands.sh' to have the following functions availible.
Inline Queries allows users to interact with your bot directly without sending extra commands.
As an answer to an inline query you can send back one or more results to the Telegram client.
The Telegram client will then show the results to the user and let him select one.
@ -346,7 +344,8 @@ see [InlineQueryResult for more information](https://core.telegram.org/bots/api#
### Background and Interactive jobs
You must include ```source modules/background.sh``` in 'commands.sh' to have the following functions availible.
Background functions and interactive jobs extends the bot functionality to not only react to user input. You can start scripts for interative
chats and send messages based on time or other external events.
##### start_proc
```startproc``` starts a script, the output of the script is sent to the user or chat, user input will be sent back to the script. see [Advanced Usage](3_advanced.md#Interactive-Chats)
@ -453,53 +452,69 @@ Usually message is automatically forwarded in 'commands.sh', but you can forwar
*replaces:*' incproc
### JSON.sh DB
Since output of JSON.sh is so handy to use in bash, we provide a simple wrapper to read and write JSON.sh style data from and to files.
File name is prefixed with BASHBOT_ETC and the suffix '.jssh' is added to file name! File names must not contain '..'
### jsshDB
Since output generated by JSON.sh is so handy to use in bash, we use the format for a simple keys/value storage and providing
fucntions to read and write JSON.sh style data from and to files.
The file extions is '.jssh' and for security reasons location of jssh files is restricted to BASHBOT_ETC.
Note: File names containg '..' and absolute file names pointing outside BASHBOT_ETC are refused by jsshDB functions.
A 'jsshDB' file is a simple 'kay=value' storage.
*Example:* for file name:
```bash
# bashbot is installed in /usr/local/telegram-bot-bash, no BASHBOT_ETC set.
# bashbot is installed in /usr/local/telegram-bot-bash, BASHBOT_ETC is not set.
"myfile" -> /usr/local/telegram-bot-bash/myfile.jssh
"addons/myfile" -> /usr/local/telegram-bot-bash/addons/myfile.jssh
"${DATADIR}/myfile usr/local/telegram-bot-bash/data-bot-bash/myfile.jssh
"${DATADIR}/myfile" -> /usr/local/telegram-bot-bash/data-bot-bash/myfile.jssh
"/home/someuser/myfile" -> function returns false, nothing done.
```
You must include ```source modules/jsshDB.sh``` in 'commands.sh' to have the following functions availible.
##### jssh_newDB
Creats new empty jsshDB file if not exist.
*usage:* jssh_newDB "filename"
##### jssh_checkDB
Check if DB name respects the rules and returns the real/final path to DB file.
Check if DB name respects the rules mentioned above and returns the real/final path to DB file.
Used internally by all jssh DB functions, but can also used to get the real filename for a jssh DB.
*usage:* jssh_checkDB "filename"
```bash
if file=$(jssh_checkDB somename); then
echo "Final filename is ${file}"
else
echo "Something wrong with somename"
fi
# somename = data-bot-bash/somevalues
Final filename is data-bot-bash/somevalues.jssh
# somename = /home/someuser/myfile
Something wrong with /home/someuser/myfile
# somename = data-bot-bash/../../../somevalues
Something wrong with data-bot-bash/../../../somevalues
```
##### jssh_readDB
Read content of a .jssh file in JSON.sh format into given ARRAY. ARRAY name must be delared with "declare -A ARRAY" upfront,
Read content of a .jssh file in JSON.sh format into given ARRAY. ARRAY name must be delared with "declare -A ARRAY" before calling readDB.
*usage:* jssh_readDB "ARRAY" "filename"
*example:*
```bash
# read file data-bot-bash/somevalues.jssh into array SOMEVALUES
jssh_readDB "SOMEVALUES" "${DATADIR:-}/somevalues"
jssh_readDB "SOMEVALUES" "${DATADIR:-.}/somevalues"
print "${SOMEVALUES[*]}"
```
##### jssh_writeDB
Write content of given ARRAY into jsshDB file. ARRAY name must be delared with "declare -A ARRAY" upfront,
Write content of an ARRAY into jsshDB file. ARRAY name must be delared with "declare -A ARRAY" before calling writeDB.
"DB" file MUST exist or nothing is written.
Note: Every existing content is overwritten.
Note: Existing content is overwritten.
*usage:* jssh_writeDB "ARRAY" "filename"
@ -511,13 +526,13 @@ MYVALUES["loveit"]="value2"
MYVALUES["whynot"]="value3"
# create DB
jssh_newDB "${DATADIR:-}/myvalues"
jssh_newDB "${DATADIR:-.}/myvalues"
# write to file data-bot-bash/somevalues.jssh from array MYVALUES
jssh_writeDB "MYVALUES" "${DATADIR:-}/myvalues"
jssh_writeDB "MYVALUES" "${DATADIR:-.}/myvalues"
# show whats written
DBfile="$(jssh_checkDB "${DATADIR:-}/myvalues.jssh")"
DBfile="$(jssh_checkDB "${DATADIR:-.}/myvalues.jssh")"
cat "DB$file"
["value1"] "value1"
@ -527,10 +542,10 @@ cat "DB$file"
```
##### jssh_updateDB
Update/write content of given ARRAY into a jsshDB file. ARRAY name must be delared with "declare -A ARRAY" upfront,
Update/Add content of an ARRAY into a jsshDB file. ARRAY name must be delared with "declare -A ARRAY" before calling updateDB.
"DB" file MUST exist or nothing is written.
Note: Existing DB content not in ARRAY is kept.
Note: Existing content not in ARRAY is kept in file.
*usage:* jssh_updateDB "ARRAY" "filename"
@ -541,7 +556,7 @@ MYVALUES=()
MYVALUES["newvalue"]="this is new"
# update file data-bot-bash/somevalues.jssh from array MYVALUES
jssh_updateDB "MYVALUES" "${DATADIR:-}/myvalues"
jssh_updateDB "MYVALUES" "${DATADIR:-.}/myvalues"
# show whats written
["value1"] "value1"
@ -551,7 +566,7 @@ jssh_updateDB "MYVALUES" "${DATADIR:-}/myvalues"
# now writeDB
cat "$DBfile"
jssh_writeDB "MYVALUES" "${DATADIR:-}/myvalues"
jssh_writeDB "MYVALUES" "${DATADIR:-.}/myvalues"
# show whats written, ups!
cat "$DBfile"
@ -566,7 +581,7 @@ Insert, update, append a key=value pair to a jsshDB file, key name is only allow
*example:*
```bash
jssh_insertDB "newkey" "an other value" "${DATADIR:-}/myvalues"
jssh_insertDB "newkey" "an other value" "${DATADIR:-.}/myvalues"
```
##### jssh_getDB
@ -576,7 +591,7 @@ Read a key=value pair from a jsshDB file, key name is only allowed to contain '-
*example:*
```bash
result="$(jssh_getDB "newvalue" "${DATADIR:-}/myvalues")"
result="$(jssh_getDB "newvalue" "${DATADIR:-.}/myvalues")"
# lets see whats the value of key newvalue
echo "$result"
@ -586,7 +601,8 @@ this is new
----
### Aliases - shortcuts for often used funtions
You must include ```source modules/aliases.sh``` in 'commands.sh' to have the following functions availible.
Aliases are handy shortcuts for using in 'mycommands.sh', they avoid error prone typing of "${CHAT[ID]}" "${USER[ID]}" as much as possible.
Do not use them in bashbot.sh, modules and addons.
##### _is_botadmin
@ -864,5 +880,5 @@ The name of your bot is availible as bash variable "$ME", there is no need to ca
#### [Prev Best Practice](5_practice.md)
#### [Next Notes for Developers](7_develop.md)
#### $$VERSION$$ v0.91-6-g9b9125c
#### $$VERSION$$ v0.94-dev2-2-gce60555

View File

@ -1,70 +1,73 @@
#### [Home](../README.md)
## Notes for bashbot developers
This section is about help and best practices for new bashbot developers. The main focus on is creating new versions of bashbot, not on develop your individual bot. Nevertheless the rules and tools described here can also help you with your bot development.
This section is about help and best practices for new bashbot developers. The main focus on is creating new versions of bashbot, modules and addons, not on develop your individual bot. Nevertheless the information provided here should help your bot development also.
bashbot development is done on github. If you want to provide fixes or new features [fork bashbot on githup](https://help.github.com/en/articles/fork-a-repo) and provide changes as [pull request on github](https://help.github.com/en/articles/creating-a-pull-request).
If you want to provide fixes or new features [fork bashbot on githup](https://help.github.com/en/articles/fork-a-repo) and provide changes as [pull request on github](https://help.github.com/en/articles/creating-a-pull-request).
### Debugging Bashbot
In normal mode of operation all bashbot output is discarded.
To get these messages (and more) you can start bashbot in the current shell with ```./bashbot.sh startbot &```.
Now you can see all output or erros from bashbot.
In addition you can change the change the level of verbosity by adding a third argument after startbot.
Usually all bashbot output is discarded.
If you want to get error messages (and more) start bashbot in the current shell with ```./bashbot.sh startbot```.
In addition you can the change the level of verbosity by adding a 'debug' as third argument.
```
"debug" redirects all output to "DEBUG.log", in addtion every update is logged in "MESSAGE.LOG" and "INLINE.log"
"debugterm" same as debug but output and errors are sent to terminal
"debugx" debug output and errors are sent to terminal
"xdebugx" same as debugx plus set bash option '-x' to show any executed command
"xdebug" same as debug plus set bash option '-x' to log any executed command
"xdebugterm" same as xdebug but output and errors are sent to terminal
"debug" all output is redirected to "DEBUG.log", in addtion every incomming message is logged in "MESSAGE.LOG" and "INLINE.log"
"xdebug" same as debug plus set bash option '-x' to log any executed command in "DEBUG.log"
```
To stop bashhbot in debugging mode run ```ps -uf | grep debug``` and use 'kill -9' to kill all processes shwon.
To stop bashhbot in debugging mode press CRTL+C. If this does not stop bashbot or you run it in background execute ```ps -uf | grep debug``` and kill all shown processes.
### Modules and Addons
**Modules** live in ```modules/*.sh``` and are bashbot functions factored out in seperate files, gouped by functionality. Main reason for creating modules was
to keep 'bashbot.sh' small, while extending functionality. In addition not every functionality is needed by a bot, so you can
disable modules by removing them, e.g. rename the respective module files to 'module.sh.off'.
**Modules** resides in ```modules/*.sh``` and are colletions of optional bashbot functions grouped by functionality. Main reason for creating modules was
to keep 'bashbot.sh' small, while extending functionality. In addition not every funtion is needed by all bots, so you can
disable modules, e.g. by rename the respective module file to 'module.sh.off'.
Modules must use only functions provided by 'bahsbot.sh' or the module itself, no depedencies to other modules or addons must exist.
If a module function is called from 'bashbot.sh', bashbot must work if the module is disabled, so the use of ```_is_function``` and
```_execute_if_function``` is mandatory.
Modules must use functions provided by 'bahsbot.sh' or the module itself and sould not depend on other modules or addons.
The only mandatory module is 'module/sendMessage.sh'.
**Addons** live in ```addons/*.sh.dist``` and are disabled by default. To activate an addon remove '.dist' from the filename, e.g.
```cp addons/example.sh.dist addons/example.sh```. Addons must register to BASHBOT_EVENTS at startup, e.g. to call a function everytime a message is recieved.
Registering to EVENTS is similar on how 'commands.sh' is executed, but more flexible and one major difference:
**Addons are executed in the context of the main script**, while 'commands.sh' is executed as a seperate process.
If a not mandatory module is used in 'bashbot.sh' or 'commands.sh', the use of ```_is_function``` or
```_execute_if_function``` is mandatory to catch absense of the module.
This is why event functions are time critical and must return as fast as possible. Spawn actions as a seperate process or function with '&', e.g.
send a message as respone from an addon: ```send_message "${CHAT[ID]}" "Message to send ..." &```.
**Addons** resides in ```addons/*.sh.dist``` and are not endabled by default. To activate an addon rename it to end with '.sh', e.g. by
```cp addons/example.sh.dist addons/example.sh```.
Addons must register themself to BASHBOT_EVENTS at startup, e.g. to call a function everytime a message is recieved.
Addons works similar as 'commands.sh' and 'mycommands.sh' but are much more flexible on when functions/commands are triggered.
Another major difference is: **Addons are executed in the context of the main script**, while 'commands.sh' and 'macommands.sh' are executed as a seperate process.
This is why event functions are time critical and must return as fast as possible.
#### Bashbot Events
Addons must register functions to bashbot events at startup by providing their name and a callback function.
Addons must register functions to bashbot events by providing their name, and internal identifier and a callback function.
If an event occours each registered function for the event is called.
Events run in the same context as the main bashbot loop, so variables set here are persistent as long bashbot is running.
Registered functions run in the same process as bashbot, not as a sub process, so variables set here are persistent as long bashbot is running.
Note: For the same reason event function MUST return imideatly! Time consuming tasks must be run in background or as a subshell, e.g. "long running &"
Note: For the same reason event function MUST return immediately! Time consuming tasks must be run as a background process, e.g. "long running &"
Availible events:
##### MESSAGE events (all iQuery and/or Message variables are avalible):
* BASHBOT_EVENT_INLINE an inline query is received
* BASHBOT_EVENT_MESSAGE any type of message is received
* BASHBOT_EVENT_TEXT a message containing text is recieved
* BASHBOT_EVENT_CMD a command is recieved (fist word starts with /)
* BASHBOT_EVENT_REPLYTO a reply to a message is received
* BASHBOT_EVENT_FORWARD a forwarded message is received
* BASHBOT_EVENT_CONTACT a contact is received
* BASHBOT_EVENT_LOCATION a location or a venue is received
* BASHBOT_EVENT_FILE a file is received
*usage*: BASHBOT_EVENT_xxx[ "uniqe-name" ]="callback"
* BASHBOT_EVENT_MESSAGE any of the following message types is received
* BASHBOT_EVENT_TEXT a message containing text is recieved
* BASHBOT_EVENT_CMD a message containing a command is recieved (starts with /)
* BASHBOT_EVENT_REPLYTO a reply to a message is received
* BASHBOT_EVENT_FORWARD a forwarded message is received
* BASHBOT_EVENT_CONTACT a contact is received
* BASHBOT_EVENT_LOCATION a location or a venue is received
* BASHBOT_EVENT_FILE a file is received
"unique-name" can be every alphanumeric string incl. '-' and '_'. Per convention it is the name of the addon followed by an internal identyfier.
*usage*: BASHBOT_EVENT_xxx[ "unique-name" ]="callback"
"callback" is called as ```callback "event" "unique-name" "debug"``` where "event" is the event name in lower case, e.g. inline, message ... ,
and "unique-name" is the key you provided when registering the event.
"unique-name" can be every alphanumeric string incl. '-' and '_'. Per convention the name of the addon followed by an internal identyfier should be used.
*Example:* Register a function to echo to any Text send to the bot
"callback" is called as the the parameters "event" "unique-name" "debug", where "event" is the event name in lower case, e.g. inline, messagei, text ... ,
and "unique-name" is the name provided when registering the event.
*Example:* Register a function to echo to any Text sent to the bot
```bash
# register callback:
BASHBOT_EVENT_TEXT["example_1"]="example_echo"
@ -76,22 +79,28 @@ example_echo() {
send_normal_message "${CHAT[ID]}" "Event: ${event} Key: ${key} : ${MESSAGE[0]}" & # note the &!
}
```
* BAHSBOT_EVENT_TIMER is executed every minute and can be used in 3 variants: oneshot, every minute, every X minutes.
Registering to BASHBOT_EVENT_TIMER works isimilar as for message events, but you must add a timing argument to the index name.
Timer counts minutes since last (re)start in 'EVENT_TIMER', next execution of 'x' is sceduled if ```EVENT_TIMER % x``` is '0' (true).
This means if you register a every 5 Minutes event its first execution may < 5 Minutes after registration.
##### Other types of events
* BAHSBOT_EVENT_TIMER executed every minute and can be used in 3 variants: oneshot, once a minute, every X minutes.
Registering to BASHBOT_EVENT_TIMER works similar as for message events, but you must add a timing argument to the name.
EVENT_TIMER is triggered every 60s and waits until the current running command is finished, so ist not excactly every
minute, but once a minute.
Every time EVENT_TIMER is triggered the variable "EVENT_TIMER" is increased. each callback is executed if ```EVENT_TIMER % time``` is '0' (true).
This means if you register an every 5 minutes callback first execution may < 5 Minutes, all subsequent executions are once every 5. Minute.
*usage:* BAHSBOT_EVENT_TIMER[ "name" , "time" ], where time is:
* 0 ignored
* 1 execute every minute
* 1 execute once every minute
* x execute every x minutes
* -x execute ONCE in x minutes *\**
* -x execute ONCE in (next) x minutes *
*\* if you really want "in x minutes" you must use ```-(EVENT_TIMER+x)```*
*Examples:*
*Example:*
```bash
# register callback:
BAHSBOT_EVENT_TIMER["example_every","1"]="example_everymin"
@ -113,17 +122,31 @@ BAHSBOT_EVENT_TIMER["example_10min","$(( (EVENT_TIMER+10) * -1 ))"]="example_in1
```
* BASHBOT_EVENT_SEND is exceuted if sendJson or sendUpload is used to send data to Telegram server
* BASHBOT_EVENT_SEND is exceuted if data is send or uploaded to Telegram server
In contrast to other events, BASHBOT_EVENT_SEND is excecuted as in a subshell, so there no need to spawn
a subshell for longer running commands and changes to shanges to variables are not persistent.
In contrast to other events, BASHBOT_EVENT_SEND is excecuted in a subshell, so there is no need to spawn
a background process for longer running commands and changes to variables are not persistent!
BASHBOT_EVENT_SEND is mainly for logging purposes and you must not send messages while processing this event.
To avoid fork bombs event processing is suspended if recursion because of sending messages is detected.
BASHBOT_EVENT_SEND is for logging purposes, you must not send messages while processing this event.
To avoid wrong use of EVENT_SEND, e.g. fork bomb, event processing is suspended if recursion is detected.
*usage*: BASHBOT_EVENT_SEND[ "uniqe-name" ]="callback"
*usage*: BASHBOT_EVENT_SEND[ "unique-name" ]="callback"
"callback" is called with paramter "send" for events from 'sendJson' or "upload" for events from 'sendUpload', followed by the arguments send to the respective function.
"callback" is called with paramter "send" or "upload", followed by the arguments used for 'sendJson' or 'upload' functions.
*Example:*
```bash
# register callback:
BAHSBOT_EVENT_SEND["example_log","1"]="example_log"
EXAMPLE_LOG="${BASHBOT_ETC:-.}/addons/${EXAMPLE_ME}.log"
# Note: do not call any send message functions from EVENT_SEND!
example_log(){
local send="$1"; shift
echo "$(date): Type: ${send} Args: $*" >>"${EXAMPLE_LOG}"
}
```
----
@ -298,5 +321,5 @@ fi
#### [Prev Function Reference](6_reference.md)
#### $$VERSION$$ v0.91-6-g9b9125c
#### $$VERSION$$ v0.94-dev2-2-gce60555