#### [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.2-0-gc50499c