mirror of
https://github.com/octoleo/telegram-bot-bash.git
synced 2024-11-15 20:47:08 +00:00
165 lines
5.4 KiB
Markdown
165 lines
5.4 KiB
Markdown
#### [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)
|
|
|
|
If you don't have a github account, it may time to [setup a free account now](https://github.com/pricing)
|
|
|
|
### Add commands to mycommands.sh only
|
|
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():
|
|
```bash
|
|
# file: mycommands.sh
|
|
# your additional bashbot commands
|
|
|
|
# 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
|
|
}
|
|
```
|
|
|
|
### DIsable, replace and extend global commands
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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
|
|
|
|
**Learn more about [Bot commands](https://core.telegram.org/bots#commands).**
|
|
|
|
```bash
|
|
# file: mycommands.sh
|
|
|
|
case "$MESSAGE" in
|
|
##########
|
|
# disable start command
|
|
'/start'*) # disable all commands starting with leave
|
|
return 1
|
|
;;
|
|
# replace command with your own actions
|
|
'/kickme'*) # this will replace the /kickme command
|
|
send_markdown_mesage "${CHAT[ID]}" "*This bot will not kick you!*"
|
|
return 1
|
|
;;
|
|
# extend global command
|
|
'/info'*) # output date in front of regular info
|
|
send_normal_message "${CHAT[ID]}" "$(date)"
|
|
return 0
|
|
;;
|
|
esac
|
|
```
|
|
|
|
|
|
### Separate logic from commands
|
|
|
|
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:
|
|
```bash
|
|
# file: mycommands.sh
|
|
# your additional bashbot commands
|
|
|
|
mycommands() {
|
|
|
|
case "$MESSAGE" in
|
|
'/doit'*) # logic for /doit is done in process_message
|
|
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'.
|
|
|
|
```
|
|
|
|
As you can see my `mybotcommands.inc.sh` contains an useless echo command in 'TEXT=' assignment and can be replaced by `TEXT="${TEXT}${WORD}"`
|
|
|
|
```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.
|
|
```
|
|
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.
|
|
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)
|
|
|
|
#### $$VERSION$$ v1.30-0-g3266427
|
|
|