2019-05-16 14:43:44 +00:00
#### [Home](../README.md)
## Best Practices
### New to bot development?
If you are new to Bot development read [Bots: An introduction for developers ](https://core.telegram.org/bots ) and consult [Telegram Bot API Documentation ](https://core.telegram.org/bots/api/ ).
In addition you should know about [BotFather, the one bot to rule them all ](https://core.telegram.org/bots#3-how-do-i-create-a-bot ). It will help you create new bots and change settings for existing ones. [Commands known by Botfather ](https://core.telegram.org/bots#generating-an-authorization-token )
2020-06-23 14:11:45 +00:00
If you don't have a github account, it may time to [setup a free account now ](https://github.com/pricing )
2019-05-16 14:43:44 +00:00
### Add commands to mycommands.sh only
2020-07-28 07:14:57 +00:00
Do not change ```bashbot.sh``` and ```commands.sh```, instead place your commands in to ```mycommands.sh```.
To start with a clean/minimal bot copy ```mycommands.sh.clean``` to ```mycommands.sh``` and start editing
the message strings and place commands in the```case ... esac``` block of the function mycommands():
2019-05-16 14:43:44 +00:00
```bash
# file: mycommands.sh
2020-09-27 15:36:01 +00:00
# your additional bashbot commands
2019-05-16 14:43:44 +00:00
# uncomment the following lines to overwrite info and help messages
bashbot_info='This is *MY* variant of _bashbot_ , the Telegram bot written entirely in bash.
'
bashbot_help='*Available commands*:
/echo message - _echo the given messsage_
'
# NOTE: command can have @botname attached, you must add * in case tests...
mycommands() {
case "$MESSAGE" in
'/echo'*) # example echo command
send_normal_message "${CHAT[ID]}" "$MESSAGE"
;;
# .....
esac
}
```
2020-07-28 07:14:57 +00:00
### DIsable, replace and extend global commands
2019-05-16 14:43:44 +00:00
2020-07-28 07:14:57 +00:00
Global bashbot command processing, e.g. /start, /info etc. is disabled if you return a non zero value from ```mycommands.sh```,
see /start example below.
2019-05-25 11:55:11 +00:00
2020-07-28 07:14:57 +00:00
To replace a global bashbot command add the same command to ```mycommands.sh``` and place ```return 1``` at the end of
the case block, see /kickme example below.
2019-05-25 11:55:11 +00:00
2020-07-28 07:14:57 +00:00
If a command is available as a global command and in ```mycommands.sh```, plus you return a zero value (nothing or 0)
both command sections are processed. Thus you can extend global commands with additional actions, see /info example below
2019-05-16 14:43:44 +00:00
**Learn more about [Bot commands ](https://core.telegram.org/bots#commands ).**
```bash
2020-07-28 07:14:57 +00:00
# file: mycommands.sh
2019-05-16 14:43:44 +00:00
case "$MESSAGE" in
2019-05-25 11:55:11 +00:00
##########
2020-07-28 07:14:57 +00:00
# disable start command
'/start'*) # disable all commands starting with leave
return 1
2019-05-25 11:55:11 +00:00
;;
2020-07-28 07:14:57 +00:00
# replace command with your own actions
2019-05-25 11:55:11 +00:00
'/kickme'*) # this will replace the /kickme command
send_markdown_mesage "${CHAT[ID]}" "*This bot will not kick you!*"
return 1
;;
2020-07-28 07:14:57 +00:00
# extend global command
'/info'*) # output date in front of regular info
send_normal_message "${CHAT[ID]}" "$(date)"
return 0
2019-05-16 14:43:44 +00:00
;;
esac
```
2020-06-23 14:11:45 +00:00
### Separate logic from commands
2019-05-16 14:43:44 +00:00
2020-06-23 14:11:45 +00:00
If a command need more than 2-3 lines of code, you should use a function to separate logic from command. Place your functions in ```mycommands.sh``` and call the from your command. Example:
2019-05-16 14:43:44 +00:00
```bash
# file: mycommands.sh
2020-06-23 14:11:45 +00:00
# your additional bashbot commands
2019-05-16 14:43:44 +00:00
mycommands() {
case "$MESSAGE" in
2020-06-23 15:42:34 +00:00
'/doit'*) # logic for /doit is done in process_message
2019-05-16 14:43:44 +00:00
result="$(process_message "$MESSAGE")"
send_normal_message "${CHAT[ID]}" "$result"
;;
esac
}
# place your functions here
process_message() {
local ARGS="${1#/* }" # remove command
local TEXT OUTPUT=""
# process every word in MESSAGE, avoid globbing
set -f
for WORD in $ARGS
do
# process links
if [[ "$WORD" == "https://"* ]]; then
REPORT="$(dosomething_with_link "$WORD")"
# no link, add as text
else
TEXT="$(echo "${TEXT} $WORD")"
continue
fi
# compose result
OUTPUT="* ${REPORT} ${WORD} ${TEXT}"
TEXT=""
done
# return result, reset globbing in case we had no ARGS
echo "${OUTPUT}${TEXT}"
}
```
### Test your Bot with shellcheck
Shellcheck is a static linter for shell scripts providing excellent tips and hints for shell coding pittfalls. You can [use it online ](https://www.shellcheck.net/ ) or [install it on your system ](https://github.com/koalaman/shellcheck#installing ).
All bashbot scripts are linted by shellcheck.
Shellcheck examples:
```bash
$ shellcheck -x mybotcommands.inc.sh
Line 17:
TEXT="$(echo "${TEXT} $WORD")"
^-- SC2116: Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'.
```
2020-06-23 14:35:50 +00:00
As you can see my ```mybotcommands.inc.sh``` contains an useless echo command in 'TEXT=' assignment and can be replaced by ```TEXT="${TEXT}${WORD}"```
2019-05-16 14:43:44 +00:00
```bash
$ shellcheck -x examples/notify
OK
$ shellcheck -x examples/question
OK
$ shellcheck -x commands.sh
OK
$ shellcheck -x bashbot.sh
In bashbot.sh line 123:
text="$(echo "$text" | sed 's/ mynewlinestartshere /\r\n/g')" # hack for linebreaks in startproc scripts
^-- SC2001: See if you can use ${variable//search/replace} instead.
In bashbot.sh line 490:
CONTACT[USER_ID]="$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","contact","user_id"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' < "$TMP")"
^-- SC2034: CONTACT appears unused. Verify it or export it.
```
2020-06-23 14:35:50 +00:00
The example show two warnings in bashbots scripts. The first is a hint you may use shell substitutions instead of sed, this is fixed and much faster as the "echo | sed" solution.
2019-05-16 14:43:44 +00:00
The second warning is about an unused variable, this is true because in our examples CONTACT is not used but assigned in case you want to use it :-)
#### [Prev Best Practice](5_practice.md)
#### [Next Functions Reference](6_reference.md)
2020-08-15 07:29:13 +00:00
#### $$VERSION$$ v1.0-0-g99217c4
2019-05-16 14:43:44 +00:00