├── .gitignore
├── LICENSE
├── README.html
├── README.md
├── README.txt
├── addons
├── antiFlood.sh
└── example.sh
├── bashbot.rc
├── bashbot.sh
├── bin
├── any_command.sh
├── bashbot_env.inc.sh
├── bashbot_init.inc.sh
├── bashbot_stats.sh
├── delete_message.sh
├── edit_buttons.sh
├── edit_message.sh
├── kickban_user.sh
├── process_batch.sh
├── process_update.sh
├── promote_user.sh
├── send_broadcast.sh
├── send_buttons.sh
├── send_dice.sh
├── send_file.sh
└── send_message.sh
├── commands.sh
├── db.json
├── dev
├── all-tests.sh
├── dev.inc.sh
├── git-add.sh
├── hooks
│ ├── post-commit.sh
│ ├── pre-commit.sh
│ └── pre-push.sh
├── inject-json.sh
├── install-hooks.sh
├── make-distribution.sh
├── make-distribution.sh.exclude
├── make-html.sh
├── make-standalone.sh
├── make-standalone.sh.include
├── obfuscate.sh
├── shellcheck.files
└── version.sh
├── doc
├── 0_install.md
├── 1_firstbot.md
├── 2_usage.md
├── 3_advanced.md
├── 4_expert.md
├── 5_practice.md
├── 6_reference.md
├── 7_develop.md
└── bashbot.ascii
├── examples
├── README.md
├── background-scripts
│ ├── mycommands.sh
│ ├── run_diskusage.sh
│ ├── run_filecontent.sh
│ ├── run_filename.sh
│ └── run_notify.sh
├── bash2env.sh
├── bashbot-multi.sh
├── bashbot.cron
├── calc.sh
├── jsonDB-keyboard
│ └── mycommands.sh
├── notify.sh
├── question.sh
├── send-system-status
│ ├── botacl
│ └── mycommands.sh
└── webhook
│ ├── BASHBOT_HOME
│ ├── README.md
│ ├── index.php
│ └── json.txt
├── modules
├── aliases.sh
├── answerInline.sh
├── background.sh
├── chatMember.sh
├── jsonDB.sh
├── processUpdates.sh
└── sendMessage.sh
├── mycommands.conf
├── mycommands.sh
├── mycommands.sh.clean
├── scripts
└── interactive.sh.clean
└── test
├── ADD-test-new.sh
├── ALL-tests.inc.sh
├── a-commit-test.sh
├── b-example-test.sh
├── c-init-test.sh
├── c-init-test
├── blocked.jssh
├── botacl
├── botconfig.jssh
├── count.jssh
├── count.test
└── stats.out
├── d-JSON.sh-test.sh
├── d-JSON.sh-test
├── JSON26783.log.in
├── JSON26783.log.result-1
├── JSON26783.log.result-2
├── JSON30458.log.in
├── JSON30458.log.result-1
├── JSON30458.log.result-2
├── JSON32034.log.in
├── JSON32034.log.result-1
└── JSON32034.log.result-2
├── d-process_inline-test.sh
├── d-process_inline-test
├── d-process_inline-test.input
└── d-process_inline-test.result
├── d-process_message-test.sh
├── d-process_message-test
├── d-process_message-test-left_chat_member.input
├── d-process_message-test-left_chat_member.result
├── d-process_message-test-mesage.result
├── d-process_message-test-message.input
├── d-process_message-test-message.result
├── d-process_message-test-new_chat_member.input
├── d-process_message-test-new_chat_member.result
├── d-process_message-test-new_chat_picture.input
├── d-process_message-test-new_chat_picture.result
├── d-process_message-test-new_chat_title.input
├── d-process_message-test-new_chat_title.result
├── d-process_message-test-pinned_message.input
└── d-process_message-test-pinned_message.result
├── d-send_message-test.sh
├── d-send_message-test
├── d-send_message-test.input
└── d-send_message-test.result
├── d-user_is-test.sh
├── e-env-test.sh
└── e-env-test
├── blocked.jssh
├── botacl
├── botconfig.jssh
└── count.jssh
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | /.github/
3 | /count*
4 | /token*
5 | /blocked*
6 | /botconf*
7 | /botacl*
8 | /botown*
9 | *.jssh
10 | *.save
11 | *.log
12 | *.swp
13 | *.swo
14 | /logs/
15 | /JSON.sh/
16 | /data-bot-bash/
17 | /DIST/
18 | /STANDALONE/
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This project is released to the public domain where applicable.
2 |
3 | Otherwise, it is released under the terms of the WTFPLv2:
4 |
5 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6 | Version 2, December 2004
7 |
8 | Copyright (C) 2004 Sam Hocevar
9 |
10 | Everyone is permitted to copy and distribute verbatim or modified
11 | copies of this license document, and changing it is allowed as long
12 | as the name is changed.
13 |
14 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
15 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
16 |
17 | 0. You just DO WHAT THE FUCK YOU WANT TO.
18 |
19 |
--------------------------------------------------------------------------------
/addons/antiFlood.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: addons/antiFlood.sh.dist
3 | #
4 | # this addon counts how many files, e.g. stickers, are sent to
5 | # a chat and takes actions if threshold is reached
6 | #
7 | #### $$VERSION$$ v1.52-1-g0dae2db
8 |
9 | # used events:
10 | #
11 | # BASHBOT_EVENT_TEXT message containing message text received
12 | # BASHBOT_EVENT_CMD a command is received
13 | # BASHBOT_EVENT_FILE file received
14 | #
15 | # all global variables and functions can be used in registered functions.
16 | #
17 | # parameters when loaded
18 | # $1 event: init, startbot ...
19 | # $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
20 | #
21 | # parameters on events
22 | # $1 event: inline, message, ..., file
23 | # $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
24 | #
25 | # shellcheck disable=SC2140
26 |
27 | # export used events
28 | export BASHBOT_EVENT_TEXT BASHBOT_EVENT_CMD BASHBOT_EVENT_FILE BASHBOT_EVENT_TIMER
29 |
30 | # any global variable defined by addons MUST be prefixed by addon name
31 | ANTIFL_ME="antiFlood"
32 |
33 | declare -Ax ANTIFL_CHATS ANTIFL_ACTUALS
34 |
35 | ANTIFL_DEFAULT="5" # 5 files per minute
36 | ANTIFL_BAN="5" # 5 minutes
37 |
38 | # initialize after installation or update
39 | if [[ "$1" = "init"* ]]; then
40 | jssh_newDB "addons/${ANTIFL_ME}"
41 | fi
42 |
43 |
44 |
45 | # register on startbot
46 | if [[ "$1" = "start"* ]]; then
47 | ANTIFL_ADMIN="$(getConfigKey "botadmin")"
48 | #load existing chat settings on start
49 | jssh_readDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}"
50 |
51 | # register to CMD
52 | BASHBOT_EVENT_CMD["${ANTIFL_ME}"]="${ANTIFL_ME}_cmd"
53 |
54 | antiFlood_cmd(){
55 | # shellcheck disable=SC2153
56 | local chat="${CHAT[ID]}"
57 |
58 | case "${CMD[0]}" in
59 | # command /afstart starts detection, $1 floodlevel
60 | "/afstart")
61 | # allow bot admin to activate for other chats
62 | [[ "${CMD[3]}" =~ ^[-0-9]+$ ]] && user_is_botadmin "${USER[ID]}" && chat="$3"
63 | [[ "${CMD[1]}" =~ ^[0-9]+$ ]] && ANTIFL_CHATS["${chat}","level"]="${CMD[1]}" \
64 | || ANTIFL_CHATS["${chat}","level"]="${ANTIFL_DEFAULT}"
65 | [[ "${CMD[2]}" =~ ^[0-9]+$ ]] && ANTIFL_CHATS["${chat}","ban"]="${CMD[2]}" \
66 | || ANTIFL_CHATS["${chat}","ban"]="${ANTIFL_BAN}"
67 | antiFlood_timer
68 | send_normal_message "${USER[ID]}" "Antiflood set for chat ${chat}" &
69 | ;;
70 | # command /afactive starts counter meausares
71 | "/afdo" | "/afactive")
72 | [[ "${CMD[1]}" =~ ^[-0-9]+$ ]] && user_is_botadmin "${USER[ID]}" && chat="$3"
73 | ANTIFL_CHATS["${chat}","active"]="yes"
74 | jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" &
75 | send_normal_message "${USER[ID]}" "Antiflood activated for chat ${chat}" &
76 | ;;
77 | # command /afactive starts counter meausares
78 | "/afstop")
79 | [[ "${CMD[1]}" =~ ^[-0-9]+$ ]] && user_is_botadmin "${USER[ID]}" && chat="$3"
80 | ANTIFL_CHATS["${chat}","active"]="no"
81 | jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" &
82 | send_normal_message "${USER[ID]}" "Antiflood stopped for chat ${chat}" &
83 | ;;
84 | esac
85 | }
86 |
87 | # register to timer
88 | BASHBOT_EVENT_TIMER["${ANTIFL_ME}","${ANTIFL_BAN}"]="antiFlood_timer"
89 |
90 | # save settings and reset flood level every BAN Min
91 | antiFlood_timer(){
92 | ANTIFL_ACTUALS=( )
93 | jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" &
94 | }
95 |
96 | # register to inline and command
97 | BASHBOT_EVENT_TEXT["${ANTIFL_ME}"]="${ANTIFL_ME}_multievent"
98 | BASHBOT_EVENT_FILE["${ANTIFL_ME}"]="${ANTIFL_ME}_multievent"
99 |
100 | antiFlood_multievent(){
101 | # not started
102 | [ -z "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ] && return
103 | # count user flood text
104 | if [ "$1" = "text" ]; then
105 | if [ "${#MESSAGE[0]}" -gt "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ]; then
106 | (( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}"]-- ))
107 | # shellcheck disable=SC2154
108 | (( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}","file"]-- ))
109 | else
110 | # shellcheck disable=SC2154
111 | (( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}"]++ ))
112 | fi
113 | fi
114 | # count user chat flood
115 | if [ "$1" = "file" ]; then
116 | # shellcheck disable=SC2154
117 | (( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}","file"]++ ))
118 | # shellcheck disable=SC2154
119 | (( ANTIFL_ACTUALS["${CHAT[ID]}","file"]++ ))
120 | antiFlood_action & # do actions in subshell
121 | fi
122 | }
123 |
124 | # check and handle actions
125 | antiFlood_action() {
126 | # check flood level of user
127 | if [ "$(( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}","file"] +1))" -gt "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ]; then
128 | if [ "${ANTIFL_CHATS["${CHAT[ID]}","active"]}" = "yes" ]; then
129 | # remove message
130 | delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
131 | else
132 | # inform admin
133 | send_markdown_message "${ANTIFL_ADMIN}" "User ${USER[USERNAME]} reached flood level in chat ${CHAT[USERNAME]}!"
134 | fi
135 | fi
136 | # check flood level of chat
137 | if [ "$(( ANTIFL_ACTUALS["${CHAT[ID]}","file"] +1))" -gt "$(( ANTIFL_CHATS["${CHAT[ID]}","level"] * ANTIFL_BAN ))" ]; then
138 | if [ "${ANTIFL_CHATS["${CHAT[ID]}","active"]}" = "yes" ]; then
139 | # remove message
140 | delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
141 | else
142 | # inform admin
143 | send_markdown_message "${ANTIFL_ADMIN}" "Chat ${CHAT[USERNAME]} reached max flood level!"
144 | fi
145 | fi
146 | }
147 | fi
148 |
--------------------------------------------------------------------------------
/addons/example.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: addons/example.sh.dist
3 | #
4 | # Addons can register to bashbot events at startup
5 | # by providing their name and a callback per event
6 | #
7 | #### $$VERSION$$ v1.52-1-g0dae2db
8 | #
9 | # If an event occurs each registered event function is called.
10 | #
11 | # Events run in the same context as the main bashbot event loop
12 | # so variables set here are persistent as long bashbot is running.
13 | #
14 | # Note: For the same reason event function MUST return imideatly!
15 | # compute intensive tasks must be run in a nonblocking subshell,
16 | # e.g. "(long running) &"
17 | #
18 |
19 | # Available events:
20 | # on events startbot and init, this file is sourced
21 | #
22 | # BASHBOT_EVENT_INLINE inline query received
23 | # BASHBOT_EVENT_MESSAGE any type of message received
24 | # BASHBOT_EVENT_TEXT message containing message text received
25 | # BASHBOT_EVENT_CMD a command is received
26 | # BASHBOT_EVENT_REPLYTO reply to message received
27 | # BASHBOT_EVENT_FORWARD forwarded message received
28 | # BASHBOT_EVENT_CONTACT contact received
29 | # BASHBOT_EVENT_LOCATION location or venue received
30 | # BASHBOT_EVENT_FILE file received
31 | #
32 | # BASHBOT_EVENT_TIMER this event is a bit special as it fires every Minute
33 | # and has 3 meanings: oneshot, every time, every X minutes.
34 | #
35 | # all global variables and functions can be used in registered functions.
36 | #
37 | # parameters when loaded
38 | # $1 event: init, startbot ...
39 | # $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
40 | #
41 | # parameters on events
42 | # $1 event: inline, message, ..., file
43 | # $2 key: key of array BASHBOT_EVENT_xxx
44 | # $3 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
45 | #
46 |
47 | # export used events
48 | export BASHBOT_EVENT_INLINE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLY BASHBOT_EVENT_TIMER BASHBOT_EVENT_SEND
49 |
50 | # any global variable defined by addons MUST be prefixed by addon name
51 | EXAMPLE_ME="example"
52 |
53 | # initialize after installation or update
54 | if [[ "$1" = "init"* ]]; then
55 | : # nothing to do
56 | fi
57 |
58 |
59 | # register on startbot
60 | if [[ "$1" = "start"* ]]; then
61 | # register to reply
62 | BASHBOT_EVENT_REPLY["${EXAMPLE_ME}"]="${EXAMPLE_ME}_reply"
63 | EXAMPLE_ADMIN="$(getConfigKey "botadmin")"
64 |
65 | # any function defined by addons MUST be prefixed by addon name
66 | # function local variables can have any name, but must be LOCAL
67 | example_reply(){
68 | local msg="message" event="$1" key="$2"
69 | send_markdown_message "${CHAT[ID]}" "User *${USER[USERNAME]}* replied to ${msg} from *${REPLYTO[USERNAME]}* (Event: ${event} Key:{${key})" &
70 | }
71 |
72 | # register to inline and command
73 | BASHBOT_EVENT_INLINE["${EXAMPLE_ME}"]="${EXAMPLE_ME}_multievent"
74 | BASHBOT_EVENT_CMD["${EXAMPLE_ME}"]="${EXAMPLE_ME}_multievent"
75 |
76 | # any function defined by addons MUST be prefixed by addon name
77 | # function local variables can have any name, but must be LOCAL
78 | example_multievent(){
79 | local event="$1" key="$2"
80 | local msg="${MESSAGE[0]}"
81 | # shellcheck disable=SC2154
82 | [ "${type}" = "inline" ] && msg="${iQUERY[0]}"
83 | send_normal_message "${CHAT[ID]}" "${event} from ${key} received: ${msg}" &
84 | }
85 |
86 | BASHBOT_EVENT_TIMER["${EXAMPLE_ME}after5min","-5"]="${EXAMPLE_ME}_after5min"
87 |
88 | # any function defined by addons MUST be prefixed by addon name
89 | # function local variables can have any name, but must be LOCAL
90 | example_after5min(){
91 | send_markdown_message "${EXAMPLE_ADMIN}" "This is a one time event after 5 Minutes!" &
92 | }
93 |
94 | BASHBOT_EVENT_TIMER["${EXAMPLE_ME}every2min","2"]="${EXAMPLE_ME}_every2min"
95 |
96 | # any function defined by addons MUST be prefixed by addon name
97 | # function local variables can have any name, but must be LOCAL
98 | example_every2min(){
99 | send_markdown_message "${EXAMPLE_ADMIN}" "This a a every 2 minute event ..." &
100 | }
101 |
102 | # register to send
103 | BASHBOT_EVENT_SEND["${EXAMPLE_ME}"]="${EXAMPLE_ME}_log"
104 | EXAMPLE_LOG="${BASHBOT_ETC:-.}/addons/${EXAMPLE_ME}.log"
105 |
106 | # any function defined by addons MUST be prefixed by addon name
107 | # function local variables can have any name, but must be LOCAL
108 | # $1 = send / upload
109 | # $* remaining args are from sendJson and sendUpload
110 | # Note: do not call any send message functions from EVENT_SEND!
111 | example_log(){
112 | local send="$1"; shift
113 | printf "%s: Type: %s Args: %s\n" "$(date)" "${send}" "$*" >>"${EXAMPLE_LOG}"
114 | }
115 | fi
116 |
--------------------------------------------------------------------------------
/bashbot.rc:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # description: Start or stop telegram-bash-bot
3 | #
4 | # example service script to run bashbot in background as specified user
5 | #
6 | # tested on: ubuntu, opensuse, debian
7 | #
8 | #### $$VERSION$$ v1.52-1-g0dae2db
9 | # shellcheck disable=SC2009
10 | # shellcheck disable=SC2181
11 | # shellcheck disable=SC2250
12 |
13 | #
14 | ### BEGIN INIT INFO
15 | # Provides: bashbot
16 | # Required-Start: $network $syslog
17 | # Required-Stop: $network
18 | # Default-Start: 2 3 5
19 | # Default-Stop: 0 1 6
20 | # Description: Start or stop telegram-bot-bash server
21 | ### END INIT INFO
22 |
23 | # save default values
24 | TERM="" # disable bashbot clear and color output
25 | runcmd="echo Dry run:" # not activated until you edit lines below
26 |
27 | #######################
28 | # Configuration Section
29 |
30 | # edit the next line to fit the user you want to run bashbot, e.g. nobody:
31 | runas="nobody"
32 |
33 | # uncomment one of the example lines to fit your system
34 | # runcmd="su ${runas} -s /bin/bash -c " # runasuser with *su*
35 | # runcmd="/usr/sbin/runuser ${runas} -s /bin/bash -c " # runasuser with *runuser*
36 |
37 | # edit the values of the following lines to fit your config:
38 | # your bot name as given to botfather, e.g. mysomething_bot
39 | name=""
40 | [ -z "${name}" ] && name="unknown"
41 |
42 | # your bot installation dir
43 | bashbotdir="/usr/local/telegram-bot-bash"
44 | databotdir="${bashbotdir}/data-bot-bash"
45 | FIFO="${databotdir}/webhook-fifo-${name}"
46 |
47 | # programs to run
48 | bashbot="cd ${bashbotdir}; ${bashbotdir}/bashbot.sh"
49 | webhook="cd ${bashbotdir}; nohup ${bashbotdir}/bin/process_batch.sh --startbot --watch ${FIFO}"
50 | # set additionl parameter, e.g. debug
51 | mode=""
52 |
53 | # select logfile for webhook start stop and script errors
54 | hooklog="DEBUG"
55 | hooklog="WEBHOOK"
56 |
57 | # END Configuration
58 | #######################
59 |
60 |
61 | # check for bot status
62 | stat=""
63 | ps -f -u "${runas}" | grep "${name}" | grep -qF "bashbot.sh startbot"
64 | if [ "$?" = "0" ]; then
65 | # printf "bashbot (%s) is running in poll mode\n" "${name}"
66 | stat="${stat} polling"
67 | fi
68 | ps -f -u "${runas}" | grep "${name}" | grep -qF "process_batch.sh --startbot"
69 | if [ "$?" = "0" ]; then
70 | #printf "bashbot (%s) is running in webhook mode\n" "${name}"
71 | stat="${stat} webhook"
72 | elif [ "${name}" != "unknown" ]; then
73 | #printf "bashbot (%s) is stopped\n" "${name}"
74 | stat="stop"
75 | else
76 | stat="unknown"
77 | fi
78 |
79 | case "$1" in
80 | 'start')
81 | [ "${stat}" != "stop" ] && printf "Warning, bot is already running in mode: %s\n" "${stat}"
82 | $runcmd "$bashbot start $mode" # >/dev/null 2>&1 >${bashbotdir}/logs/${hooklog}.log &" # >/dev/null 2>&1 /dev/null; wait ${KILLID} 2>/dev/null"
105 | sleep 1
106 | fi
107 | RETVAL=$?
108 | $0 status
109 | ;;
110 | 'status')
111 | case "${stat}" in
112 | *"poll"*) printf "bashbot (%s) is running in polling mode\n" "${name}"
113 | RETVAL=0
114 | ;;&
115 | *"hook"*) printf "bashbot (%s) is running in webhook mode\n" "${name}"
116 | RETVAL=0
117 | ;;
118 | *"stop"*) printf "bashbot (%s) is not running\n" "${name}"
119 | RETVAL=1
120 | ;;
121 | *) printf "bashbot (%s) status is %s\n" "${name}" "${stat}"
122 | RETVAL=2
123 | ;;
124 | esac
125 | ;;
126 | 'restart'|'reload')
127 | $0 stop; $0 start
128 | RETVAL=$?
129 | ;;
130 | 'restarthook'|'reloadhook')
131 | $0 stophook; $0 starthook
132 | RETVAL=$?
133 | ;;
134 | 'restartback')
135 | $0 suspendback; $0 resumeback
136 | RETVAL=$?
137 | ;;
138 | 'suspendback'|'resumeback'|'killback')
139 | # shellcheck disable=SC2250
140 | $runcmd "$bashbot $1"
141 | RETVAL=$?
142 | # kill inotifywait from runuser
143 | if [ "$1" != "resumeback" ]; then
144 | # shellcheck disable=SC2046
145 | kill -9 $(ps -u "${runas}" | grep inotifywait | sed 's/ .*//') >/dev/null 2>&1
146 | fi
147 | ;;
148 | *)
149 | printf "%s\n" "Usage: $0 [ start | stop | restart | starthook | stophook | restarthook ]"
150 | printf "%s\n" " $0 [ status | restartback | suspendback | resumeback | killback ]"
151 | RETVAL=1
152 | ;;
153 | esac
154 | exit "${RETVAL}"
155 |
--------------------------------------------------------------------------------
/bin/any_command.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034,SC2059
3 | #===============================================================================
4 | #
5 | # FILE: bin/any_command.sh
6 | #
7 | USAGE='any_command.sh [-h|--help] [--force|--reference] bot_command args ...'
8 | #
9 | # DESCRIPTION: execute (almost) any bashbot command/function
10 | # can be used for testing commands while bot development
11 | #
12 | # OPTIONS: -- force - execute unknown commands/functions
13 | # by default only commands in 6_reference.md are allowed
14 | #
15 | # -h - display short help
16 | # --help - this help
17 | #
18 | # Set BASHBOT_HOME to your installation directory
19 | #
20 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
21 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
22 | # CREATED: 30.01.2021 10:24
23 | #
24 | #### $$VERSION$$ v1.52-1-g0dae2db
25 | #===============================================================================
26 |
27 | ####
28 | # parse args
29 | COMMAND=""
30 |
31 | # set bashbot environment
32 | source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
33 | print_help "$1"
34 |
35 |
36 | error=""
37 | # check options
38 | if [[ "$1" = "--force" ]]; then
39 | # skip checks
40 | shift
41 | else
42 | # check for --ref
43 | ref="$1"; [[ "$1" == "--ref"* ]] && shift
44 | if [ "${#1}" -lt 11 ];then
45 | printf "${RED}Command must be minimum 11 characters!${NC}\n"
46 | error=3
47 | fi
48 | if [[ "$1" != *"_"* ]];then
49 | printf "${RED}Command must contain _ (underscore)!${NC}\n"
50 | error=3
51 | fi
52 | # simple hack to get allowed commands from doc
53 | if grep -q "^##### $1" <<<"$(sed -n -e '/^##### _is_/,$ d' -e '/^##### /p' "${BASHBOT_HOME:-..}doc/"6_*)"; then
54 | # oiutput reference and exit
55 | if [[ "${ref}" == "--ref"* ]]; then
56 | sed -n -e '/^##### '"$1"'/,/^##/ p' "${BASHBOT_HOME:-..}doc/"6_*
57 | exit
58 | fi
59 | else
60 | printf "Command ${GREY}%s${NC} not found in 6_reference.md, use ${GREY}--force${NC} to execute!\n" "$1"
61 | error=4
62 | fi
63 | [ -n "${error}" ] && exit "${error}"
64 | fi
65 |
66 |
67 | ####
68 | # ready, do stuff here -----
69 | COMMAND="$1"
70 | if [ "$2" == "BOTADMIN" ]; then
71 | ARG1="${BOTADMIN}"
72 | else
73 | ARG1="$2"
74 | fi
75 |
76 | # clear result and response
77 | BOTSENT=()
78 | UPD=()
79 |
80 | # send message in selected format
81 | "${COMMAND}" "${ARG1}" "${@:3}"
82 |
83 | # output result an telegram response
84 | print_result
85 | print_response
86 |
--------------------------------------------------------------------------------
/bin/bashbot_env.inc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #===============================================================================
3 | #
4 | # FILE: bashbot_env.inc.sh
5 | #
6 | # USAGE: source bashbot_env.inc.sh [debug]
7 | #
8 | # DESCRIPTION: set bashbot environment for all scripts in this directory
9 | #
10 | # OPTIONS: $1 - will be forwarded ro bashbot, e.g. debug
11 | #
12 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
13 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
14 | # CREATED: 18.12.2020 12:27
15 | #
16 | #### $$VERSION$$ v1.52-1-g0dae2db
17 | #===============================================================================
18 |
19 | ############
20 | # set where your bashbot lives
21 | export BASHBOT_HOME BASHBOT_ETC BASHBOT_VAR FILE_REGEX ME
22 |
23 | # default: one dir up
24 | BASHBOT_HOME="$(cd "${BASH_SOURCE[0]%/*}/../" >/dev/null 2>&1 && pwd)"
25 | [ "${BASHBOT_HOME}" = "" ] && BASHBOT_HOME="../"
26 |
27 | # set you own BASHBOT_HOME if different, e.g.
28 | # BASHBOT_HOME="/usr/local/telegram-bot-bash"
29 | BASHBOT_VAR="${BASHBOT_HOME}"
30 | BASHBOT_ETC="${BASHBOT_HOME}"
31 |
32 | #####
33 | # if files are not readable, eviroment is wrong or bashbot is not initialized
34 |
35 | # check for bashbot
36 | if [ ! -r "${BASHBOT_HOME}/bashbot.sh" ]; then
37 | printf "%s\n" "Bashbot.sh not found in \"${BASHBOT_HOME}\""
38 | exit 4
39 | fi
40 |
41 | dev=" Are we in dev or did you forget to run init?"
42 | # check for botconfig.jssh readable
43 | if [ ! -r "${BASHBOT_ETC}/botconfig.jssh" ]; then
44 | printf "%s\n" "Bashbot config file in \"${BASHBOT_ETC}\" does not exist or is not readable. ${dev}"
45 | exit 3
46 | fi
47 | # check for count.jssh readable
48 | if [ ! -r "${BASHBOT_VAR}/count.jssh" ]; then
49 | printf "%s\n" "Bashbot count file in \"${BASHBOT_VAR}\" does not exist or is not readable. ${dev}"
50 | exit 3
51 | fi
52 |
53 | # shellcheck disable=SC1090
54 | source "${BASHBOT_HOME}/bashbot.sh" source "$1"
55 |
56 | # overwrite bot FILE regex to BASHBOT_VAR
57 | # change this to the location you want to allow file uploads from
58 | UPLOADDIR="${BASHBOT_VAR%/bin*}"
59 | FILE_REGEX="${UPLOADDIR}/.*"
60 |
61 | # get and check ADMIN and NAME
62 | BOTNAME="$(getConfigKey "botname")"
63 | ME="${BOTNAME}"
64 | [[ -z "${BOTADMIN}" || "${BOTADMIN}" == "?" ]] && printf "%s\n" "${ORANGE}Warning: Botadmin not set, send bot command${NC} /start"
65 | [[ -z "${BOTNAME}" ]] && printf "%s\n" "${ORANGE}Warning: Botname not set, run bashbot.sh botname"
66 |
67 | # default webhook pipe
68 | export WEBHOOK="${DATADIR}/webhook-fifo-${ME}"
69 |
70 |
71 | # output command result or Telegram response
72 | print_result() { jssh_printDB "BOTSENT" | sort -r; }
73 | print_response() { jssh_printDB "UPD"; }
74 |
75 | # check and output help
76 | print_help() {
77 | case "$1" in
78 | '')
79 | printf "missing arguments\n"
80 | ;&
81 | "-h"*)
82 | printf 'usage: %s\n' "${USAGE}"
83 | exit 1
84 | ;;
85 | '--h'*)
86 | sed -n '/^#====/,/^#====/p' <"$0"
87 | exit 1
88 | ;;
89 | esac
90 | }
91 |
92 |
--------------------------------------------------------------------------------
/bin/bashbot_stats.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/bashbot_stats.sh
6 | #
7 | USAGE='bashbot_stats.sh [-h|--help] [debug]'
8 | #
9 | # DESCRIPTION: output bashbot user stats
10 | #
11 | # OPTIONS: -h - display short help
12 | # --help - this help
13 | #
14 | # Set BASHBOT_HOME to your installation directory
15 | #
16 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
17 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
18 | # CREATED: 23.12.2020 20:34
19 | #
20 | #### $$VERSION$$ v1.52-1-g0dae2db
21 | #===============================================================================
22 |
23 | # set bashbot environment
24 | source "${0%/*}/bashbot_env.inc.sh" "$1"
25 | [ -n "$1" ] && print_help "$1"
26 |
27 | ####
28 | # ready, do stuff here -----
29 |
30 | echo -e "${GREEN}Hi I'm ${BOTNAME}.${NC}"
31 | declare -A STATS
32 | jssh_readDB_async "STATS" "${COUNTFILE}"
33 | for MSG in ${!STATS[*]}
34 | do
35 | [[ ! "${MSG}" =~ ^[0-9-]*$ ]] && continue
36 | (( USERS++ ))
37 | done
38 | for MSG in ${STATS[*]}
39 | do
40 | (( MESSAGES+=MSG ))
41 | done
42 | if [ "${USERS}" != "" ]; then
43 | echo -e "${GREY}A total of ${NC}${MESSAGES}${GREY} messages from ${NC}${USERS}${GREY} users are processed.${NC}"
44 | else
45 | echo -e "${ORANGE}No one used your bot so far ...${NC}"
46 | fi
47 | jssh_readDB_async "STATS" "${BLOCKEDFILE}"
48 | for MSG in ${!STATS[*]}
49 | do
50 | [[ ! "${MSG}" =~ ^[0-9-]*$ ]] && continue
51 | (( BLOCKS++ ))
52 | done
53 | if [ "${BLOCKS}" != "" ]; then
54 | echo -e "${ORANGE}${BLOCKS} user(s) are blocked:${NC}${GREY}"
55 | sort -r "${BLOCKEDFILE}.jssh"
56 | echo -e "${NC}\c"
57 | else
58 | echo -e "${GREEN}No user is blocked currently ...${NC}"
59 | fi
60 | # show user created bot stats
61 | _exec_if_function my_bashbot_stats "$@"
62 |
63 |
--------------------------------------------------------------------------------
/bin/delete_message.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/delete_message.sh
6 | #
7 | USAGE='delete_message.sh [-h|--help] "CHAT[ID]" "MESSAGE[ID]" [debug]'
8 | #
9 | # DESCRIPTION: delete a message in the given user/group
10 | #
11 | # OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN
12 | # MESSAGE[ID] - message to delete
13 | #
14 | # -h - display short help
15 | # --help - this help
16 | #
17 | # Set BASHBOT_HOME to your installation directory
18 | #
19 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
20 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
21 | # CREATED: 03.01.2021 15:37
22 | #
23 | #### $$VERSION$$ v1.52-1-g0dae2db
24 | #===============================================================================
25 |
26 | ####
27 | # parse args
28 | DELETE="delete_message"
29 |
30 | # set bashbot environment
31 | source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
32 | print_help "$1"
33 |
34 | ####
35 | # ready, do stuff here -----
36 | if [ "$1" == "BOTADMIN" ]; then
37 | CHAT="${BOTADMIN}"
38 | else
39 | CHAT="$1"
40 | fi
41 |
42 | # delete message
43 | "${DELETE}" "${CHAT}" "$2"
44 |
45 | [ "${BOTSENT[OK]}" = "true" ] && BOTSENT[ID]="$2"
46 |
47 | # output send message result
48 | print_result
49 |
--------------------------------------------------------------------------------
/bin/edit_buttons.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/edit_buttons.sh
6 | #
7 | USAGE='send_message.sh [-h|--help] "CHAT[ID]" "MESSAGE[ID]" "text|url" ...'
8 | #
9 | # DESCRIPTION: send a send buttons in a row to the given user/group
10 | #
11 | # OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
12 | # MESSAGE[ID] - ID of MESSAGE with buttons to edit
13 | # text|url - buttons to send, each button as "text|url" pair or
14 | # "url" only to show url as text also, "" starts new row
15 | # "url" not http(s):// or tg:// is sent as callback_data
16 | #
17 | # -h - display short help
18 | # --help - this help
19 | #
20 | # EXAMPLE: 2 buttons on 2 rows, first shows Amazon, second the url as text
21 | # send_buttons.sh "Amazon|https://www.amazon.com" "" "https://mydealz.de" ...
22 | #
23 | # Set BASHBOT_HOME to your installation directory
24 | #
25 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
26 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
27 | # CREATED: 21.01.2021 08:10
28 | #
29 | #### $$VERSION$$ v1.52-1-g0dae2db
30 | #===============================================================================
31 |
32 | ####
33 | # parse args
34 | SEND="edit_inline_keyboard"
35 |
36 | # set bashbot environment
37 | source "${0%/*}/bashbot_env.inc.sh" "debug"
38 | print_help "$1"
39 |
40 | ####
41 | # ready, do stuff here -----
42 | if [ "$1" == "BOTADMIN" ]; then
43 | CHAT="${BOTADMIN}"
44 | else
45 | CHAT="$1"
46 | fi
47 | MESSAGE_ID="$2"
48 | shift 2
49 |
50 | # send message in selected format
51 | "${SEND}" "${CHAT}" "${MESSAGE_ID}" "$(_button_row "$@")"
52 |
53 | # output send message result
54 | print_result
55 |
--------------------------------------------------------------------------------
/bin/edit_message.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/edit_message.sh
6 | #
7 | USAGE='send_edit_message.sh [-h|--help] [format|caption] "CHAT[ID]" "MESSAGE[ID]" "message ...." [debug]'
8 | #
9 | # DESCRIPTION: replace a message in the given user/group
10 | #
11 | # OPTIONS: format - normal, markdown, html or caption for file caption (optional)
12 | # CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
13 | # MESSAGE[ID] - message to replace
14 | # message - message to send in specified format
15 | # if no format is given send_normal_message() format is used
16 | #
17 | # -h - display short help
18 | # --help - this help
19 | #
20 | # Set BASHBOT_HOME to your installation directory
21 | #
22 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
23 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
24 | # CREATED: 23.12.2020 16:52
25 | #
26 | #### $$VERSION$$ v1.52-1-g0dae2db
27 | #===============================================================================
28 |
29 | ####
30 | # parse args
31 | SEND="edit_normal_message"
32 | case "$1" in
33 | "nor"*|"tex"*)
34 | SEND="edit_normal_message"
35 | shift
36 | ;;
37 | "mark"*)
38 | SEND="edit_markdownv2_message"
39 | shift
40 | ;;
41 | "htm"*)
42 | SEND="edit_html_message"
43 | shift
44 | ;;
45 | "cap"*)
46 | SEND="edit_message_caption"
47 | shift
48 | ;;
49 | esac
50 |
51 | # set bashbot environment
52 | source "${0%/*}/bashbot_env.inc.sh" "${4:-debug}" # $4 debug
53 | print_help "$1"
54 |
55 | ####
56 | # ready, do stuff here -----
57 | if [ "$1" == "BOTADMIN" ]; then
58 | CHAT="${BOTADMIN}"
59 | else
60 | CHAT="$1"
61 | fi
62 |
63 | # send message in selected format
64 | "${SEND}" "${CHAT}" "$2" "$3"
65 |
66 | # output send message result
67 | print_result
68 |
--------------------------------------------------------------------------------
/bin/kickban_user.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/kickban_user.sh
6 | #
7 | USAGE='kickban_user.sh [-h|--help] [-u|--unban] "CHAT[ID]" "USER[ID]" [debug]'
8 | #
9 | # DESCRIPTION: kickban or unban a user from the given group
10 | #
11 | # OPTIONS: -u | --unban - unban user
12 | # CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
13 | # USER[ID] - user to (un)ban
14 | #
15 | # -h - display short help
16 | # --help - this help
17 | #
18 | #
19 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
20 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
21 | # CREATED: 25.01.2021 20:34
22 | #
23 | #### $$VERSION$$ v1.52-1-g0dae2db
24 | #===============================================================================
25 |
26 | ####
27 | # parse args
28 | BAN="kick_chat_member"
29 | case "$1" in
30 | "-u"|"--unban")
31 | BAN="unban_chat_member"
32 | shift
33 | ;;
34 | esac
35 |
36 | # set bashbot environment
37 | source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
38 | print_help "$1"
39 |
40 | ####
41 | # ready, do stuff here -----
42 |
43 | # send message in selected format
44 | "${BAN}" "$1" "$2"
45 |
46 | # output send message result
47 | print_result
48 |
--------------------------------------------------------------------------------
/bin/process_batch.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034,SC2059
3 | #===============================================================================
4 | #
5 | # FILE: bin/process_batch.sh
6 | #
7 | USAGE='process_batch.sh [-h|--help] [-s|--startbot] [-w|--watch] [-n|--lines n] [file] [debug]'
8 | #
9 | # DESCRIPTION: processes last 10 telegram updates in file, one update per line
10 | #
11 | # -s --startbot load addons, start TIMER, trigger startup actions
12 | # -w --watch watch for new updates added to file
13 | # -n --lines read only last "n" lines
14 | # file to read updates from
15 | # empty means read from webhook pipe
16 | #
17 | # -h - display short help
18 | # --help - this help
19 | #
20 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
21 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
22 | # CREATED: 27.02.2021 13:14
23 | #
24 | #### $$VERSION$$ v1.52-1-g0dae2db
25 | #===============================================================================
26 |
27 | ####
28 | # parse args
29 | COMMAND="process_multi_updates"
30 | lines="-n 10"
31 | mode="batch"
32 |
33 | opt=0
34 | while [[ "${opt}" -lt 5 && "$1" == "-"* ]]
35 | do
36 | (( opt++ ))
37 | case "$1" in
38 | "-s"|"--startbot")
39 | startbot="yes"
40 | shift
41 | ;;
42 | "-w"|"--watch")
43 | follow="-f"
44 | mode="webhook"
45 | shift
46 | ;;
47 | "-n"|"--lines")
48 | lines="-n $2"
49 | shift 2
50 | ;;
51 | esac
52 | done
53 |
54 | # set bashbot environment
55 | source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
56 | print_help "${1:-nix}"
57 |
58 | # empty file is webhook
59 | file="${WEBHOOK}"
60 | [ -n "$1" ] && file="$1"
61 |
62 | # start bot
63 | if [ -n "${startbot}" ]; then
64 | # warn when starting bot without pipe
65 | [ -p "${file}" ] || printf "%(%c)T: %b\n" -1 "${ORANGE}Warning${NC}: File is not a pipe:${GREY} ${file##*/}${NC}"
66 | start_bot "$2" "${mode}"
67 | printf "%(%c)T: %b\n" -1 "${GREEN}Bot startup actions done, start ${mode} updates ...${NC}"
68 | fi
69 | # check file exist
70 | if [[ ! -r "${file}" || -d "${file}" ]]; then
71 | printf "%(%c)T: %b\n" -1 "${RED}Error${NC}: File not readable:${GREY} ${file}${NC}."
72 | exit 1
73 | fi
74 |
75 | ####
76 | # ready, do stuff here -----
77 |
78 | # kill all sub processes on exit
79 | trap 'printf "%(%c)T: %s\n" -1 "Bot in '"${mode}"' mode stopped"; kill $(jobs -p) 2>/dev/null; wait $(jobs -p) 2>/dev/null; send_normal_message "'"${BOTADMIN}"'" "Bot '"${BOTNAME} ${mode}"' stopped ..."' EXIT HUP QUIT
80 |
81 | # wait after (first) update to avoid processing to many in parallel
82 | UPDWAIT="0.5"
83 | # use tail to read appended updates
84 | # shellcheck disable=SC2086,SC2248
85 | tail ${follow} ${lines} "${file}" 2>/dev/null |\
86 | while IFS="" read -r input 2>/dev/null
87 | do
88 | # read json from stdin and convert update format
89 | # replace any ID named BOTADMIN with ID of bot admin
90 | : "${input//\"id\":BOTADMIN,/\"id\":${BOTADMIN},}"
91 | json='{"result": ['"${_}"']}'
92 | UPDATE="$(${JSONSHFILE} -b -n <<<"${json}" 2>/dev/null)"
93 |
94 | # process telegram update
95 | "${COMMAND}" "$2"
96 | sleep "${UPDWAIT}"
97 | UPDWAIT="0.05"
98 | done
99 |
--------------------------------------------------------------------------------
/bin/process_update.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034,SC2059
3 | #===============================================================================
4 | #
5 | # FILE: bin/process_update.sh
6 | #
7 | USAGE='process_update.sh [-h|--help] [debug] [/dev/null)"
38 |
39 | # process telegram update
40 | "${COMMAND}" "$1"
41 |
42 |
--------------------------------------------------------------------------------
/bin/promote_user.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/promote_user.sh
6 | #
7 | USAGE='promote_user.sh [-h|--help] "CHAT[ID]" "USER[ID]" "right[:true|false]" ..'
8 | #
9 | # DESCRIPTION: promote / denote user rights in given group
10 | #
11 | # OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
12 | # USER[ID] - user to (un)ban
13 | # rights[:true|false] - rights to grant in long or short form,
14 | # followed by :true to grant or :false to renove
15 | # long: is_anonymous can_change_info can_post_messages can_edit_messages
16 | # can_delete_messages can_invite_users can_restrict_members
17 | # can_pin_messages can_promote_member`
18 | # short: anon change post edit delete invite restrict pin promote
19 | #
20 | # -h - display short help
21 | # --help - this help
22 | #
23 | #
24 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
25 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
26 | # CREATED: 25.01.2021 22:34
27 | #
28 | #### $$VERSION$$ v1.52-1-g0dae2db
29 | #===============================================================================
30 |
31 | ####
32 | # parse args
33 | PROMOTE="promote_chat_member"
34 |
35 | # set bashbot environment
36 | source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
37 | print_help "$1"
38 |
39 | ####
40 | # ready, do stuff here -----
41 |
42 | # send message in selected format
43 | "${PROMOTE}" "$@"
44 |
45 | # output send message result
46 | print_result
47 |
--------------------------------------------------------------------------------
/bin/send_broadcast.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | # shellcheck disable=SC2059
5 | #
6 | # FILE: bin/broadcast_message.sh
7 | #
8 | USAGE='broadcast_message.sh [-h|--help] [--doit] [--groups|--both|--db=file] [format] "message ...." [debug]'
9 | #
10 | # DESCRIPTION: send a message to all users listed in a jsonDB (default count db)
11 | #
12 | # OPTIONS: --doit - broadcast is dangerous, simulate run without --doit
13 | # --groups - send to groups instead of users
14 | # --both - send to users and groups (default with --db)
15 | # --db name - send to all user/groups in jsonDB database (e.g. blocked)
16 | # db file: name.jssh, db keys are user/chat id, values are ignored
17 | #
18 | # format - normal, markdown, html (optional)
19 | # message - message to send in specified format
20 | # if no format is givern send_message() format is used
21 | #
22 | # -h - display short help
23 | # --help - this help
24 | #
25 | # Set BASHBOT_HOME to your installation directory
26 | #
27 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
28 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
29 | # CREATED: 16.12.2020 16:14
30 | #
31 | #### $$VERSION$$ v1.52-1-g0dae2db
32 | #===============================================================================
33 |
34 | ####
35 | # minimum messages seen in a chat before send a broadcast to it
36 | MINCOUNT=2
37 | USERDB=""
38 |
39 | ####
40 | # broadcast is dangerous, without --doit we do a dry run ...
41 | if [ "$1" = "--doit" ]; then
42 | DOIT="yes"
43 | shift
44 | fi
45 |
46 | ####
47 | # send to users by default, --group sends groups, --both to both
48 | SENDTO="users"
49 | if [ "$1" = "--both" ]; then
50 | GROUPSALSO=" and groups"
51 | shift
52 | elif [ "$1" = "--groups" ]; then
53 | SENDTO="groups"
54 | GROUPSALSO=" only"
55 | shift
56 | elif [ "$1" = "--db" ]; then
57 | USERDB="${2%.jssh}"
58 | MINCOUNT=""
59 | GROUPSALSO=" and groups"
60 | shift 2
61 | fi
62 |
63 | ####
64 | # parse args -----------------
65 | SEND="send_message"
66 | case "$1" in
67 | "nor"*|"tex"*)
68 | SEND="send_normal_message"
69 | shift
70 | ;;
71 | "mark"*)
72 | SEND="send_markdownv2_message"
73 | shift
74 | ;;
75 | "html")
76 | SEND="send_html_message"
77 | shift
78 | ;;
79 | esac
80 |
81 | # set bashbot environment
82 | source "${0%/*}/bashbot_env.inc.sh" "$2" # $3 debug
83 | print_help "$1"
84 |
85 | # read in users from given DB or count.jssh
86 | database="${USERDB:-${COUNTFILE}}"
87 | declare -A SENDALL
88 | jssh_readDB_async "SENDALL" "${database}"
89 | if [ -z "${SENDALL[*]}" ]; then
90 | printf "${ORANGE}User database not found or empty: ${NC}${database}\n"
91 | fi
92 |
93 | # loop over users
94 | printf "${GREEN}Sending broadcast message to ${SENDTO}${GROUPSALSO} of ${BOTNAME} using database:${NC}${GREY} ${database##*/}"
95 |
96 | { # dry run
97 | [ -z "${DOIT}" ] && printf "${NC}\n${ORANGE}DRY RUN! use --doit as first argument to execute broadcast...${NC}\n"
98 |
99 | for USER in ${!SENDALL[*]}
100 | do
101 | # send to users, groups or both ...
102 | [[ -z "${GROUPSALSO}" && "${USER}" == *"-"* ]] && continue
103 | [[ "${SENDTO}" != "users" && "${USER}" != *"-"* ]] && continue
104 | # ignore everything not a user or group
105 | [[ ! "${USER}" =~ ^[0-9-]*$ ]] && continue
106 | # ignore chats with no count or lower MINCOUNT
107 | [[ -n "${MINCOUNT}" && ( ! "${SENDALL[${USER}]}" =~ ^[0-9]*$ || "${SENDALL[${USER}]}" -lt "${MINCOUNT}" ) ]] && continue
108 | (( COUNT++ ))
109 | if [ -z "${DOIT}" ]; then
110 | printf "${SEND} ${USER} $1 $2\n"
111 | else
112 | "${SEND}" "${USER}" "$1" "$2"
113 | printf "." 1>&2
114 | # ups, kicked or banned ...
115 | if [ "${BOTSENT[ERROR]}" = "403" ]; then
116 | # remove chat from future broadcasts
117 | jssh_insertKeyDB "${USER}" "${SENDALL[${USER}]} banned" "${COUNTFILE}"
118 | printf "${ORANGE}Warning: bot banned from chat${NC} %s ${ORANGE}after${NC} %s ${ORANGE}commands${NC}\n"\
119 | "${USER}" "${SENDALL[${USER}]}"
120 | fi
121 | sleep 0.1
122 | fi
123 | done
124 | # printout final stats message
125 | printf "${NC}\n${GREEN}Message${NC} $1 ${GREEN}sent to${NC} ${COUNT} ${GREEN}${SENDTO}${GROUPSALSO}.${NC}\n"
126 | } | more
127 |
128 |
--------------------------------------------------------------------------------
/bin/send_buttons.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/send_message.sh
6 | #
7 | USAGE='send_message.sh [-h|--help] "CHAT[ID]" "message" "text|url" ...'
8 | #
9 | # DESCRIPTION: send a send buttons in a row to the given user/group
10 | #
11 | # OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
12 | # message - message to send
13 | # text|url - buttons to send, each button as "text|url" pair or
14 | # "url" not http(s):// or tg:// is sent as callback_data
15 | # "url" only to show url as text also, "" starts new row
16 | #
17 | # -h - display short help
18 | # --help - this help
19 | #
20 | # EXAMPLE: 2 buttons on 2 rows, first shows Amazon, second the url as text
21 | # send_buttons.sh "Amazon|https://www.amazon.com" "" "https://mydealz.de" ...
22 | #
23 | # Set BASHBOT_HOME to your installation directory
24 | #
25 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
26 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
27 | # CREATED: 18.01.2021 11:34
28 | #
29 | #### $$VERSION$$ v1.52-1-g0dae2db
30 | #===============================================================================
31 |
32 | ####
33 | # parse args
34 | SEND="send_inline_keyboard"
35 |
36 | # set bashbot environment
37 | source "${0%/*}/bashbot_env.inc.sh" "debug"
38 | print_help "$1"
39 |
40 | ####
41 | # ready, do stuff here -----
42 | if [ "$1" == "BOTADMIN" ]; then
43 | CHAT="${BOTADMIN}"
44 | else
45 | CHAT="$1"
46 | fi
47 | MESSAGE="$2"
48 | shift 2
49 |
50 | # send message in selected format
51 | "${SEND}" "${CHAT}" "${MESSAGE}" "$(_button_row "$@")"
52 |
53 | # output send message result
54 | print_result
55 |
--------------------------------------------------------------------------------
/bin/send_dice.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/send_dice.sh
6 | #
7 | USAGE='send_dice.sh [-h|--help] "CHAT[ID]" "emoji" [debug]'
8 | #
9 | # DESCRIPTION: send an animated emoji (dice) to given chat
10 | #
11 | # OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
12 | # emoji - must be one of: “🎲”, “🎯”, “🏀”, “⚽” “🎰” "🎳"
13 | # :game_die: :dart: :basketball: :soccer: :slot_machine: :bowling:
14 | #
15 | # -h - display short help
16 | # --help - this help
17 | #
18 | # Set BASHBOT_HOME to your installation directory
19 | #
20 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
21 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
22 | # CREATED: 07.02.2021 18:45
23 | #
24 | #### $$VERSION$$ v1.52-1-g0dae2db
25 | #===============================================================================
26 |
27 | ####
28 | # parse args
29 | SEND="send_dice"
30 |
31 | # set bashbot environment
32 | source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $5 debug
33 | print_help "$1"
34 |
35 | ####
36 | # ready, do stuff here -----
37 | if [ "$1" == "BOTADMIN" ]; then
38 | CHAT="${BOTADMIN}"
39 | else
40 | CHAT="$1"
41 | fi
42 |
43 | # send message in selected format
44 | "${SEND}" "${CHAT}" "$2"
45 |
46 | # output send message result
47 | print_result
48 |
--------------------------------------------------------------------------------
/bin/send_file.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/send_file.sh
6 | #
7 | USAGE='send_file.sh [-h|--help] "CHAT[ID]" "file|URL" "caption ...." [type] [debug]'
8 | #
9 | # DESCRIPTION: send a file to the given user/group
10 | #
11 | # OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
12 | # file - local file to send, must be an absolute path or relative to pwd
13 | # Note: must not contain .. or . and located below BASHBOT_ETC
14 | # URL - send an URL instead local file
15 | #
16 | # caption - message to send with file
17 | # type - photo, video, sticker, voice, document (optional)
18 | #
19 | # -h - display short help
20 | # --help - this help
21 | #
22 | # Set BASHBOT_HOME to your installation directory
23 | #
24 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
25 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
26 | # CREATED: 25.12.2020 20:24
27 | #
28 | #### $$VERSION$$ v1.52-1-g0dae2db
29 | #===============================================================================
30 |
31 | ####
32 | # parse args
33 | SEND="send_file"
34 |
35 | # set bashbot environment
36 | source "${0%/*}/bashbot_env.inc.sh" "${5:-debug}" # $5 debug
37 | print_help "$1"
38 |
39 | ####
40 | # ready, do stuff here -----
41 | if [ "$1" == "BOTADMIN" ]; then
42 | CHAT="${BOTADMIN}"
43 | else
44 | CHAT="$1"
45 | fi
46 |
47 | FILE="$2"
48 | # convert to absolute path if not start with / or http://
49 | [[ ! ( "$2" == "/"* || "$2" =~ ^https*:// || "$2" == "file_id://"*) ]] && FILE="${PWD}/$2"
50 |
51 | # send message in selected format
52 | "${SEND}" "${CHAT}" "${FILE}" "$3" "$4"
53 |
54 | # output send message result
55 | print_result
56 |
--------------------------------------------------------------------------------
/bin/send_message.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC1090,SC2034
3 | #===============================================================================
4 | #
5 | # FILE: bin/send_message.sh
6 | #
7 | USAGE='send_message.sh [-h|--help] [format] "CHAT[ID]" "message ...." [debug]'
8 | #
9 | # DESCRIPTION: send a message to the given user/group
10 | #
11 | # OPTIONS: format - normal, markdown, html, stdin, - (optional)
12 | # CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
13 | # message - message to send in specified format
14 | # if no format is givern send_message() format is used
15 | #
16 | # use format "stdin" to read message from stdin or from a file:
17 | # send_message.sh stdin "CHAT[ID]" /dev/null
23 |
24 | # mkdir needed dirs
25 | mkdir "${TESTENV}/data-bot-bash"
26 |
27 | # inject JSON.sh
28 | mkdir "${TESTENV}/JSON.sh"
29 | curl -sL "https://cdn.jsdelivr.net/gh/dominictarr/JSON.sh/JSON.sh" >"${TESTENV}/JSON.sh/JSON.sh"
30 | chmod +x "${TESTENV}/JSON.sh/JSON.sh"
31 |
32 | ########################
33 | #prepare and run tests
34 | #set -e
35 | fail=0
36 | tests=0
37 | passed=0
38 | #all_tests=${__dirname:}
39 | #printf PLAN ${#all_tests}
40 | for test in $(find ./*-test.sh | sort -u) ;
41 | do
42 | [ "${test}" = "dev/all-tests.sh" ] && continue
43 | [ ! -x "${test}" ] && continue
44 | tests=$((tests+1))
45 | printf "TEST: %s\n" "${test}"
46 | "${test}" "${TESTENV}"
47 | ret=$?
48 | set +e
49 | if [ "${ret}" -eq 0 ] ; then
50 | printf "OK: ---- %s\n" "${test}"
51 | passed=$((passed+1))
52 | else
53 | printf "FAIL: %s\n" "${test} ${fail}"
54 | fail=$((fail+ret))
55 | break
56 | fi
57 | done
58 |
59 | ###########################
60 | # cleanup depending on test state
61 | if [ "${fail}" -eq 0 ]; then
62 | printf 'SUCCESS '
63 | exitcode=0
64 | rm -rf "${TESTENV}"
65 | else
66 | printf 'FAILURE '
67 | exitcode=1
68 | rm -rf "${TESTENV}/test"
69 | find "${TESTENV}/"* ! -name '[a-z]-*' -delete
70 | fi
71 |
72 | #########################
73 | # show test result and test logs
74 | printf "%s\n\n" "${passed} / ${tests}"
75 | [ -d "${TESTENV}" ] && printf "Logfiles from run are in %s\n" "${TESTENV}"
76 |
77 | ls -ld /tmp/bashbot.test* 2>/dev/null && printf "Do not forget to delete bashbot test files in /tmp!!\n"
78 |
79 | exit "${exitcode}"
80 |
--------------------------------------------------------------------------------
/dev/dev.inc.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #############################################################
3 | #
4 | # File: dev/dev.inc.sh
5 | #
6 | # Description: common stuff for all dev scripts
7 | #
8 | #### $$VERSION$$ v1.52-1-g0dae2db
9 | #############################################################
10 |
11 | # magic to ensure that we're always inside the root of our application,
12 | # no matter from which directory we'll run script
13 |
14 | # shellcheck disable=SC2034
15 | GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
16 | BASE_DIR=$(git rev-parse --show-toplevel 2>/dev/null)
17 | if [ "${BASE_DIR}" != "" ] ; then
18 | cd "${BASE_DIR}" || exit 1
19 | else
20 | printf "Sorry, no git repository %s\n" "$(pwd)" && exit 1
21 | fi
22 |
23 | HOOKDIR="dev/hooks"
24 | LASTCOMMIT=".git/.lastcommit"
25 |
--------------------------------------------------------------------------------
/dev/git-add.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # file: git-add.sh
3 | #
4 | # works together with git pre-push.sh and ADD all changed files since last push
5 |
6 | #### $$VERSION$$ v1.52-1-g0dae2db
7 |
8 | #shellcheck disable=SC1090
9 | source "${0%/*}/dev.inc.sh"
10 |
11 | # check for last commit date
12 | if [ ! -f "${LASTCOMMIT}" ]; then
13 | if ! touch -d "$(git log -1 --format=%cD)" "${LASTCOMMIT}"; then
14 | printf "No previous commit found, use \"git add\" instead ... Abort\n"
15 | exit
16 | fi
17 | fi
18 |
19 | set +f
20 | FILES="$(find ./* -newer "${LASTCOMMIT}" | grep -v -e 'DIST\/' -e 'STANDALONE\/' -e 'JSON.sh')"
21 | set -f
22 | # FILES="$(find ./* -newer .git/.lastpush)"
23 | [ "${FILES}" = "" ] && printf "Nothing changed since last commit ...\n" && exit
24 |
25 | # run pre_commit on files
26 | dev/hooks/pre-commit.sh
27 |
28 | printf "Add files to repo: "
29 | # shellcheck disable=SC2086
30 | for file in ${FILES}
31 | do
32 | [ -d "${file}" ] && continue
33 | printf "%s" "${file} "
34 | done
35 | printf " - Done.\n"
36 |
37 | # stay with "." for (re)moved files!
38 | git add .
39 |
40 |
--------------------------------------------------------------------------------
/dev/hooks/post-commit.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #### $$VERSION$$ v1.52-1-g0dae2db
3 |
4 | ############
5 | # NOTE: you MUST run install-hooks.sh again when updating this file!
6 |
7 | # magic to ensure that we're always inside the root of our application,
8 | # no matter from which directory we'll run script
9 | GIT_DIR=$(git rev-parse --git-dir)
10 | cd "${GIT_DIR}/.." || exit 1
11 |
12 | export HOOKDIR="dev/hooks"
13 | LASTPUSH='.git/.lastcommit'
14 |
15 | # if any command inside script returns error, exit and return that error
16 | set -e
17 |
18 | #printf "Running post-commit hook\n............................\n"
19 |
20 | unset IFS; set -f
21 |
22 | # note date of last push for version
23 | touch "${LASTPUSH}"
24 |
--------------------------------------------------------------------------------
/dev/hooks/pre-commit.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #### $$VERSION$$ v1.52-1-g0dae2db
3 |
4 | ############
5 | # NOTE: you MUST run install-hooks.sh again when updating this file!
6 |
7 | # magic to ensure that we're always inside the root of our application,
8 | # no matter from which directory we'll run script
9 | GIT_DIR=$(git rev-parse --git-dir)
10 | cd "${GIT_DIR}/.." || exit 1
11 |
12 | export HOOKDIR="dev/hooks"
13 | LASTPUSH='.git/.lastpush'
14 |
15 | # if any command inside script returns error, exit and return that error
16 | set -e
17 |
18 | printf "Running pre-commit hook\n............................\n"
19 |
20 | unset IFS; set -f
21 |
22 | # check for shellcheck
23 | if command -v shellcheck >/dev/null 2>&1; then
24 | printf "Test all scripts with shellcheck\n"
25 | else
26 | printf "Error: shellcheck is not installed. Please install shellcheck\n"
27 | exit 1
28 | fi
29 |
30 | # run shellcheck before commit
31 | set +f
32 | FILES="$(find ./* -name '*.sh' | grep -v -e 'DIST\/' -e 'STANDALONE\/' -e 'JSON.sh')"
33 | set -f
34 | FILES="${FILES} $(sed '/^#/d' <"dev/shellcheck.files")"
35 | if [ "${FILES}" != "" ]; then
36 | # shellcheck disable=SC2086
37 | shellcheck -o all -e SC2249,SC2154 -x ${FILES} || exit 1
38 | printf " OK\n............................\n"
39 | else
40 | # something went wrong
41 | exit 1
42 | fi
43 |
44 | # get version strings
45 | REMOTEVER="$(git ls-remote -t --refs 2>/dev/null | tail -1 | sed -e 's/.*\/v//' -e 's/-.*//')"
46 | VERSION="$(git describe --tags | sed -e 's/-.*//' -e 's/v//' -e 's/,/./')"
47 | [ -z "${REMOTEVER}" ] && REMOTEVER="${VERSION}"
48 |
49 | # LOCAL version must greater than latest REMOTE release version
50 | printf "Update Version of modified files\n"
51 | if ! command -v bc &> /dev/null || (( $(printf "%s\n" "${VERSION} >= ${REMOTEVER}" | bc -l) )); then
52 | # update version in bashbot files on push
53 | set +f
54 | [ -f "${LASTPUSH}" ] && LASTFILES="$(find ./* -newer "${LASTPUSH}" ! -path "./DIST/*" ! -path "./STANDALONE/*")"
55 | [ "${LASTFILES}" = "" ] && exit
56 | printf " "
57 | # shellcheck disable=SC2086
58 | dev/version.sh ${LASTFILES} 2>/dev/null || exit 1
59 | printf " OK\n............................\n"
60 | else
61 | printf "Error: local version %s must be equal to or greater then release version%s\n" "${VERSION}" "${REMOTEVER}."
62 | printf "use \"git tag vx.zz\" to create a new local version\n"
63 | exit 1
64 | fi
65 |
66 | if command -v codespell &>/dev/null; then
67 | printf "Running codespell\n............................\n"
68 | codespell -q 3 --skip="*.zip,*gz,*.log,*.html,*.txt,.git*,jsonDB-keyboard,DIST,STANDALONE" -L "ba"
69 | printf "if there are (to many) typo's shown, consider running:\ncodespell -i 3 -w --skip=\"*.log,*.html,*.txt,.git*,examples\" -L \"ba\"\n"
70 | else
71 | printf "consider installing codespell: pip install codespell\n"
72 | fi
73 | printf "............................\n"
74 |
75 |
--------------------------------------------------------------------------------
/dev/hooks/pre-push.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #### $$VERSION$$ v1.52-1-g0dae2db
3 |
4 | ############
5 | # NOTE: you MUST run install-hooks.sh again when updating this file!
6 |
7 | # magic to ensure that we're always inside the root of our application,
8 | # no matter from which directory we'll run script
9 | GIT_DIR=$(git rev-parse --git-dir)
10 | cd "${GIT_DIR}/.." || exit 1
11 |
12 | export HOOKDIR="dev/hooks"
13 | LASTPUSH='.git/.lastpush'
14 |
15 | # if any command inside script returns error, exit and return that error
16 | set -e
17 |
18 | printf "Running pre-push hook\n............................\n"
19 |
20 | unset IFS; set -f
21 |
22 | # note date of last push for version
23 | touch "${LASTPUSH}"
24 |
--------------------------------------------------------------------------------
/dev/inject-json.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | ##############################################################
3 | #
4 | # File: inject-json.sh
5 | #
6 | # Description: download and prepare JSON.sh and JSON.awk
7 | #
8 | # Usage: source inject-json.sh
9 | #
10 | #### $$VERSION$$ v1.52-1-g0dae2db
11 | ##############################################################
12 |
13 | # download JSON.sh
14 | JSONSHFILE="JSON.sh/JSON.sh"
15 | if [ ! -r "${JSONSHFILE}" ]; then
16 | printf "Inject JSON.sh ... "
17 | mkdir "JSON.sh" 2>/dev/null
18 | curl -sL -o "${JSONSHFILE}" "https://cdn.jsdelivr.net/gh/dominictarr/JSON.sh/JSON.sh"
19 | chmod +x "${JSONSHFILE}"
20 | printf "Done!\n"
21 | fi
22 |
23 | # download JSON.awk
24 | JSONSHFILE="JSON.sh/JSON.awk.dist"
25 | if [ ! -r "${JSONSHFILE}" ]; then
26 | printf "Inject JSON.awk ... "
27 | curl -sL -o "${JSONSHFILE}" "https://cdn.jsdelivr.net/gh/step-/JSON.awk/JSON.awk"
28 | curl -sL -o "${JSONSHFILE%/*}/awk-patch.sh" "https://cdn.jsdelivr.net/gh/step-/JSON.awk/tool/patch-for-busybox-awk.sh"
29 | chmod +x "${JSONSHFILE}"
30 | printf "Done!\n"
31 | bash "${JSONSHFILE%/*}/awk-patch.sh" "${JSONSHFILE}"
32 | fi
33 | # delete backup files
34 | rm -f "${JSONSHFILE%/*}"/*.bak
35 |
36 |
--------------------------------------------------------------------------------
/dev/install-hooks.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # this has to run once atfer git clone
3 | # and every time we create new hooks
4 | #### $$VERSION$$ v1.52-1-g0dae2db
5 |
6 | #shellcheck disable=SC1090
7 | source "${0%/*}/dev.inc.sh"
8 |
9 | printf "Installing hooks..."
10 | for hook in pre-commit post-commit pre-push
11 | do
12 | rm -f "${GIT_DIR}/hooks/${hook}"
13 | if [ -f "${HOOKDIR}/${hook}.sh" ]; then
14 | printf "%s"" ${hook}"
15 | ln -s "../../${HOOKDIR}/${hook}.sh" "${GIT_DIR}/hooks/${hook}"
16 | fi
17 | done
18 | printf " Done!\n"
19 |
--------------------------------------------------------------------------------
/dev/make-distribution.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | ##############################################################
3 | #
4 | # File: make-distribution.sh
5 | #
6 | # Description: creates files and arcchives to distribute bashbot
7 | #
8 | # Options: --notest - skip tests
9 | #
10 | #### $$VERSION$$ v1.52-1-g0dae2db
11 | ##############################################################
12 |
13 | #shellcheck disable=SC1090
14 | source "${0%/*}/dev.inc.sh"
15 |
16 | VERSION="$(git describe --tags | sed -e 's/-[0-9].*//' -e 's/v//')"
17 |
18 | DISTNAME="telegram-bot-bash"
19 | DISTDIR="./DIST/${DISTNAME}"
20 | DISTMKDIR="data-bot-bash logs bin bin/logs addons"
21 |
22 | DISTFILES="bashbot.sh commands.sh mycommands.sh.clean bin doc examples scripts modules LICENSE README.md README.txt README.html"
23 | DISTFILESDEV="dev/make-standalone.sh dev/inject-json.sh dev/make-html.sh dev/obfuscate.sh"
24 | DISTFILESDIST="mycommands.sh mycommands.conf bashbot.rc $(echo "addons/"*.sh)"
25 |
26 | # run tests first!
27 | for test in $1 dev/all-test*.sh
28 | do
29 | [[ "${test}" == "--notest"* ]] && break
30 | [ ! -x "${test}" ] && continue
31 | if ! "${test}" ; then
32 | printf "ERROR: Test %s failed, can't create dist!\n" "${test}"
33 | exit 1
34 | fi
35 | done
36 |
37 | # create dir for distribution and copy files
38 | mkdir -p "${DISTDIR}" 2>/dev/null
39 |
40 | printf "Copy files\n"
41 | # shellcheck disable=SC2086
42 | cp -r ${DISTFILES} "${DISTDIR}"
43 | mkdir -p "${DISTDIR}/dev"
44 | # shellcheck disable=SC2086
45 | cp ${DISTFILESDEV} "${DISTDIR}/dev"
46 | cd "${DISTDIR}" || exit 1
47 |
48 | printf "Create directories\n"
49 | # shellcheck disable=SC2250
50 | for dir in $DISTMKDIR
51 | do
52 | [ ! -d "${dir}" ] && mkdir "${dir}"
53 | done
54 |
55 | # do not overwrite on update
56 | printf "Create .dist files\n"
57 | for file in ${DISTFILESDIST}
58 | do
59 | [ "${file}" = "addons/*.sh" ] && continue
60 | cp "${BASE_DIR}/${file}" "${file}.dist"
61 | done
62 |
63 | # inject JSON.sh into distribution
64 | # shellcheck disable=SC1090
65 | source "${BASE_DIR}/dev/inject-json.sh"
66 |
67 | # make html doc
68 | printf "Create html doc\n"
69 | # shellcheck disable=SC1090,SC1091
70 | source "../../dev/make-html.sh"
71 |
72 | # create archive
73 | cd .. || exit 1
74 | printf "Create dist archives\n"
75 | # shellcheck disable=SC2046
76 | zip -rq - "${DISTNAME}" --exclude $(cat "${BASE_DIR}/dev/${0##*/}.exclude") >"${DISTNAME}-${VERSION}.zip"
77 | tar --exclude-ignore="${BASE_DIR}/dev/${0##*/}.exclude" -czf "${DISTNAME}-${VERSION}.tar.gz" "${DISTNAME}"
78 |
79 | printf "%s Done!\n" "$0"
80 |
81 | # shellcheck disable=SC2086
82 | ls -ld "${DISTNAME}-${VERSION}".*
83 |
84 | # an empty DEBUG.log is created ... :-(
85 | rm -f "${BASE_DIR}/test/"*.log
86 |
--------------------------------------------------------------------------------
/dev/make-distribution.sh.exclude:
--------------------------------------------------------------------------------
1 | STANDALONE
2 | data-bot-bash/*
3 | test
4 | webhook-fifo*
5 | JSON.awk
6 | bashbot.rc
7 | mycommands.sh
8 | mycommands.conf
9 | awk-patch.sh
10 | make-standalone.sh.include
11 | *.jssh*
12 | botacl
13 | *.flock
14 | *.log
15 | *.last
16 | *.ok
17 | *.bad
18 | *.bak
19 | *.jpg
20 | *.jpeg
21 | *.png
22 | *.zip
23 | *.gz
24 |
--------------------------------------------------------------------------------
/dev/make-html.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | ##############################################################
3 | #
4 | # File: make-html.sh
5 | #
6 | # Description: creates html version from *.md files
7 | #
8 | # Usage: source make-hmtl
9 | #
10 | #### $$VERSION$$ v1.52-1-g0dae2db
11 | ##############################################################
12 |
13 | # check for correct dir
14 | if [[ ! ( -f README.html && -f README.md ) ]]; then
15 | printf "Error: Can't create html, script must run where README.md and README.html is!\n"
16 |
17 | else
18 | # check if pandoc installed
19 | if [ "$(type -t pandoc)" != "file" ]; then
20 | printf "pandoc not found, skipping html generation ...\n"
21 |
22 | else
23 | ########
24 | # everything seems ok, start html generation
25 | printf "Start hmtl conversion "
26 | # create dir for html doc and index.html there
27 | mkdir html 2>/dev/null
28 | cp README.html html/index.html
29 | # convert *.md files in doc to *.hmtl in html
30 | find doc -iname "*.md" -type f -exec sh -c\
31 | 'printf "."; pandoc -s -f commonmark -M "title=Bashobot Documentation - ${0%.md}.html" "$0" -o "./html/$(basename ${0%.md}.html)"' {} \;
32 | # html for examples dir
33 | if [ -d "examples" ]; then
34 | EXAMPLES="examples" # add to final conversion job
35 | find examples -iname "*.md" -type f -exec sh -c\
36 | 'printf "."; pandoc -s -f commonmark -M "title=Bashobot Documentation - ${0%.md}.html" "$0" -o "${0%.md}.html"' {} \;
37 | fi
38 | # final: convert links from *.md to *.html
39 | # shellcheck disable=SC2248
40 | find README.html html ${EXAMPLES} -iname "*.html" -type f -exec sh -c\
41 | 'sed -i -E "s/href=\"(\.\.\/)*doc\//href=\"\1html\//g;s/href=\"(.*).md(#.*)*\"/href=\"\1.html\"/g" $0' {} \;
42 | printf " Done!\n"
43 | fi
44 | fi
45 |
--------------------------------------------------------------------------------
/dev/make-standalone.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | ###################################################################
3 | #
4 | # File: make-standalone.sh
5 | #
6 | # Description:
7 | # even after make-distribution.sh bashbot is not self contained as it was in the past.
8 | #
9 | # Options: --notest
10 | #
11 | # If you your bot is finished you can use make-standalone.sh to create the
12 | # the old all-in-one bashbot: bashbot.sh and commands.sh only!
13 | #
14 | #### $$VERSION$$ v1.52-1-g0dae2db
15 | ###################################################################
16 |
17 | # include git config and change to base dir
18 | incfile="${0%/*}/dev.inc.sh"
19 | #shellcheck disable=SC1090
20 | [ -f "${incfile}" ] && source "${incfile}"
21 |
22 | # seems we are not in a dev env
23 | if [ -z "${BASE_DIR}" ]; then
24 | BASE_DIR="$(pwd)"
25 | [[ "${BASE_DIR}" == *"/dev" ]] && BASE_DIR="${BASE_DIR%/*}"
26 | # go to basedir
27 | cd "${BASE_DIR}" || exit 1
28 | fi
29 |
30 | # see if if bashbot is in base dir
31 | [ ! -f "bashbot.sh" ] && printf "bashbot.sh not found in %s\n" " $(pwd)" && exit 1
32 |
33 | # run pre_commit if exist
34 | [[ -f "dev/dev.inc.sh" && "$1" != "--notest" ]] && dev/hooks/pre-commit.sh
35 |
36 | # files and dirs to copy
37 | #DISTNAME="telegram-bot-bash"
38 | DISTDIR="./STANDALONE"
39 | DISTMKDIR="data-bot-bash logs bin/logs addons"
40 | DISTFILES="bashbot.sh commands.sh mycommands.sh modules scripts LICENSE README.* doc addons"
41 | DISTBINFILES="bin/bashbot_env.inc.sh bin/bashbot_stats.sh bin/process_batch.sh bin/process_update.sh bin/send_broadcast.sh bin/send_message.sh"
42 |
43 | # add extra files, minimum mycommands.conf
44 | extrafile="${BASE_DIR}/dev/${0##*/}.include"
45 | [ ! -f "${extrafile}" ] && printf "bashbot.rc\nbotacl\nbotconfig.jssh\nmycommands.conf\ndev/obfuscate.sh\n" >"${extrafile}"
46 | DISTFILES+=" $(<"${extrafile}")"
47 |
48 | # create dir for distribution and copy files
49 | printf "Create directories and copy files\n"
50 | mkdir -p "${DISTDIR}/bin" 2>/dev/null
51 | # shellcheck disable=SC2086
52 | cp -rp ${DISTFILES} "${DISTDIR}" 2>/dev/null
53 | # shellcheck disable=SC2086
54 | cp -p ${DISTBINFILES} "${DISTDIR}/bin" 2>/dev/null
55 |
56 | cd "${DISTDIR}" || exit 1
57 |
58 | # remove log files
59 | find . -name '*.log' -delete
60 |
61 | # shellcheck disable=SC2250
62 | for dir in $DISTMKDIR
63 | do
64 | [ ! -d "${dir}" ] && mkdir "${dir}"
65 | done
66 |
67 | # inject JSON.sh into distribution
68 | # shellcheck disable=SC1090
69 | source "${BASE_DIR}/dev/inject-json.sh"
70 |
71 | #######################
72 | # here the magic starts
73 | # create all in one bashbot.sh file
74 |
75 | printf "OK, now lets do the magic ...\n\t... create unified commands.sh\n"
76 |
77 | {
78 | # first head of commands.sh
79 | sed -n '0,/^if / p' commands.sh | grep -v -F -e "___" -e "*MUST*" -e "mycommands.sh.dist" -e "mycommands.sh.clean"| head -n -2
80 |
81 | # then mycommands from first non comment line on
82 | printf '\n##############################\n# my commands starts here ...\n'
83 | sed -n '/^$/,$ p' mycommands.sh
84 |
85 | # last tail of commands.sh
86 | printf '\n##############################\n# default commands starts here ...\n'
87 | sed -n '/source .*\/mycommands.sh"/,$ p' commands.sh | tail -n +2
88 |
89 | } >>$$commands.sh
90 |
91 | mv $$commands.sh commands.sh
92 | rm -f mycommands.sh
93 |
94 | printf "\t... create unified bashbot.sh\n"
95 |
96 | {
97 | # first head of bashbot.sh
98 | sed -n '0,/for module in/ p' bashbot.sh | head -n -3
99 |
100 | # then modules without shebang
101 | printf '\n##############################\n# bashbot modules starts here ...\n'
102 | # shellcheck disable=SC2016
103 | cat modules/*.sh | sed -e 's/^#\!\/bin\/bash.*//' -e '/^#.*\$\$VERSION\$\$/d'
104 |
105 | # last remaining commands.sh
106 | printf '\n##############################\n'
107 | sed -n '/^# read commands file/,$ p' bashbot.sh
108 |
109 | } >>$$bashbot.sh
110 |
111 | mv $$bashbot.sh bashbot.sh
112 | chmod +x bashbot.sh
113 |
114 | rm -rf modules
115 |
116 | printf "Create minimized Version of bashbot.sh and commands.sh\n"
117 | # shellcheck disable=SC2016
118 | sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e '/shellcheck/! s/\t+#.*//' -e 's/^[[:space:]]*//'\
119 | -e '/^$/d' bashbot.sh | sed 'N;s/\\\n/ /;P;D' | sed 'N;s/\\\n/ /;P;D' > bashbot.sh.min
120 | # shellcheck disable=SC2016
121 | sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e '/shellcheck/! s/\t+#.*//' -e 's/^[[:space:]]*//'\
122 | -e '/^$/d' commands.sh | sed 'N;s/\\\n/ /;P;D' > commands.sh.min
123 | chmod +x bashbot.sh.min
124 |
125 | # make html doc
126 | printf "Create html doc\n"
127 | #shellcheck disable=SC1090
128 | source "${BASE_DIR}/dev/make-html.sh"
129 |
130 | printf "%s Done!\n" "$0"
131 |
132 | cd .. || exit 1
133 |
134 | printf "\nStandalone bashbot files are now available in %s:\n\n" "${DISTDIR}"
135 | ls -l "${DISTDIR}"
136 |
137 |
--------------------------------------------------------------------------------
/dev/make-standalone.sh.include:
--------------------------------------------------------------------------------
1 | bashbot.rc
2 | botacl
3 | botconfig.jssh
4 | mycommands.conf
5 | dev/obfuscate.sh
6 |
--------------------------------------------------------------------------------
/dev/obfuscate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # joke hack to obfuscate bashbot.min.sh
4 | #
5 | #### $$VERSION$$ v1.52-1-g0dae2db
6 | # shellcheck disable=SC2028,SC2016,SC1117
7 |
8 | infile="bashbot.sh"
9 | outfile="./bashbot.obf.sh"
10 |
11 | if [ ! -f "${infile}" ]; then
12 | printf "This is a hack to obfuscate %s, run me in STANDALONE after running make-standalone.sh\n" "${infile}"
13 | exit 1
14 | fi
15 | # create gzipped base64 encoded file plus commands to decode
16 | {
17 | # shellcheck disable=SC2183
18 | printf '#!/bin/bash\na="$PWD";cd "$(mktemp -d)"||exit;%s'\
19 | 'printf '"'$(gzip -9 <"${infile}" | base64)'"'|base64 -d|gunzip >a;export BASHBOT_HOME="$a";chmod +x a;./a "$@";a="$PWD";cd ..;rm -rf "$a"'
20 | } >"${outfile}"
21 |
22 | chmod +x "${outfile}"
23 | ls -l "${outfile}"
24 | printf "Try to run %s init ;-)\n" "${outfile}"
25 |
--------------------------------------------------------------------------------
/dev/shellcheck.files:
--------------------------------------------------------------------------------
1 | # list of additional files to check from shellcheck
2 | #### $$VERSION$$ v1.52-1-g0dae2db
3 | bashbot.rc
4 | mycommands.conf
5 | mycommands.sh.clean
6 |
--------------------------------------------------------------------------------
/dev/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | #### $$VERSION$$ v1.52-1-g0dae2db
4 | # shellcheck disable=SC2016
5 | #
6 | # Easy Versioning in git:
7 | #
8 | # for setting your Version in git use e.g.:
9 | # git tag -a v0.5 -m 'Version 0.5'
10 | #
11 | # Push tags upstream—this is not done by default:
12 | # git push --tags
13 | #
14 | # # in case of a wrong tag remove it:
15 | # git tag -d v0.5
16 | #
17 | # delete remote tag (eg, GitHub version)
18 | # git push origin :refs/tags/v0.5
19 | #
20 | # Then use the describe command:
21 | #
22 | # git describe --tags --long
23 | # This gives you a string of the format:
24 | #
25 | # v0.5-0-gdeadbee
26 | # ^ ^ ^^
27 | # | | ||
28 | # | | |'-- SHA of HEAD (first seven chars)
29 | # | | '-- "g" is for git
30 | # | '---- number of commits since last tag
31 | # |
32 | # '--------- last tag
33 | #
34 | # run this script to (re)place Version number in files
35 | #
36 |
37 | #shellcheck disable=SC1090
38 | source "${0%/*}/dev.inc.sh"
39 |
40 | unset IFS
41 | # set -f # if you are paranoid use set -f to disable globbing
42 |
43 | VERSION="$(git describe --tags --long)"
44 | printf "Update to version %s ...\n" "${VERSION}"
45 |
46 | # only regular files, ignore .dot files/dirs, e.g. .git .gitinore in BASEDIR
47 | if [ -n "$1" ]; then
48 | FILES="$*"
49 | else
50 | printf "Update version string in all files? (y/N)\b\b"
51 | read -r answer
52 | [[ "${answer}" != "y" && "${answer}" != "Y" ]] && exit
53 | FILES="$(find ./* -type f ! -path "./DIST/*" ! -path "./STANDALONE/*")"
54 | fi
55 |
56 | # autogenerate REMADME.html REMADE.txt
57 | if [[ "${FILES}" == *"README.md"* ]]; then
58 | FILES+=" README.html README.txt"
59 | type -f pandoc >/dev/null && pandoc -s -f commonmark -M "title=Bashbot README" README.md >README.html
60 | cat "doc/bashbot.ascii" >"README.txt"
61 | if [ -r "README.html" ] && type -f html2text >/dev/null; then
62 | # convert html links to text [link]
63 | sed -E 's/([^<#]+)<\/a>/\2 [\1]/g' >README.txt
65 | else
66 | type -f fold >/dev/null && fold -s -w 90 README.md >>README.txt
67 | fi
68 | fi
69 |
70 | # change version string in given files
71 | for file in ${FILES}
72 | do
73 | # symlink is a file :-(
74 | [[ -L "${file}" || ! -f "${file}" ]] && continue
75 | #[ "${file}" == "version" ] && continue
76 | printf "%s" " ${file}" >&2
77 | sed -i 's/^#### $$VERSION$$.*/#### \$\$VERSION\$\$ '"${VERSION}"'/' "${file}"
78 | done
79 |
80 | printf " done.\n"
81 |
82 |
--------------------------------------------------------------------------------
/doc/0_install.md:
--------------------------------------------------------------------------------
1 | #### [Home](../README.md)
2 |
3 | ## Check bash installation
4 |
5 | There may systems where bash seems to be installed but it is not (_e.g. embedded systems_) or where bash is to old.
6 | Bashbot has some builtin checks but it may better to check before installing bashbot.
7 |
8 | Run the following commands to see if your bash looks ok ...
9 |
10 | ```bash
11 | # system say bash is there?
12 | if which bash; then echo "bash seems available..."; else echo "NO bash"; fi
13 |
14 | # real bash supports ARRAY
15 | bash -c 'if eval "a[1]=1"; then echo "Shell support arrays..."; else echo "Shell has NO arrays"; fi'
16 |
17 | # check for bash version by feature
18 | bash -c 'if [ "$(LANG=C.UTF-8 echo -e "\u1111")" != "\u1111" ]; then echo "Bash version ok ..."; else echo "Bash version may to old ..."; fi'
19 |
20 | # display bash version, must be greater than 4.3
21 | bash --version | grep "bash"
22 | ```
23 |
24 | ## Install bashbot
25 |
26 | Installing bashbot is very simple: Download and extract the installation archive.
27 |
28 | 1. Choose a directory to install bashbot (_e.g.your HOME or /usr/local_)
29 | 2. Download [latest release zip / tar archive](https://github.com/topkecleon/telegram-bot-bash/releases/latest) and extract all files.
30 | 3. Change into the directory `telegram-bot-bash`
31 | 4. Copy `mycommands.conf.dist` `mycommands.conf`
32 | 4. Copy `mycommands.sh.dist` or `mycommands.sh.clean` to `mycommands.sh`
33 | 5. Run `./bashbot.sh init`\* to setup the environment and enter your Bots token given by botfather.
34 |
35 | Edit config in `mycommands.conf` and commands in `mycommands.sh` to fit your need.
36 | Now your Bot is ready to start ...
37 |
38 | *If you are new to Bot development read [Bots: An introduction for developers](https://core.telegram.org/bots)*
39 |
40 | \* _Run with sudo if you want to run bashbot from different user, e.g. from `bashbot.rc`._
41 |
42 | ### Update bashbot
43 |
44 | Update bashbot is almost identical to installing bashbot: Download and extract the installation archive.
45 |
46 | **Important: All files may overwritten, make a backup!**
47 |
48 | 1. Go to the directory where bashbot is installed (_e.g.$HOME/telegram-bot-bash or /usr/local/telegram-bot-bash_)
49 | 2. Download [latest release zip / tar archive](https://github.com/topkecleon/telegram-bot-bash/releases/latest)
50 | 3. Stop all running instances of bashbot `./bashbot.sh stop`
51 | 4. Change to parent directory of bashbot installation and extract all files from archive.
52 | 5. Run `./bashbot.sh init`\* to setup your environment after the update
53 | 6. Restart your bot `./bashbot.sh start`
54 |
55 | `mycommands.conf` and `mycommands.sh` will not overwritten, this avoids losing your bot config and commands on updates.
56 |
57 | *Note*: If you are updating from a pre-1.0 version, update to [Version 1.20](https://github.com/topkecleon/telegram-bot-bash/releases/tags/v1.20) first!
58 |
59 | ### Use JSON.awk
60 |
61 | [JSON.awk](https://github.com/step-/JSON.awk) is an awk port of `JSON.sh`, it provides the same functionality but is 5 times faster.
62 | On most systems you can use `JSON.awk` with system default awk installation.
63 | ( [gnu awk, posix awk, mawk, busybox akw](https://github.com/step-/JSON.awk#compatibility-with-awk-implementations) ).
64 |
65 | After you have checked that `JSON.awk.dist` is working on your system copy it to `JSON.awk` and (re)start bashbot.
66 |
67 | BSD and MacOS users must install `gnu awk` and adjust the shebang, see below
68 |
69 | *Note*: To install or update `JSON.awk` manually execute the following commands in the directory `JSON.sh/`:
70 |
71 | wget https://cdn.jsdelivr.net/gh/step-/JSON.awk/JSON.awk
72 | wget https://cdn.jsdelivr.net/gh/step-/JSON.awk/tool/patch-for-busybox-awk.sh
73 | bash patch-for-busybox-awk.sh
74 | chmod +x JSON.awk
75 |
76 |
77 | ### Install bashbot from git repo
78 |
79 | Installation and updates should be done using the zip / tar archives provided on github to avoid
80 | problems and not overwriting your bot config and `mycommands.sh`.
81 |
82 | Nevertheless you can install or update bashbot from a git repo, see next chapter ...
83 |
84 |
85 | ### Create Installation / Update archives
86 |
87 | To install or update bashbot from git repo execute `dev/make-distribution.sh`.
88 | This creates the installation archives in `DIST/` and a ready to run test installation in `DIST/telegram.bot-bash`.
89 |
90 | *Note:* You should be familiar with `git`.
91 |
92 | 1. Run `git clone https://github.com/topkecleon/telegram-bot-bash.git`
93 | 2. Change into the directory `telegram-bot-bash`
94 | 3. Optional: Run ` git checkout develop` for latest develop version
95 | 4. Run ` dev/make-distribution.sh` (_add --notest to skip tests_)
96 | 5. Change to dir `DIST/`
97 |
98 | Use the installation archives to install or update bashbot as described above.
99 |
100 | To run a test bot, e.g. while development or testing latest changes, you can use the bashbot installation provided in `DIST/telegram-bot-bash`.
101 | To update the test installation (_after git pull, local changes or switch master/develop_) run `dev/make-distribution.sh` again.
102 |
103 |
104 | ### Note for BSD and MacOS
105 |
106 | **On MacOS** you must install a more recent version of bash, as the default bash is way to old,
107 | see e.g. [Install Bash on Mac](http://macappstore.org/bash/)
108 |
109 | **On BSD and MacOS** I recommend to install gnu coreutils and include them in your PATH
110 | environment variable before running bashbot, e.g. the gnu versions of sed, grep, find, awk ...
111 |
112 | On BSD and MacOS you must adjust the shebang line of the scripts `bashbot.sh` and `json.sh` to point to to the correct bash
113 | or use the script: `examples/bash2env *.sh */*.sh` to convert them for you.
114 |
115 | Bashbot will stay with `#!/bin/bash` shebang, as using a fixed path is IMHO more secure than the portable '!/usr/bin/env bash` variant.
116 |
117 | Compatibility with BSD/MacOS will result in a rewrite of all grep/sed commands with an uncertain outcome,
118 | see [BSD/MacOS vs. GNU sed](https://riptutorial.com/sed/topic/9436/bsd-macos-sed-vs--gnu-sed-vs--the-posix-sed-specification)
119 | to get an impression how different they are.
120 |
121 |
122 | ### Notes on Changes
123 |
124 | #### Config moved to mycommands.conf
125 |
126 | From Version 1.30 on config for new bots is moved to `mycommands.conf`.
127 |
128 | #### Support for update from pre-1.0 removed
129 |
130 | From Version 1.21 on updating from a pre-1.0 version (_no \*.jssh config_) is no more supported!
131 | You must update to [Version 1.20](https://github.com/topkecleon/telegram-bot-bash/releases/tags/v1.20) first!
132 |
133 | #### [Next Create Bot](1_firstbot.md)
134 |
135 | #### $$VERSION$$ v1.52-1-g0dae2db
136 |
137 |
--------------------------------------------------------------------------------
/doc/1_firstbot.md:
--------------------------------------------------------------------------------
1 | #### [Home](../README.md)
2 | ## Create a Telegram Bot with Botfather
3 | **[BotFather is 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)
4 |
5 | ### Creating a new Bot
6 |
7 | 1. Message @botfather https://telegram.me/botfather with the following
8 | text: `/newbot`
9 | If you don't know how to message by username, click the search
10 | field on your Telegram app and type `@botfather`, you should be able
11 | to initiate a conversation. Be careful not to send it to the wrong
12 | contact, because there are users with a similar username.
13 |
14 | 
15 |
16 | 2. @botfather replies with `Alright, a new bot. How are we going to
17 | call it? Please choose a name for your bot.`
18 |
19 | 3. Type whatever name you want for your bot.
20 |
21 | 4. @botfather replies with `Good. Now let's choose a username for your
22 | bot. It must end in bot. Like this, for example: TetrisBot or
23 | tetris_bot.`
24 |
25 | 5. Type whatever username you want for your bot, minimum 5 characters,
26 | and must end with `bot`. For example: `telesample_bot`
27 |
28 | 6. @botfather replies with:
29 |
30 | Done! Congratulations on your new bot. You will find it at
31 | telegram.me/telesample_bot. You can now add a description, about
32 | section and profile picture for your bot, see /help for a list of
33 | commands.
34 |
35 | Use this token to access the HTTP API:
36 | 123456789:AAG90e14-0f8-40183D-18491dDE
37 |
38 | For a description of the Bot API, see this page:
39 | https://core.telegram.org/bots/api
40 |
41 | 7. Note down the 'token' mentioned above.
42 |
43 | 8. Type `/setprivacy` to @botfather.
44 |
45 | 
46 |
47 | 9. @botfather replies with `Choose a bot to change group messages settings.`
48 |
49 | 10. Type `@telesample_bot` (change to the username you set at step 5
50 | above, but start it with `@`)
51 |
52 | 11. @botfather replies with
53 |
54 | 'Enable' - your bot will only receive messages that either start
55 | with the '/' symbol or mention the bot by username.
56 | 'Disable' - your bot will receive all messages that people send to groups.
57 | Current status is: ENABLED
58 |
59 | 12. Type `Disable` to let your bot receive all messages sent to a
60 | group. This step is up to you actually.
61 |
62 | 13. @botfather replies with `Success! The new status is: DISABLED. /help`
63 |
64 |
65 | #### [Prev Installation](0_install.md)
66 | #### [Next Getting started](2_usage.md)
67 |
68 | #### $$VERSION$$ v1.52-1-g0dae2db
69 |
70 |
--------------------------------------------------------------------------------
/doc/5_practice.md:
--------------------------------------------------------------------------------
1 | #### [Home](../README.md)
2 | ## Best Practices
3 |
4 | ### New to bot development?
5 |
6 | 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/).
7 |
8 | 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)
9 |
10 | If you don't have a github account, it may time to [setup a free account now](https://github.com/pricing)
11 |
12 | ### Add commands to mycommands.sh only
13 | Do not change `bashbot.sh` and `commands.sh`, instead place your commands in to `mycommands.sh`.
14 | To start with a clean/minimal bot copy `mycommands.sh.clean` to `mycommands.sh` and start editing
15 | the message strings and place commands in the` case ... esac` block of the function mycommands():
16 | ```bash
17 | # file: mycommands.sh
18 | # your additional bashbot commands
19 |
20 | # uncomment the following lines to overwrite info and help messages
21 | bashbot_info='This is *MY* variant of _bashbot_, the Telegram bot written entirely in bash.
22 | '
23 |
24 | bashbot_help='*Available commands*:
25 | /echo message - _echo the given messsage_
26 | '
27 |
28 | # NOTE: command can have @botname attached, you must add * in case tests...
29 | mycommands() {
30 |
31 | case "$MESSAGE" in
32 | '/echo'*) # example echo command
33 | send_normal_message "${CHAT[ID]}" "$MESSAGE"
34 | ;;
35 | # .....
36 | esac
37 | }
38 | ```
39 |
40 | ### DIsable, replace and extend global commands
41 |
42 | Global bashbot command processing, e.g. /start, /info etc. is disabled if you return a non zero value from `mycommands.sh`,
43 | see /start example below.
44 |
45 | To replace a global bashbot command add the same command to `mycommands.sh` and place `return 1` at the end of
46 | the case block, see /kickme example below.
47 |
48 | If a command is available as a global command and in `mycommands.sh`, plus you return a zero value (nothing or 0)
49 | both command sections are processed. Thus you can extend global commands with additional actions, see /info example below
50 |
51 | **Learn more about [Bot commands](https://core.telegram.org/bots#commands).**
52 |
53 | ```bash
54 | # file: mycommands.sh
55 |
56 | case "$MESSAGE" in
57 | ##########
58 | # disable start command
59 | '/start'*) # disable all commands starting with leave
60 | return 1
61 | ;;
62 | # replace command with your own actions
63 | '/kickme'*) # this will replace the /kickme command
64 | send_markdown_mesage "${CHAT[ID]}" "*This bot will not kick you!*"
65 | return 1
66 | ;;
67 | # extend global command
68 | '/info'*) # output date in front of regular info
69 | send_normal_message "${CHAT[ID]}" "$(date)"
70 | return 0
71 | ;;
72 | esac
73 | ```
74 |
75 |
76 | ### Separate logic from commands
77 |
78 | 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:
79 | ```bash
80 | # file: mycommands.sh
81 | # your additional bashbot commands
82 |
83 | mycommands() {
84 |
85 | case "$MESSAGE" in
86 | '/doit'*) # logic for /doit is done in process_message
87 | result="$(process_message "$MESSAGE")"
88 | send_normal_message "${CHAT[ID]}" "$result"
89 | ;;
90 | esac
91 |
92 | }
93 |
94 | # place your functions here
95 |
96 | process_message() {
97 | local ARGS="${1#/* }" # remove command
98 | local TEXT OUTPUT=""
99 |
100 | # process every word in MESSAGE, avoid globbing
101 | set -f
102 | for WORD in $ARGS
103 | do
104 | # process links
105 | if [[ "$WORD" == "https://"* ]]; then
106 | REPORT="$(dosomething_with_link "$WORD")"
107 | # no link, add as text
108 | else
109 | TEXT="$(echo "${TEXT} $WORD")"
110 | continue
111 | fi
112 | # compose result
113 | OUTPUT="* ${REPORT} ${WORD} ${TEXT}"
114 | TEXT=""
115 | done
116 |
117 | # return result, reset globbing in case we had no ARGS
118 | echo "${OUTPUT}${TEXT}"
119 | }
120 |
121 | ```
122 |
123 | ### Test your Bot with shellcheck
124 | 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).
125 | All bashbot scripts are linted by shellcheck.
126 |
127 | Shellcheck examples:
128 | ```bash
129 | $ shellcheck -x mybotcommands.inc.sh
130 |
131 | Line 17:
132 | TEXT="$(echo "${TEXT} $WORD")"
133 | ^-- SC2116: Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'.
134 |
135 | ```
136 |
137 | As you can see my `mybotcommands.inc.sh` contains an useless echo command in 'TEXT=' assignment and can be replaced by `TEXT="${TEXT}${WORD}"`
138 |
139 | ```bash
140 | $ shellcheck -x examples/notify
141 | OK
142 | $ shellcheck -x examples/question
143 | OK
144 | $ shellcheck -x commands.sh
145 | OK
146 | $ shellcheck -x bashbot.sh
147 |
148 | In bashbot.sh line 123:
149 | text="$(echo "$text" | sed 's/ mynewlinestartshere /\r\n/g')" # hack for linebreaks in startproc scripts
150 | ^-- SC2001: See if you can use ${variable//search/replace} instead.
151 |
152 |
153 | In bashbot.sh line 490:
154 | CONTACT[USER_ID]="$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","contact","user_id"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")"
155 | ^-- SC2034: CONTACT appears unused. Verify it or export it.
156 | ```
157 | 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.
158 | 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 :-)
159 |
160 | #### [Prev Best Practice](5_practice.md)
161 | #### [Next Functions Reference](6_reference.md)
162 |
163 | #### $$VERSION$$ v1.52-1-g0dae2db
164 |
165 |
--------------------------------------------------------------------------------
/doc/bashbot.ascii:
--------------------------------------------------------------------------------
1 |
2 | ..
3 | ****
4 | ****oooooo*****
5 | *****ooooooooooooo*****
6 | *****oooooooooooooooooooooo****
7 | ****oooooooooooooooooooooooooooooooo**
8 | *.*oooooooooooooooooooooooooooooooooooo**
9 | *.ooooooooooooooooooooooooooooooooo**....
10 | *.oooooooooooooooooooooooooooo**.........
11 | *.oooooooooooooooooooooooo**.............
12 | *.ooooooooooooooooooo**.................. ____ _ _ _
13 | *.ooooooooooooooooo*.......,............. | _ \ | | | | | |
14 | *.ooooooooooooooooo*.....,***,........... | |_) | __ _ ___ | |__ | |__ ___ | |_
15 | *.ooooooooooooooooo*....o*............... | _ < / _` |/ __|| '_ \ | '_ \ / _ \ | __|
16 | *.ooooooooooooooooo*....*o***,........... | |_) || (_| |\__ \| | | || |_) || (_) || |_
17 | *.*oooooooooooooooo*........o*.....oo.... |____/ \__,_||___/|_| |_||_.__/ \___/ \__|
18 | ****ooooooooooooo*....`***....oo.....*
19 | *****oooooooo*......*..oo.....**
20 | ******ooo*.............*
21 | ***o*........**
22 | **...**
23 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | #### [Home](../README.md)
2 |
3 | ## Bashbot examples
4 |
5 | ### bashbot multi
6 | An example wrapper to run multiple instances of bashbot, use ```./bashbot-multi.sh botname command```
7 |
8 | ### bashbot.cron
9 | An example crontab is provided in ```examples/bashbot.cron```, see [Expert use](../doc/4_expert.md#Scedule-bashbot-from-Cron)
10 |
11 |
12 | ### Interactive chats
13 | Two examples for interactive scripts are provided as **calc.sh** and **question.sh**, see [Advanced use](../doc/3_advanced.md#Interactive-Chats)
14 |
15 | ### Background scripts
16 |
17 | Background jobs are an easy way to provide sceduled messages or alerts if something happens.
18 | **notify.sh** is a simple example on how to send a message every x seonds, e.g. current time.
19 |
20 | **background-scripts** contains a more useful example on how to start and stop different scripts plus some example background scripts.
21 |
22 | ```
23 | mycommands.sh - /run_xxx and /kill-xxx will start any script named run_xxx.sh
24 |
25 | run_diskusage.sh - shows disk usage every 100 seconds
26 | run_filename.sh - shown the name of new files in a named dir
27 | run_filecontent.sh - shown the content of new files in a named dir
28 | run_notify.sh - same as notify.sh
29 | ```
30 | **Note:** Output of system commands often contains newlines, each newline results in a telegram message, the function 'send_telegram' in
31 | mycommands.sh avoids this by converting each newline to ' mynewlinestartshere ' before output the string.
32 |
33 | ### System Status
34 |
35 | **send-system-status** contains an example for commands showing status of different subsystems. This example is adapted from
36 | https://github.com/RG72/telegram-bot-bash to current bashbot commands, but not fully tested. This will show how easy you can
37 | convert existing bots.
38 |
39 | ```
40 | mycommands.sh - commands to show system status
41 | botacl - controls who can show system status
42 |
43 | *Available commands*:
44 | /se *sensors*
45 | /smb *smbstatus*
46 | /free *memory status*
47 | /md *raid status*
48 | /lvm *lvm status*
49 | /lvsd *Datailed lvm status*
50 | /df *disk space*
51 | /ifconfig *ifconfig output*
52 | /smart *sda* _smart status for sda drive_
53 | ```
54 | ### jsonDB and Keyboards
55 |
56 | **jsonDB-keybords** contains a stripped down real world example from my bot showing the usage of jsonDB to store and retrieve values
57 | plus use of keyboards in private chats. It's an extended version of mycommands.sh.dist. Messages and help are in german.
58 |
59 | ### Webhook
60 |
61 | **Webhook** contains instructions on how use webhook API to get updates from telegram instead polling Telegram server.
62 |
63 | #### $$VERSION$$ v1.52-1-g0dae2db
64 |
65 |
66 |
--------------------------------------------------------------------------------
/examples/background-scripts/mycommands.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # files: mycommands.sh.dist
3 | # copy to mycommands.sh and add all your commands an functions here ...
4 | export res
5 |
6 | # your additional bashbot commands ...
7 | mycommands() {
8 |
9 | case "${MESSAGE}" in
10 | '/run_'*)
11 | myback="run_${MESSAGE#*_}"
12 | if [ -x "./${myback}.sh" ]; then
13 | checkback "${myback}"
14 | if [ "${res}" -gt 0 ] ; then
15 | send_normal_message "${CHAT[ID]}" "Start ${myback}, use /kill${myback} to stop it."
16 | background "./${myback}.sh" "${myback}"
17 | else
18 | send_normal_message "${CHAT[ID]}" "Background job ${myback} already running."
19 | fi
20 | fi
21 | ;;
22 | '/kill_'*)
23 | myback="run_${MESSAGE#*_}"
24 | if [ -x "./${myback}.sh" ]; then
25 | checkback "${myback}"
26 | if [ "${res}" -eq 0 ] ; then
27 | killback "${myback}"
28 | send_normal_message "${CHAT[ID]}" "Stopping ${myback}, use /run_${myback} to start again."
29 | else
30 | send_normal_message "${CHAT[ID]}" "No background job ${myback}."
31 | fi
32 | fi
33 | ;;
34 | esac
35 | }
36 |
37 | # place your additional processing functions here ...
38 |
39 | # inifnite loop for waching a given dir for new files
40 | # $1 dir to wtach for new files
41 | watch_dir_loop() {
42 | local newfile old
43 | [ ! -d "$1" ] && echo "ERROR: no directory $1 found!" >&2 && exit 1
44 | # wait for new files in WATCHDIR
45 | inotifywait -q -m "$1" -e create --format "%f" \
46 | | while true
47 | do
48 | # read in newfile
49 | read -r newfile
50 |
51 | #skip if not match or same name as last time
52 | [ "${newfile}" = "${old}" ] && continue
53 | sleep 0.2
54 |
55 | # process content and output message
56 | echo "$(date): new file: ${newfile}" >>"$0.log"
57 | # note: loop callback must a function in the calling script!
58 | if _is_function loop_callback ; then
59 | loop_callback "$1/${newfile}"
60 | else
61 | echo "ERROR: loop_callback not found!" >&2
62 | exit 1
63 | fi
64 | done
65 | } # 2>>"$0.log"
66 |
67 |
68 | output_telegram() {
69 | # output to telegram
70 | sed <<< "${1}" -e ':a;N;$!ba;s/\n/ mynewlinestartshere /g'
71 | } # 2>>"$0.log"
72 |
73 | # name and location of the tml file
74 |
75 | # $1 string to output
76 | # $2 file to add file to
77 | output_html_file() {
78 | local date
79 | date="$(date)"
80 | output_file "$(sed <<< "$1
${date}
" '
81 | s/ my[a-z]\{3,15}\(start\|ends\)here.*
/
/g
82 | s/ *mynewlinestartshere */
/
83 | s/\n/
/
84 | ')"
85 | } # >>"$0.log" 2>&1
86 |
87 | # $1 string to output
88 | # $2 file to add file to
89 | output_file() {
90 | local publish="${2}"
91 | [ ! -w "${publish}" ] && echo "ERROR: file ${publish} is not writeable or does not exist!" && exit
92 |
93 | # output at beginnung of file, add date to message
94 | sed <<< "${1}" '
95 | s/ *mynewlinestartshere */\n/
96 | s/ my[a-z]\{3,15}\(start\|ends\)here.*//g
97 | ' >"${publish}$$"
98 | cat "${publish}" >>"${publish}$$"
99 | mv "${publish}$$" "${publish}"
100 | } # >>"$0.log" 2>&1
101 |
102 |
--------------------------------------------------------------------------------
/examples/background-scripts/run_diskusage.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: run_diskusage.sh
3 | # example for an background job display a system value
4 | #
5 | # This file is public domain in the USA and all free countries.
6 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
7 | #### $$VERSION$$ v1.52-1-g0dae2db
8 |
9 | ######
10 | # parameters
11 | # $1 $2 args as given to starct_proc chat script arg1 arg2
12 | # $3 path to named pipe/log
13 |
14 |
15 | # adjust your language setting here
16 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
17 | export 'LC_ALL=C.UTF-8'
18 | export 'LANG=C.UTF-8'
19 | export 'LANGUAGE=C.UTF-8'
20 |
21 | unset IFS
22 | # set -f # if you are paranoid use set -f to disable globbing
23 |
24 | # discard STDIN for background jobs!
25 | cat >/dev/null &
26 |
27 | # shellcheck source=examples/background-scripts/mycommands.sh
28 | source "./mycommands.sh"
29 |
30 | # check if $1 is a number
31 | regex='^[0-9]+$'
32 | if [[ $1 =~ ${regex} ]] ; then
33 | SLEEP="$1"
34 | else
35 | SLEEP=100 # time between time notifications
36 | fi
37 |
38 | NEWLINE=$'\n'
39 |
40 | # output disk usage every $1 seconds
41 | WAIT=0
42 | while sleep "${WAIT}"
43 | do
44 | output_telegram "Current Disk usage ${NEWLINE} $(df -h / /tmp /usr /var /home)"
45 | # only for testing, delete echo line for production ...
46 | echo "Current Disk usage ${NEWLINE} $(df -h / /tmp /usr /var /home)"
47 | WAIT="${SLEEP}"
48 | done
49 |
50 |
--------------------------------------------------------------------------------
/examples/background-scripts/run_filecontent.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: run_filename
3 | # background job to display content of all new files in WATCHDIR
4 | #
5 | #### $$VERSION$$ v1.52-1-g0dae2db
6 |
7 | ######
8 | # parameters
9 | # $1 $2 args as given to starct_proc chat script arg1 arg2
10 | # $3 path to named pipe/log
11 |
12 |
13 | # adjust your language setting here
14 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
15 | export 'LC_ALL=C.UTF-8'
16 | export 'LANG=C.UTF-8'
17 | export 'LANGUAGE=C.UTF-8'
18 |
19 | unset IFS
20 | # set -f # if you are paranoid use set -f to disable globbing
21 |
22 | # discard STDIN for background jobs!
23 | cat >/dev/null &
24 |
25 | # watch for new files created by a trusted program
26 | WATCHDIR="/my_trusted/dir_to_watch"
27 |
28 | # shellcheck source=examples/background-scripts/mycommands.sh
29 | source "./mycommands.sh"
30 |
31 | # test your script and the remove ...
32 | WATCHDIR="/tmp/bottest"
33 |
34 | NEWLINE='mynewlinestartshere'
35 |
36 | # this is called by watch dir loop
37 | # $1 is name of the new file
38 | loop_callback() {
39 | # output content of file, you must trust creator because content is sent as message!
40 | output_telegram "Contents of ${1}: ${NEWLINE} $(cat "${1}")"
41 | }
42 |
43 | watch_dir_loop "${WATCHDIR}"
44 |
--------------------------------------------------------------------------------
/examples/background-scripts/run_filename.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: run_filename
3 | # background job to display all new files in WATCHDIR
4 | #
5 | #### $$VERSION$$ v1.52-1-g0dae2db
6 |
7 | ######
8 | # parameters
9 | # $1 $2 args as given to starct_proc chat script arg1 arg2
10 | # $3 path to named pipe/log
11 |
12 |
13 | # adjust your language setting here
14 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
15 | export 'LC_ALL=C.UTF-8'
16 | export 'LANG=C.UTF-8'
17 | export 'LANGUAGE=C.UTF-8'
18 |
19 | unset IFS
20 | # set -f # if you are paranoid use set -f to disable globbing
21 |
22 | # shellcheck source=examples/background-scripts/mycommands.sh
23 | cat >/dev/null &
24 |
25 | # watch for new logfiles
26 | WATCHDIR="/var/log"
27 |
28 | # shellcheck disable=SC1091
29 | source "./mycommands.sh"
30 |
31 | # test your script and the remove ...
32 | WATCHDIR="/tmp/bottest"
33 |
34 | # this is called by watch dir loop
35 | # $1 is name of the new file
36 | loop_callback() {
37 | # output one simple line ...
38 | echo "New file ${1} created in ${WATCHDIR}!"
39 | }
40 |
41 | watch_dir_loop "${WATCHDIR}"
42 |
43 |
--------------------------------------------------------------------------------
/examples/background-scripts/run_notify.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: notify.sh
3 | # example for an background job, run with startback notify.sh
4 | #
5 | # This file is public domain in the USA and all free countries.
6 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
7 | #### $$VERSION$$ v1.52-1-g0dae2db
8 |
9 | ######
10 | # parameters
11 | # $1 $2 args as given to starct_proc chat script arg1 arg2
12 | # $3 path to named pipe/log
13 |
14 |
15 | # adjust your language setting here
16 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
17 | export 'LC_ALL=C.UTF-8'
18 | export 'LANG=C.UTF-8'
19 | export 'LANGUAGE=C.UTF-8'
20 |
21 | unset IFS
22 | # set -f # if you are paranoid use set -f to disable globbing
23 |
24 | # discard STDIN for background jobs!
25 | cat >/dev/null &
26 |
27 | # check if $1 is a number
28 | regex='^[0-9]+$'
29 | if [[ "$1" =~ ${regex} ]] ; then
30 | SLEEP="$1"
31 | else
32 | SLEEP=10 # time between time notifications
33 | fi
34 |
35 | # output current time every $1 seconds
36 | while sleep "${SLEEP}"
37 | do
38 | date "+* It's %k:%M:%S o' clock ..."
39 | done
40 |
41 |
--------------------------------------------------------------------------------
/examples/bash2env.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # file: bash2env.sh
3 | # simole helper script to convert bash shebang from
4 | # ! /bin/bash TO ! /usr/bin/env bash
5 |
6 | # This file is public domain in the USA and all free countries.
7 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
8 | # shellcheck disable=SC1117
9 | #### $$VERSION$$ v1.52-1-g0dae2db
10 |
11 | # adjust your language setting here
12 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
13 | export 'LC_ALL=C.UTF-8'
14 | export 'LANG=C.UTF-8'
15 | export 'LANGUAGE=C.UTF-8'
16 |
17 | unset IFS
18 | MYSHEBANG=""
19 |
20 | ################
21 | # uncomment one of the following lines to make the conversion
22 | # Linux/Unix bash
23 | # MYSHEBANG="#!/bin/bash"
24 |
25 | # BSD bash
26 | # MYSHEBANG="#!/usr/bin/bash"
27 |
28 | # homebrew gnu bash on MacOS
29 | # MYSHEBANG="#!/usr/local/opt/bash"
30 |
31 | # use portable /usr/bin/env
32 | # MYSHEBANG="#!/usr/bin/env bash"
33 |
34 | # bashbot default bash
35 | FROMSHEBANG="#!/bin/bash"
36 |
37 | # uncomment to convert back to bashbot default bash
38 | # FROMSHEBANG="#!/usr/bin/env bash"
39 | # MYSHEBANG="#!/bin/bash"
40 |
41 | if [ "$1" = "" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
42 | echo "$0: convert bash shebang to point to your local installation"
43 | echo "usage: $0 script [script ...]"
44 | exit
45 | fi
46 |
47 | # loop tomprocess files
48 | if [ "${MYSHEBANG}" != "" ]; then
49 | echo "Warning, shebang will changed from ${FROMSHEBANG} changed to ${MYSHEBANG}!"
50 | else
51 | echo "Dry run, demonstration only!"
52 | echo "Uncomment one of the MYSHEBANG= lines fitting your environment to make the changes permanent."
53 |
54 | fi
55 |
56 | echo "Press enter to continue ..."
57 | #shellcheck disable=SC2034
58 | read -r CONTINUE
59 |
60 |
61 | for file in "$@"
62 | do
63 | file "${file}"
64 | if [[ "$(file -b "${file}")" =~ Bourne.*script.*text ]]; then
65 | echo "Processing ${file} ..."
66 | if head -n 1 "${file}" | grep -q "^${FROMSHEBANG}"; then
67 | if [ "${MYSHEBANG}" != "" ]; then
68 | sed -i -e '1 s|^'"${FROMSHEBANG}"'|'"${MYSHEBANG}"'|' "${file}"
69 | head -n 1 "${file}"
70 | else
71 | sed -n -e '1 s|^'"${FROMSHEBANG}"'|#!/some/shebang/bash (dry run)|p' "${file}"
72 | fi
73 | else
74 | echo "Found: $(head -n 1 "${file}") - Nothing to convert."
75 | fi
76 | echo -e "... done.\n"
77 | else
78 | echo -e "Not a bash script, skipping ${file} ...\n"
79 | fi
80 | done
81 |
--------------------------------------------------------------------------------
/examples/bashbot-multi.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file. multibot.sh
3 | # description: run multiple telegram bots from one installation
4 | #
5 | #### $$VERSION$$ v1.52-1-g0dae2db
6 |
7 | if [ "$2" = "" ] || [ "$2" = "-h" ]; then
8 | echo "Usage: $0 botname command"
9 | exit 1
10 | fi
11 |
12 | BOT="$1"
13 | [ "${#BOT}" -lt 5 ] && echo "Botname must have a minimum length of 5 characters" && exit 1
14 |
15 | # where should the bots live?
16 | # true in one dir, false in separate dirs
17 | if true; then
18 | # example for all in one bashbot dir
19 | BINDIR="/usr/local/telegram-bot-bash"
20 | ETC="${BINDIR}"
21 | VAR="${BINDIR}"
22 |
23 | else
24 | # alternative Linux-like locations
25 | BINDIR="/usr/local/bin"
26 | ETC="/etc/bashbot"
27 | VAR="/var/bashbot"
28 | export BASHBOT_JSONSH="/usr/local/bin/JSON.sh"
29 |
30 | fi
31 |
32 | # set final ENV
33 | export BASHBOT_ETC="${ETC}/${BOT}"
34 | export BASHBOT_VAR="${VAR}/${BOT}"
35 |
36 | # some checks
37 | [ ! -d "${BINDIR}" ] && echo "Dir ${BINDIR} does not exist" && exit 1
38 | [ ! -d "${BASHBOT_ETC}" ] && echo "Dir ${BASHBOT_ETC} does not exist" && exit 1
39 | [ ! -d "${BASHBOT_VAR}" ] && echo "Dir ${BASHBOT_VAR} does not exist" && exit 1
40 | [ ! -x "${BINDIR}/bashbot.sh" ] && echo "${BINDIR}/bashbot.sh not executable or does not exist" && exit 1
41 | [ ! -r "${BASHBOT_ETC}/commands.sh" ] && echo "${BASHBOT_ETC}/commands.sh not readable or does not exist" && exit 1
42 | [ ! -r "${BASHBOT_ETC}/mycommands.sh" ] && echo "${BASHBOT_ETC}/mycommands.sh not readable or does not exist" && exit 1
43 |
44 | "${BINDIR}/bashbot.sh" "$2"
45 |
--------------------------------------------------------------------------------
/examples/bashbot.cron:
--------------------------------------------------------------------------------
1 | #
2 | # this is an example crontab file for telegram-bot-bash
3 | # copy it to /etc/cron.d/bashbot
4 | #
5 | # (c) https://github.com/gnadelwartz
6 | #
7 | # This file is public domain in the USA and all free countries.
8 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
9 | #
10 | #### $$VERSION$$ v1.52-1-g0dae2db
11 |
12 |
13 | SHELL=/bin/sh
14 | PATH=/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:
15 | # place your mailadress here
16 | MAILTO=root
17 |
18 |
19 | # ┌───────────── minute (0 - 59)
20 | # │ ┌───────────── hour (0 - 23)
21 | # │ │ ┌───────────── day of the month (1 - 31)
22 | # │ │ │ ┌───────────── month (1 - 12)
23 | # │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
24 | # │ │ │ │ │ 7 is also Sunday on some systems)
25 | # │ │ │ │ │
26 | # │ │ │ │ │ ┌───────────── run as user (must be omited in users crontab
27 | # │ │ │ │ │ |
28 | # * * * * * USER command to execute
29 | # * * * * * root echo "run every minute!"
30 |
31 | # run as www every day at 0:00 plus random sleep between 0-3h
32 | 0 0 * * * nobody sleep "$((RANDOM \% 180 ))m" ; /usr/local/telegram-bot-bash/bashbot.rc start # (re)start bot
33 | 0 0 * * * nobody sleep "$((RANDOM \% 180 ))m" ; /usr/local/telegram-bot-bash/bashbot.rc resumeback # (re)start background jobs
34 |
35 | # run as www on 24 of Dec, 12:00
36 | 0 12 24 12 * nobody /usr/local/telegram-bot-bash/bashbot.sh broadcast "X-Mas shopping is over!" # broadcast a message
37 |
38 |
--------------------------------------------------------------------------------
/examples/calc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ########################################################################
3 | #
4 | # File: calc.sh
5 | #
6 | # Description: example for an background job, see mycommands.sh.dist
7 | #
8 | # Usage: runback calc example/calc.sh - or run in terminal
9 | # killback calc - to stop background job
10 | #
11 | # This file is public domain in the USA and all free countries.
12 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
13 | #
14 | #### $$VERSION$$ v1.52-1-g0dae2db
15 | ########################################################################
16 |
17 | ######
18 | # parameters
19 | # $1 $2 args as given to starct_proc chat script arg1 arg2
20 | # $3 path to named pipe/log
21 |
22 | INPUT="${3:-/dev/stdin}"
23 |
24 | # adjust your language setting here
25 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
26 | export 'LC_ALL=C.UTF-8'
27 | export 'LANG=C.UTF-8'
28 | export 'LANGUAGE=C.UTF-8'
29 |
30 | unset IFS
31 | # set -f # if you are paranoid use set -f to disable globbing
32 |
33 | printf 'Starting Calculator ...\n'
34 | printf 'Enter first number.\n'
35 | read -r A <"${INPUT}"
36 | printf 'Enter second number.\n'
37 | read -r B <"${INPUT}"
38 | printf 'Select Operation: mykeyboardstartshere [ "Addition" , "Subtraction" , "Multiplication" , "Division" , "Cancel" ]\n'
39 | read -r opt <"${INPUT}"
40 | printf 'Result: '
41 | case ${opt,,} in
42 | 'a'*) res="$(( A + B ))" ;;
43 | 's'*) res="$(( A - B ))" ;;
44 | 'm'*) res="$(( A * B ))" ;;
45 | 'd'*) res="$(( A / B ))" ;;
46 | 'c'*) res="abort!" ;;
47 | * ) printf "unknown operator!\n";;
48 | esac
49 | printf "%s\nBye ...\n" "${res}"
50 |
51 |
--------------------------------------------------------------------------------
/examples/notify.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ########################################################################
3 | #
4 | # File: notify.sh
5 | #
6 | # Description: example for an background job, see mycommands.sh.dist
7 | #
8 | # Usage: runback notify example/notify.sh [seconds] - or run in terminal
9 | # killback notify - to stop background job
10 | #
11 | # Options: seconds - time to sleep between output, default 10
12 | #
13 | # This file is public domain in the USA and all free countries.
14 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
15 | #
16 | #### $$VERSION$$ v1.52-1-g0dae2db
17 | ########################################################################
18 |
19 | ######
20 | # parameters
21 | # $1 $2 args as given to starct_proc chat script arg1 arg2
22 | # $3 path to named pipe/log
23 |
24 | # adjust your language setting here
25 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
26 | export 'LC_ALL=C.UTF-8'
27 | export 'LANG=C.UTF-8'
28 | export 'LANGUAGE=C.UTF-8'
29 |
30 | unset IFS
31 | # set -f # if you are paranoid use set -f to disable globbing
32 |
33 | # discard STDIN for background jobs!
34 | cat >/dev/null &
35 |
36 | # $1 = time between time notifications
37 | # check if $1 is a valid number
38 | if [[ "$1" =~ ^[0-9]+$ ]] ; then
39 | SLEEP="$1"
40 | else
41 | SLEEP=10
42 | fi
43 |
44 | # output current time every $1 seconds
45 | printf "Output time every %s seconds ...\n" "${SLEEP}"
46 |
47 | while true
48 | do
49 | date "+* It's %k:%M:%S o'clock ..."
50 | sleep "${SLEEP}"
51 | done
52 |
53 |
--------------------------------------------------------------------------------
/examples/question.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ########################################################################
3 | #
4 | # File: question.sh
5 | #
6 | # Usage: runproc example/question.sh - or run in terminal
7 | #
8 | # Description: example for an interactive chat, see mycommands.sh.dist
9 | #
10 | # This file is public domain in the USA and all free countries.
11 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
12 | #
13 | #### $$VERSION$$ v1.52-1-g0dae2db
14 | ########################################################################
15 |
16 | ######
17 | # parameters
18 | # $1 $2 args as given to starct_proc chat script arg1 arg2
19 | # $3 path to named pipe
20 |
21 | INPUT="${3:-/dev/stdin}"
22 |
23 | # adjust your language setting here
24 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
25 | export 'LC_ALL=C.UTF-8'
26 | export 'LANG=C.UTF-8'
27 | export 'LANGUAGE=C.UTF-8'
28 |
29 | unset IFS
30 | # set -f # if you are paranoid use set -f to disable globbing
31 |
32 | # kill interactive script if not finished in time, e.g. user away or error
33 | MAXWAIT="1m"
34 | { sleep "${MAXWAIT}"; printf "Stopping Questionnaire after %s, you need to much time to finish ... BYE\n" "${MAXWAIT}"; kill $$; wait 2>/dev/null ;} &
35 |
36 | # simple yes/no question, defaults to no
37 | printf "Hi, hello there\nWould you like some tea (y/n)?\n"
38 | read -r answer <"${INPUT}"
39 | if [[ ${answer,,} == "y"* ]]; then
40 | printf "OK then, here you go: http://www.rivertea.com/blog/wp-content/uploads/2013/12/Green-Tea.jpg\n"
41 | else
42 | printf "OK then, no tea ...\n"
43 | fi
44 |
45 | # question with Keyboard, repeating until correct answer given
46 | until [ "${SUCCESS}" = "y" ] ;do
47 | printf 'Do you like Music? mykeyboardstartshere "Yass!" , "No"\n'
48 | read -r answer <"${INPUT}"
49 | case ${answer,,} in
50 | '') printf "empty answer! Try again\n";;
51 | 'yass'*) printf "Goody! mykeyboardendshere\n";SUCCESS=y;;
52 | 'no'*) printf "Well that's weird. mykeyboardendshere\n";SUCCESS=y;;
53 | *) SUCCESS=n;;
54 | esac
55 | done
56 | printf "OK, Done!\n"
57 |
58 |
--------------------------------------------------------------------------------
/examples/send-system-status/botacl:
--------------------------------------------------------------------------------
1 | # file: botacl
2 | # a user not listed here, will return false from 'user_is_allowed'
3 | #
4 | #### $$VERSION$$ v1.52-1-g0dae2db
5 | # Format:
6 | # user:resource:chat
7 |
8 | # allow user 123456789 access to all resources in all chats
9 | 123456789:*:*
10 |
11 | # allow user 12131415 to request systemstatus in all chats
12 | 12131415:systemstatus:*
13 |
14 | # * are only allowed on the right hand side and not for user!
15 | # the following examples are NOT valid!
16 | *:*:*
17 | *:start:*
18 | *:*:98979695
19 |
--------------------------------------------------------------------------------
/examples/send-system-status/mycommands.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # files: mycommands.sh
3 | #
4 | # this example is rendered after https://github.com/RG72/telegram-bot-bash
5 | # to show how you can customize bashbot by only editing mycommands.sh
6 | # NOTE: this is not tested, simply copied from original source and reworked!
7 | #
8 | #### $$VERSION$$ v1.52-1-g0dae2db
9 | #
10 | # shellcheck disable=SC2154
11 | # shellcheck disable=SC2034
12 |
13 |
14 | # uncomment the following lines to overwrite info and help messages
15 | #'
16 |
17 | # returned messages
18 |
19 | bashbot_info='This bot allows you to request status of your system.
20 | To begin using the bot, try with the /help command.
21 | '
22 | bashbot_help='*Available commands*:
23 | /se *sensors*
24 | /smb *smbstatus*
25 | /free *memory status*
26 | /md *raid status*
27 | /lvm *lvm status*
28 | /lvsd *Datailed lvm status*
29 | /df *disk space*
30 | /ifconfig *ifconfig output*
31 | /smart *-d sda* _smart status for sda drive_
32 | '
33 |
34 |
35 | # your additional bashbot commands
36 | # NOTE: command can have @botname attached, you must add * in case tests...
37 | mycommands() {
38 | local msg=""
39 |
40 | if user_is_botadmin "${USER[ID]}" || user_is_allowed "${USER[ID]}" "systemstatus"; then
41 | case "${CMD}" in
42 | '/md'*) msg="$(cat /proc/mdstat)";;
43 | '/smb'*) msg="$(smbstatus)" ;;
44 | '/se'*) msg="$(sensors | sed -r 's/\s|\)+//g' | sed -r 's/\(high=|\(min=/\//' | sed -r 's/\,crit=|\,max=/\//')";;
45 | '/free'*) msg="$(free -h)";;
46 | '/pvs'*) msg="$(pvs)";;
47 | '/ifc'*) msg="$(ifconfig)";;
48 | '/vgs'*) msg="$(vgs)";;
49 | '/lvm'*) msg="$(lvs | sed -r 's/\s+/\n/g')";;
50 | '/lvsd'*) msg="$(lvs -a -o +devices | sed -r 's/\s+/\n/g')";;
51 | '/smart'*)
52 | [ "${CMD[1]}" == "" ] && msg="example \`/smart sda\`" && return
53 | drive="$(echo "${CMD[1]}" | cut -c 1-3)"
54 | echo "smartctl -a /dev/${drive}"
55 | msg="$(smartctl -a "/dev/${drive}")"
56 | ;;
57 | '/df') msg="$(df -h | sed -r 's/^/\n/' | sed -r 's/\s+/\n/g')";;
58 | esac
59 |
60 | if [ "${msg}" != "" ]; then
61 | send_normal_message "${CHAT[ID]}" "${msg}"
62 | fi
63 | else
64 | send_normal_message "${USER[ID]}" "Sorry, you are not allowed to use this bot!"
65 | fi
66 | }
67 |
68 | # place your processing functions here
69 |
70 |
--------------------------------------------------------------------------------
/examples/webhook/BASHBOT_HOME:
--------------------------------------------------------------------------------
1 | /usr/local/github/telegram-bot-bash-develop/DIST/telegram-bot-bash
2 | /usr/local/github/telegram-bot-bash-develop/STANDALONE
3 | /usr/local/telegram-bot-bash
4 |
--------------------------------------------------------------------------------
/examples/webhook/README.md:
--------------------------------------------------------------------------------
1 | #### [Examples](../README.md)
2 |
3 | ## Bashbot webhook example
4 |
5 | ### Webhook
6 |
7 | Bashbot default mode is to poll Telegram server for updates but Telegram offers webhook as a more efficient method to deliver updates.
8 | If your server is reachable from the Internet its possible to use the method described here.
9 |
10 | Prerequisite for receiving Telegram updates with webhook is a valid SSL certificate, a self signed certificate will not be sufficient.
11 |
12 | Webhook processing require special setup on server and Telegram side, therefore it's implemented as separate scripts and you need at least sudo rights to setup.
13 |
14 | #### Setup Apache webhook
15 |
16 | Prerequisite: An Apache webserver with a valid SLL certificate chain and php enabled.\
17 | This should work with other webservers also but it's not testet.
18 |
19 | Setup webhook with Apache:
20 |
21 | - install bashbot as described in [Bashbot Installation](../../doc/0_install.md)
22 | - create file `data-bot-bash/webhook-fifo-` (_\ as in `botconfig.jssh`_)
23 | - run `sudo bashbot.sh init` to setup bashbot to run as same user as web server (_e.g. www_)
24 | - create a directory in web root: `telegram/` (_ as `botconfig.jssh`_)
25 | - give web server access to directory (_e.g.`chown www:www -R telegram`_)
26 | - go into the new directory and copy all files from `examples/webhook` to it
27 | - edit file `BASHBOT_HOME` to contain ithe Bashbot installation directory as first line (_other lines are ignored_)
28 | - execute `php index.php` with user id of web server to test write access to `data-bot-bash/webhook-fifo-
29 |
30 | Calling `https:///telegram//` will execute `index.php`
31 | thus append received data to the file `data-bot-bash/webhook-fifo-`.
32 | E.g. `https:///telegram//?json={"test":"me"}` will append `{"test":"me"}`.
33 |
34 | Now your Server is ready to receive updates from Telegram.
35 |
36 |
37 | #### Default webhook processing
38 |
39 | This is the testet and supported default method for processing Telegram updates over webhook.
40 |
41 | To enable update processing delete the file `data-bot-bash/webhook-fifo-` if webhook is working as described above.
42 | Incoming Telegram updates are now forwarded to the script `bin/process_update.sh` for processing.
43 |
44 | On incoming Telegram updates the script is executed, it sources bashbot.sh and forward the update to Bashbot for processing.
45 | Even it seems overhead to source Bashbot for every update, it's more responsive and create less load than Bashbot polling mode.
46 |
47 | Nevertheles there are some limitations compared to polling mode:
48 | - no startup actions
49 | - `addons` and `TIMER_EVENTS` are not working
50 |
51 | Interactive and background jobs are working as of Bashbot Version 1.51.
52 |
53 | #### Full webhook processing
54 |
55 | Full webhook processing use an external script to imitate Bashbot polling mode with webhook.
56 |
57 | 1. Default webook method must work first!
58 | 2. run `bashbot.sh init` to setup bashbot to run with your user id
59 | 2. Create a named pipe: `mkfifo data-bot-bash/webhook-fifo-botname` and give the web server write access to it
60 | 3. execute `php index.php` with user id of web server to test write access to `data-bot-bash/webhook-fifo-
61 | 4. Start script for Bashbot webhook polling mode:\
62 | `bin/process-batch.sh --startbot --watch data-bot-bash/webhook-fifo-`
63 |
64 | The script read updates from given file line by line and forward updates to Bashbot update processing. `--startbot` will run the startup actions
65 | (_e.g. load addons, start TIMER, trigger first run_) and `--watch` will wait for new updates instead of exit on end of file.
66 | Short form: 'bin/process-batch.sh -s -w'
67 |
68 | If script works as expected, you may run Bashbot webook polling in background by using `./bachbot.rc starthook/stophook`.
69 |
70 | To switch back to default processing delete fifo `data-bot-bash/webhook-fifo-` and stop `bin/process-batch.sh`.
71 |
72 | #### Enable webhook on Telegram side
73 |
74 | To get updates via webhook your server must be reachable from the internet and you must
75 | instruct Telegram where to deliver updates, this is done by calling bashbot function `set_webhook`.
76 |
77 | *Example:*
78 |
79 | ```bash
80 | bin/any_command.sh set_webhook "https://myserver.com/telegram"
81 | ```
82 |
83 | instruct Telegram to use the URL `https://myserver.com/telegram//` to deliver updates.
84 | After you enable webhook to deliver Telegram updates it's no more possible to poll updates with `bashbot.sh start`.
85 |
86 | To stop delivering of Telegram updates via webhook run `bin/any_command.sh delete_webhook`.
87 |
88 | **Important**: Telegram will refuse to deliver updates if your webhook has no valid SSL certificate chain.
89 |
90 |
91 | #### Bash webhook
92 |
93 | A pure bash webhook implementation is not possible without extra software because Telegram delivers
94 | webhook updates only over secure TLS connections with a valid SSL certificate chain.
95 |
96 | `socat` looks like a tool to listen for Telegram updates from bash scripts, let's see ...
97 |
98 |
99 | #### $$VERSION$$ v1.52-1-g0dae2db
100 |
101 |
--------------------------------------------------------------------------------
/examples/webhook/index.php:
--------------------------------------------------------------------------------
1 | = 20 && strpos($tmp, '/.') === false) {
25 | $BASHBOT_HOME=$tmp;
26 | }
27 | }
28 |
29 | // bashbot config file
30 | $CONFIG=$BASHBOT_HOME.'/botconfig.jssh';
31 | // set botname here or read botname from config file if unknown
32 | $botname="unknown";
33 | if ($botname == "unknown" && file_exists($CONFIG)) {
34 | $prefix='["botname"] "';
35 | $len=strlen($prefix);
36 | $arr = file($CONFIG, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
37 | foreach ($arr as $line) {
38 | if(substr($line, 0, $len) == $prefix) {
39 | $botname=substr($line, $len, strlen($line)-$len-1);
40 | }
41 | }
42 |
43 | }
44 |
45 | // script endpoint
46 | $cmd=$BASHBOT_HOME.'/bin/process_update.sh';
47 | // default fifo endpoint
48 | $fifo=$BASHBOT_HOME.'/data-bot-bash/webhook-fifo-'.$botname;
49 |
50 | // prepeare read, e.g. run from CLI
51 | $data='';
52 | $input="php://input";
53 | $json_file="json.txt";
54 | if (php_sapi_name() == "cli") {
55 | if(is_readable($json_file)) {
56 | $input=$json_file;
57 | } else {
58 | $input="php://stdin";
59 | }
60 | }
61 | // read request data
62 | if($json = file_get_contents($input)) {
63 | $data = $json;
64 | } else {
65 | $data = implode(" ",$_POST);
66 | if ($data == '') { $data = implode(" ",$_GET); }
67 | }
68 | // uncomment to save last received JSON
69 | // file_put_contents($json_file, str_replace(array("\n", "\r"), '',$data). PHP_EOL));
70 |
71 | // prepare for writing
72 | if ($data == '') {
73 | error_response(400, "No data received");
74 | }
75 | if (! chdir($BASHBOT_HOME)) {
76 | error_response(403, "No route to bot home");
77 | }
78 |
79 | // fifo or command?
80 | if (! is_writeable($fifo)) {
81 | // pipe to command
82 | if (! file_exists($cmd)) {
83 | error_response(502, "Webhook endpoint not found");
84 | }
85 | if (! $handle = popen( $cmd.' debug', 'w' )) {
86 | error_response(503, "Can't open webhook command endpoint");
87 | }
88 | } else {
89 | // write to fifo
90 | if (! $handle = fopen( $fifo, 'a' )) {
91 | error_response(503, "Can't open webhook file endpoint");
92 | }
93 | flock($handle, LOCK_EX);
94 | }
95 | if (fwrite( $handle, str_replace(array("\n", "\r"), '',$data). PHP_EOL) === false) {
96 | error_response(504, "Write to webhook failed");
97 | }
98 | flock($handle, LOCK_UN);
99 | pclose($handle);
100 | /**/
101 |
102 | function error_response($code, $msg) {
103 | $api = substr(php_sapi_name(), 0, 3);
104 | if ($api == 'cgi' || $api == 'fpm') {
105 | header('Status: '.$code.' '.$msg);
106 | } else {
107 | $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
108 | header($protocol.' '.$code.' '.$msg);
109 | }
110 | exit('Error '.$code.': '.$msg. PHP_EOL);
111 | }
112 | ?>
113 |
--------------------------------------------------------------------------------
/examples/webhook/json.txt:
--------------------------------------------------------------------------------
1 | {"update_id":665220889,"message":{"message_id":760,"from":{"id":BOTADMIN,"is_bot":false,"first_name":"Kay","last_name":"M","username":"KayM","language_code":"de"},"chat":{"id":BOTADMIN,"first_name":"Kay","last_name":"M","username":"KayM","type":"private"},"date":1612029749,"text":"/info","entities":[{"offset":0,"length":5,"type":"bot_command"}]}}
2 |
--------------------------------------------------------------------------------
/modules/aliases.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: modules/aliases.sh
3 | # do not edit, this file will be overwritten on update
4 |
5 | # This file is public domain in the USA and all free countries.
6 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
7 | #
8 | #### $$VERSION$$ v1.52-1-g0dae2db
9 | #
10 | # will be automatically sourced from bashbot
11 |
12 | # source once magic, function named like file
13 | eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
14 |
15 | # easy handling of users:
16 | _is_botadmin() {
17 | user_is_botadmin "${USER[ID]}"
18 | }
19 | _is_admin() {
20 | user_is_admin "${CHAT[ID]}" "${USER[ID]}"
21 | }
22 | _is_creator() {
23 | user_is_creator "${CHAT[ID]}" "${USER[ID]}"
24 | }
25 | _is_allowed() {
26 | user_is_allowed "${USER[ID]}" "$1" "${CHAT[ID]}"
27 | }
28 | _leave() {
29 | leave_chat "${CHAT[ID]}"
30 | }
31 | _kick_user() {
32 | kick_chat_member "${CHAT[ID]}" "$1"
33 | }
34 | _unban_user() {
35 | unban_chat_member "${CHAT[ID]}" "$1"
36 | }
37 | # easy sending of messages of messages
38 | _message() {
39 | send_normal_message "${CHAT[ID]}" "$1"
40 | }
41 | _normal_message() {
42 | send_normal_message "${CHAT[ID]}" "$1"
43 | }
44 | _html_message() {
45 | send_html_message "${CHAT[ID]}" "$1"
46 | }
47 | _markdown_message() {
48 | send_markdown_message "${CHAT[ID]}" "$1"
49 | }
50 | # easy handling of keyboards
51 | _inline_button() {
52 | send_inline_button "${CHAT[ID]}" "" "$1" "$2"
53 | }
54 | _inline_keyboard() {
55 | send_inline_keyboard "${CHAT[ID]}" "" "$1"
56 | }
57 | _keyboard_numpad() {
58 | send_keyboard "${CHAT[ID]}" "" '["1","2","3"],["4","5","6"],["7","8","9"],["-","0","."]' "yes"
59 | }
60 | _keyboard_yesno() {
61 | send_keyboard "${CHAT[ID]}" "" '["yes","no"]'
62 | }
63 | _del_keyboard() {
64 | remove_keyboard "${CHAT[ID]}" ""
65 | }
66 |
--------------------------------------------------------------------------------
/modules/answerInline.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: modules/inline.sh
3 | # do not edit, this file will be overwritten on update
4 |
5 | # This file is public domain in the USA and all free countries.
6 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
7 | #
8 | #### $$VERSION$$ v1.52-1-g0dae2db
9 |
10 | # will be automatically sourced from bashbot
11 |
12 | # source once magic, function named like file
13 | eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
14 |
15 |
16 | answer_inline_query() {
17 | answer_inline_multi "$1" "$(shift; inline_query_compose "${RANDOM}" "$@")"
18 | }
19 | answer_inline_multi() {
20 | sendJson "" '"inline_query_id": '"$1"', "results": ['"$2"']' "${URL}/answerInlineQuery"
21 | }
22 |
23 | # $1 unique ID for answer
24 | # $2 type of answer
25 | # remaining arguments are the "must have" arguments in the order as in telegram doc
26 | # followed by the optional arguments: https://core.telegram.org/bots/api#inlinequeryresult
27 | inline_query_compose(){
28 | local JSON="{}"
29 | local ID="$1"
30 | local fours last
31 | # title2Json title caption description markup inlinekeyboard
32 | case "$2" in
33 | # user provided media
34 | "article"|"message") # article ID title message (markup description)
35 | JSON='{"type":"article","id":"'${ID}'","input_message_content": {"message_text":"'$4'"} '$(title2Json "$3" "" "$5" "$6" "$7")'}'
36 | ;;
37 | "photo") # photo ID photoURL (thumbURL title description caption)
38 | [ -z "$4" ] && tumb="$3"
39 | JSON='{"type":"photo","id":"'${ID}'","photo_url":"'$3'","thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$7" "$6" "$7" "$8")'}'
40 | ;;
41 | "gif") # gif ID photoURL (thumbURL title caption)
42 | [ -z "$4" ] && tumb="$3"
43 | JSON='{"type":"gif","id":"'${ID}'","gif_url":"'$3'", "thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$6" "$7" "$8" "$9")'}'
44 | ;;
45 | "mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption)
46 | [ -n "$4" ] && tumb='","thumb_url":"'$4'"'
47 | JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_url":"'$3'"'${tumb}$(title2Json "$5" "$6" "" "$7" "$8")'}'
48 | ;;
49 | "video") # video ID videoURL mime thumbURL title (caption)
50 | JSON='{"type":"video","id":"'${ID}'","video_url":"'$3'","mime_type":"'$4'","thumb_url":"'$5'"'$(title2Json "$6" "$7" "$8" "$9" "${10}")'}'
51 | ;;
52 | "audio") # audio ID audioURL title (caption)
53 | JSON='{"type":"audio","id":"'${ID}'","audio_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
54 | ;;
55 | "voice") # voice ID voiceURL title (caption)
56 | JSON='{"type":"voice","id":"'${ID}'","voice_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
57 | ;;
58 | "document") # document ID title documentURL mimetype (caption description)
59 | JSON='{"type":"document","id":"'${ID}'","document_url":"'$4'","mime_type":"'$5'"'$(title2Json "$3" "$6" "$7" "$8" "$9")'}'
60 | ;;
61 | "location") # location ID lat long title
62 | JSON='{"type":"location","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'"}'
63 | ;;
64 | "venue") # venue ID lat long title (address forsquare)
65 | [ -z "$6" ] && addr="$5"
66 | [ -n "$7" ] && fours=',"foursquare_id":"'$7'"'
67 | JSON='{"type":"venue","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'","address":"'$6${addr}'"'${fours}'}'
68 | ;;
69 | "contact") # contact ID phone first (last thumb)
70 | [ -n "$5" ] && last=',"last_name":"'$5'"'
71 | [ -n "$6" ] && tumb='","thumb_url":"'$6'"'
72 | JSON='{"type":"contact","id":"'${ID}'","phone_number":"'$3'","first_name":"'$4'"'${last}'"}'
73 | ;;
74 | # title2Json title caption description markup inlinekeyboard
75 | # Cached media stored in Telegram server
76 | "cached_photo") # photo ID file (title description caption)
77 | JSON='{"type":"photo","id":"'${ID}'","photo_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}'
78 | ;;
79 | "cached_gif") # gif ID file (title caption)
80 | JSON='{"type":"gif","id":"'${ID}'","gif_file_id":"'$3'"'$(title2Json "$4" "$5" "$6" "$7" "$8" )'}'
81 | ;;
82 | "cached_mpeg4_gif") # mpeg ID file (title caption)
83 | JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_file_id":"'$3'"'$(title2Json "$4" "$5" "" "$6" "$7")'}'
84 | ;;
85 | "cached_sticker") # sticker ID file
86 | JSON='{"type":"sticker","id":"'${ID}'","sticker_file_id":"'$3'"}'
87 | ;;
88 | "cached_document") # document ID title file (description caption)
89 | JSON='{"type":"document","id":"'${ID}'","document_file_id":"'$4'"'$(title2Json "$3" "$6" "$5" "$6" "$7")'}'
90 | ;;
91 | "cached_video") # video ID file title (description caption)
92 | JSON='{"type":"video","id":"'${ID}'","video_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}'
93 | ;;
94 | "cached_voice") # voice ID file title (caption)
95 | JSON='{"type":"voice","id":"'${ID}'","voice_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
96 | ;;
97 | "cached_audio") # audio ID file title (caption)
98 | JSON='{"type":"audio","id":"'${ID}'","audio_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
99 | ;;
100 | esac
101 |
102 | printf '%s\n' "${JSON}"
103 | }
104 |
105 |
--------------------------------------------------------------------------------
/modules/background.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: modules/background.sh
3 | # do not edit, this file will be overwritten on update
4 |
5 | # This file is public domain in the USA and all free countries.
6 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
7 | #
8 | # shellcheck disable=SC1117,SC2059
9 | #### $$VERSION$$ v1.52-1-g0dae2db
10 |
11 | # will be automatically sourced from bashbot
12 |
13 | # source once magic, function named like file
14 | eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
15 |
16 | ######
17 | # interactive and background functions
18 |
19 | # old syntax as aliases
20 | background() {
21 | start_back "${CHAT[ID]}" "$1" "$2"
22 | }
23 | startproc() {
24 | start_proc "${CHAT[ID]}" "$1" "$2"
25 | }
26 | checkback() {
27 | check_back "${CHAT[ID]}" "$1"
28 | }
29 | checkproc() {
30 | check_proc "${CHAT[ID]}" "$1"
31 | }
32 | killback() {
33 | kill_back "${CHAT[ID]}" "$1"
34 | }
35 | killproc() {
36 | kill_proc "${CHAT[ID]}" "$1"
37 | }
38 |
39 | # inline and background functions
40 | # $1 chatid
41 | # $2 program
42 | # $3 jobname
43 | # $4 $5 parameters
44 | start_back() {
45 | local cmdfile; cmdfile="${DATADIR:-.}/$(procname "$1")$3-back.cmd"
46 | printf '%s\n' "$1:$3:$2" >"${cmdfile}"
47 | restart_back "$@"
48 | }
49 | # $1 chatid
50 | # $2 program
51 | # $3 jobname
52 | # $4 $5 parameters
53 | restart_back() {
54 | local fifo; fifo="${DATADIR:-.}/$(procname "$1" "back-$3-")"
55 | log_update "Start background job CHAT=$1 JOB=${fifo##*/} CMD=${2##*/} $4 $5"
56 | check_back "$1" "$3" && kill_proc "$1" "back-$3-"
57 | nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"$1\" \"${fifo}\"; }" &>>"${fifo}.log" &
58 | sleep 0.5 # give bg job some time to init
59 | }
60 |
61 |
62 | # $1 chatid
63 | # $2 program
64 | # $3 $4 parameters
65 | start_proc() {
66 | [ -z "$2" ] && return
67 | [ -x "${2%% *}" ] || return 1
68 | local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
69 | check_proc "$1" && kill_proc "$1"
70 | mkfifo "${fifo}"
71 | log_update "Start interactive script CHAT=$1 JOB=${fifo##*/} CMD=$2 $3 $4"
72 | nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"$1\" \"${fifo}\"
73 | rm \"${fifo}\"; [ -s \"${fifo}.log\" ] || rm -f \"${fifo}.log\"; }" &>>"${fifo}.log" &
74 | }
75 |
76 |
77 | # $1 chatid
78 | # $2 jobname
79 | check_back() {
80 | check_proc "$1" "back-$2-"
81 | }
82 |
83 | # $1 chatid
84 | # $2 prefix
85 | check_proc() {
86 | [ -n "$(proclist "$(procname "$1" "$2")")" ]
87 | # shellcheck disable=SC2034
88 | res=$?; return $?
89 | }
90 |
91 | # $1 chatid
92 | # $2 jobname
93 | kill_back() {
94 | kill_proc "$1" "back-$2-"
95 | rm -f "${DATADIR:-.}/$(procname "$1")$2-back.cmd"
96 | }
97 |
98 |
99 | # $1 chatid
100 | # $2 prefix
101 | kill_proc() {
102 | local fifo prid
103 | fifo="$(procname "$1" "$2")"
104 | prid="$(proclist "${fifo}")"
105 | fifo="${DATADIR:-.}/${fifo}"
106 | # shellcheck disable=SC2086
107 | if [ -n "${prid}" ]; then
108 | log_update "Stop interactive / background CHAT=$1 JOB=${fifo##*/}"
109 | kill ${prid}
110 | fi
111 | [ -s "${fifo}.log" ] || rm -f "${fifo}.log"
112 | [ -p "${fifo}" ] && rm -f "${fifo}";
113 | }
114 |
115 | # $1 chatid
116 | # $2 message
117 | send_interactive() {
118 | local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
119 | [ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking!
120 | }
121 |
122 | # old style but may not work because of local checks
123 | inproc() {
124 | send_interactive "${CHAT[ID]}" "${MESSAGE[0]}"
125 | }
126 |
127 | # start stop all jobs
128 | # $1 command # kill suspend resume restart
129 | job_control() {
130 | local BOT ADM content proc CHAT job fifo killall=""
131 | BOT="$(getConfigKey "botname")"
132 | ADM="${BOTADMIN}"
133 | debug_checks "Enter job_control" "$1"
134 | # cleanup on start
135 | [[ "$1" == "re"* ]] && bot_cleanup "startback"
136 | for FILE in "${DATADIR:-.}/"*-back.cmd; do
137 | [ "${FILE}" = "${DATADIR:-.}/*-back.cmd" ] && printf "${RED}No background processes.${NN}" && break
138 | content="$(< "${FILE}")"
139 | CHAT="${content%%:*}"
140 | job="${content#*:}"
141 | proc="${job#*:}"
142 | job="${job%:*}"
143 | fifo="$(procname "${CHAT}" "${job}")"
144 | debug_checks "Execute job_control" "$1" "${FILE##*/}"
145 | case "$1" in
146 | "resume"*|"restart"*)
147 | printf "Restart Job: %s %s\n" "${proc}" " ${fifo##*/}"
148 | restart_back "${CHAT}" "${proc}" "${job}"
149 | # inform botadmin about stop
150 | [ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} restart background jobs ..." &
151 | ;;
152 | "suspend"*)
153 | printf "Suspend Job: %s %s\n" "${proc}" " ${fifo##*/}"
154 | kill_proc "${CHAT}" "${job}"
155 | # inform botadmin about stop
156 | [ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} suspend background jobs ..." &
157 | killall="y"
158 | ;;
159 | "kill"*)
160 | printf "Kill Job: %s %s\n" "${proc}" " ${fifo##*/}"
161 | kill_proc "${CHAT}" "${job}"
162 | rm -f "${FILE}" # remove job
163 | # inform botadmin about stop
164 | [ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} kill background jobs ..." &
165 | killall="y"
166 | ;;
167 | esac
168 | # send message only onnfirst job
169 | ADM=""
170 | done
171 | debug_checks "end job_control" "$1"
172 | # kill all requestet. kill ALL background jobs, even not listed in data-bot-bash
173 | [ "${killall}" = "y" ] && killallproc "back-"
174 | }
175 |
--------------------------------------------------------------------------------
/modules/chatMember.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # file: modules/chatMember.sh
3 | # do not edit, this file will be overwritten on update
4 |
5 | # This file is public domain in the USA and all free countries.
6 | # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
7 | #
8 | #### $$VERSION$$ v1.52-1-g0dae2db
9 |
10 | # will be automatically sourced from bashbot
11 |
12 | # source once magic, function named like file
13 | eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
14 |
15 |
16 | # manage chat functions -------
17 | # $1 chat
18 | new_chat_invite() {
19 | sendJson "$1" "" "${URL}/exportChatInviteLink"
20 | [ "${BOTSENT[OK]}" = "true" ] && printf "%s\n" "${BOTSENT[RESULT]}"
21 | }
22 |
23 | # $1 chat, $2 user_id, $3 title
24 | set_chatadmin_title() {
25 | sendJson "$1" '"user_id":'"$2"',"custom_title": "'"$3"'"' "${URL}/setChatAdministratorCustomTitle"
26 | }
27 | # $1 chat, $2 title
28 | set_chat_title() {
29 | sendJson "$1" '"title": "'"$2"'"' "${URL}/setChatTitle"
30 | }
31 |
32 | # $1 chat, $2 title
33 | set_chat_description() {
34 | sendJson "$1" '"description": "'"$2"'"' "${URL}/setChatDescription"
35 | }
36 |
37 | # $1 chat $2 file
38 | set_chat_photo() {
39 | local file; file="$(checkUploadFile "$1" "$2" "set_chat_photo")"
40 | [ -z "${file}" ] && return 1
41 | sendUpload "$1" "photo" "${file}" "${URL}/setChatPhoto"
42 | }
43 | # $1 chat
44 | delete_chat_photo() {
45 | sendJson "$1" "" "${URL}/deleteChatPhoto"
46 | }
47 |
48 | # $1 chat, $2 message_id
49 | pin_chat_message() {
50 | sendJson "$1" '"message_id": "'"$2"'"' "${URL}/pinChatMessage"
51 | }
52 |
53 | # $1 chat, $2 message_id
54 | unpin_chat_message() {
55 | sendJson "$1" '"message_id": "'"$2"'"' "${URL}/unpinChatMessage"
56 | }
57 |
58 | # $1 chat
59 | unpinall_chat_message() {
60 | sendJson "$1" "" "${URL}/unpinAllChatMessages"
61 | }
62 |
63 | # $1 chat
64 | delete_chat_stickers() {
65 | sendJson "$1" "" "${URL}/deleteChatStickerSet"
66 | }
67 |
68 | # manage chat member functions -------
69 | # $1 chat
70 | chat_member_count() {
71 | sendJson "$1" "" "${URL}/getChatMembersCount"
72 | [ "${BOTSENT[OK]}" = "true" ] && printf "%s\n" "${BOTSENT[RESULT]}"
73 | }
74 |
75 | kick_chat_member() {
76 | sendJson "$1" '"user_id": '"$2"'' "${URL}/kickChatMember"
77 | }
78 |
79 | unban_chat_member() {
80 | sendJson "$1" '"user_id": '"$2"'' "${URL}/unbanChatMember"
81 | }
82 |
83 | leave_chat() {
84 | sendJson "$1" "" "${URL}/leaveChat"
85 | }
86 |
87 | # $1 chat, $2 userid, $3 ... "right[:true]" default false
88 | # right: is_anonymous change_info post_messages edit_messages delete_messages invite_users restrict_members pin_messages promote_member
89 | promote_chat_member() {
90 | local arg bool json chat="$1" user="$2; shift 2"
91 | for arg in "$@"
92 | do
93 | # default false
94 | bool=false; [ "${arg##*:}" = "true" ] && bool="true"
95 | # expand args
96 | case "${arg}" in
97 | *"anon"*) arg="is_anonymous";;
98 | *"change"*) arg="can_change_info";;
99 | *"post"*) arg="can_post_messages";;
100 | *"edit"*) arg="can_edit_messages";;
101 | *"delete"*) arg="can_delete_messages";;
102 | *"pin"*) arg="can_pin_messages";;
103 | *"invite"*) arg="can_invite_users";;
104 | *"restrict"*) arg="can_restrict_members";;
105 | *"promote"*) arg="can_promote_members";;
106 | *) [ -n "${BASHBOTDEBUG}" ] && log_debug "promote_chat_member: unknown promotion CHAT=${chat} USER=${user} PROM=${arg}"
107 | continue;;
108 | esac
109 | # compose json
110 | [ -n "${json}" ] && json+=","
111 | json+='"'"${arg}"'": "'"${bool}"'"'
112 | done
113 | sendJson "${chat}" '"user_id":'"${user}"','"${json}"'' "${URL}/promoteChatMember"
114 | }
115 |
116 | # bashbot specific functions ---------
117 |
118 | # usage: status="$(get_chat_member_status "chat" "user")"
119 | # $1 chat # $2 user
120 | get_chat_member_status() {
121 | sendJson "$1" '"user_id":'"$2"'' "${URL}/getChatMember"
122 | # shellcheck disable=SC2154
123 | printf "%s\n" "${UPD["result,status"]}"
124 | }
125 |
126 | user_is_creator() {
127 | # empty is false ...
128 | [[ "${1:--}" == "${2:-+}" || "$(get_chat_member_status "$1" "$2")" == "creator" ]] && return 0
129 | return 1
130 | }
131 |
132 | # $1 chat
133 | bot_is_admin() {
134 | user_is_admin "$1" "$(getConfigKey "botid")"
135 | }
136 |
137 | # $1 chat # $2 user
138 | user_is_admin() {
139 | [[ -z "$1" || -z "$2" ]] && return 1
140 | [ "${1:--}" == "${2:-+}" ] && return 0
141 | user_is_botadmin "$2" && return 0
142 | local me; me="$(get_chat_member_status "$1" "$2")"
143 | [[ "${me}" =~ ^creator$|^administrator$ ]] && return 0
144 | return 1
145 | }
146 |
147 | # $1 user
148 | user_is_botadmin() {
149 | [ -z "$1" ] && return 1
150 | [ -z "${BOTADMIN}" ] && return 1
151 | [[ "${BOTADMIN}" == "$1" || "${BOTADMIN}" == "$2" ]] && return 0
152 | if [ "${BOTADMIN}" = "?" ]; then setConfigKey "botadmin" "${1:-?}"; BOTADMIN="${1:-?}"; return 0; fi
153 | return 1
154 | }
155 |
156 | # $1 user # $2 key # $3 chat
157 | user_is_allowed() {
158 | [ -z "$1" ] && return 1
159 | user_is_admin "$1" && return 0
160 | # user can do everything
161 | grep -F -xq "$1:*:*" "${BOTACL}" && return 0
162 | [ -z "$2" ] && return 1
163 | # user is allowed todo one action in every chat
164 | grep -F -xq "$1:$2:*" "${BOTACL}" && return 0
165 | # all users are allowed to do one action in every chat
166 | grep -F -xq "ALL:$2:*" "${BOTACL}" && return 0
167 | [ -z "$3" ] && return 1
168 | # user is allowed to do one action in one chat
169 | grep -F -xq "$1:$2:$3" "${BOTACL}" && return 0
170 | # all users are allowed to do one action in one chat
171 | grep -F -xq "ALL:$2:$3" "${BOTACL}" && return 0
172 | return 1
173 | }
174 |
--------------------------------------------------------------------------------
/mycommands.conf:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC2034
3 | #######################################################
4 | #
5 | # File: mycommands.conf
6 | #
7 | # Description: place your config and messages here
8 | #
9 | # Usage: will be sourced from mycommands.sh
10 | #
11 | # License: WTFPLv2 http://www.wtfpl.net/txt/copying/
12 | # Author: KayM (gnadelwartz), kay@rrr.de
13 | # Created: 09.01.2021 07:27
14 | #
15 | #### $$VERSION$$ v1.52-1-g0dae2db
16 | #######################################################
17 |
18 | ##########
19 | # adjust your language setting here, default is C.UTF-8
20 | # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
21 | export 'LC_ALL=C.UTF-8'
22 | export 'LANG=C.UTF-8'
23 | export 'LANGUAGE=C.UTF-8'
24 |
25 | ##########
26 | # in UTF-8 äöü etc. are part of [:alnum:] and ranges (e.g. a-z)
27 | # for more information see doc/4_expert.md#Character_classes
28 | # uncomment next line if you want classic ASCII ranges for [a-z] etc.
29 | #export LC_COLLATE=C
30 |
31 |
32 | ##########
33 | # edit the following lines to fit your bot usage
34 | # use ${ME} for current bot name in messages
35 | # Note: you must escape '_' in botname with two \ in markdown messages!
36 |
37 | # output of /info command
38 | export bashbot_info='This is @'"${ME//_/\\\\_}"', the Telegram example bot written entirely in bash.
39 | Edit commands and messages in mycommands.sh!
40 | '
41 |
42 | # output of /help command (uncomment the next 2 lines
43 | # export bashbot_help='*Available commands*:
44 | # '
45 |
46 | # Set INLINE to 1 in order to receive inline queries.
47 | # To enable this option in your bot, send the /setinline command to @BotFather.
48 | export INLINE="0"
49 |
50 | # Set CALLBACK to 1 in order to receive callback queries.
51 | # callbacks are sent from inline_keyboards (buttons) attached tp bot messages
52 | export CALLBACK="0"
53 |
54 | # if your bot is group admin it get commands sent to other bots
55 | # Set MEONLY to 1 to ignore commands sent to other bots
56 | export MEONLY="0"
57 |
58 | # Set to .* to allow sending files from all locations
59 | # NOTE: this is a regex, not shell globbing! you must use a valid egex,
60 | # '.' matches any character and '.*' matches all remaining charatcers!
61 | # additionally you must escape special characters with '\', e.g. '\. \? \[ \*" to match them literally
62 | export FILE_REGEX="${BASHBOT_ETC}/.*"
63 |
64 | # set BASHBOT_RETRY to enable retry in case of recoverable errors, e.g. throtteling
65 | # problems with send_xxx message etc are looged to logs/ERROR.log
66 | unset BASHBOT_RETRY
67 | #export BASHBOT_RETRY="yes"
68 |
69 | # set value for adaptive sleeping while waiting for uodates in millisconds
70 | # max slepp between polling updates 10s (default 5s)
71 | # export BASHBOT_SLEEP="10000"
72 |
73 | # max slepp between polling updates 2s (default 5s)
74 | # export BASHBOT_SLEEP="2000"
75 |
76 | # add 0.2s if no update available, up to BASHBOT_SLEEP (default 0.1s)
77 | export BASHBOT_SLEEP_STEP="200"
78 |
79 | # if you want to use timer functions, set BASHBOT_START_TIMER to a not empty value
80 | # default is to not start timer
81 | unset BASHBOT_START_TIMER
82 | #export BASHBOT_START_TIMER="yes"
83 |
84 | # set to "yes" and give your bot admin privilegs to remove service messages from groups
85 | export SILENCER="no"
86 |
87 | # uncomment to remove keyboards sent from your bot
88 | # export REMOVEKEYBOARD="yes"
89 | # export REMOVEKEYBOARD_PRIVATE="yes"
90 |
91 | # uncomment to say welcome to new chat members
92 | # export WELCOME_NEWMEMBER="yes"
93 | WELCOME_MSG="Welcome"
94 |
95 | # uncomment to be informed about new/left chat members
96 | # export REPORT_NEWMEMBER="yes"
97 | # export REPORT_LEFTMEMBER="yes"
98 |
99 | # uncomment to send user blocked by bot a warning if they send commands
100 | # export NOTIFY_BLOCKED_USERS="yes"
101 |
102 | # messages for admin only commands
103 | NOTADMIN="Sorry, this command is allowed for admin or owner only"
104 | NOTBOTADMIN="Sorry, this command is allowed for bot owner only"
105 |
106 | ########
107 | # special network setup may require additional ARGS to curl
108 | #
109 | # example: run bashbot over TOR or SOCKS proxy
110 | # export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1:9050" # TOR
111 | # export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1" # regular SOCKS
112 |
113 |
--------------------------------------------------------------------------------
/mycommands.sh.clean:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #######################################################
3 | #
4 | # File: mycommands.sh.clean
5 | #
6 | # copy to mycommands.sh and add all your commands and functions here ...
7 | #
8 | # Usage: will be executed when a bot command is received
9 | #
10 | # License: WTFPLv2 http://www.wtfpl.net/txt/copying/
11 | # Author: KayM (gnadelwartz), kay@rrr.de
12 | #
13 | #### $$VERSION$$ v1.52-1-g0dae2db
14 | #######################################################
15 | # shellcheck disable=SC1117
16 |
17 | ####################
18 | # Config has moved to bashbot.conf
19 | # shellcheck source=./commands.sh
20 | [ -r "${BASHBOT_ETC:-.}/mycommands.conf" ] && source "${BASHBOT_ETC:-.}/mycommands.conf" "$1"
21 |
22 |
23 | ##################
24 | # lets's go
25 | if [ "$1" = "startbot" ];then
26 | ###################
27 | # this section is processed on startup
28 |
29 | # run once after startup when the first message is received
30 | my_startup(){
31 | :
32 | }
33 | touch .mystartup
34 | else
35 | # call my_startup on first message after startup
36 | # things to do only once
37 | [ -f .mystartup ] && rm -f .mystartup && _exec_if_function my_startup
38 |
39 | #############################
40 | # your own bashbot commands
41 | # NOTE: command can have @botname attached, you must add * to case tests...
42 | mycommands() {
43 |
44 | ##############
45 | # a service Message was received
46 | # add your own stuff here
47 | if [ -n "${SERVICE}" ]; then
48 | # example: delete every service message
49 | if [ "${SILENCER}" = "yes" ]; then
50 | delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
51 | fi
52 | fi
53 |
54 | # remove keyboard if you use keyboards
55 | [ -n "${REMOVEKEYBOARD}" ] && remove_keyboard "${CHAT[ID]}" &
56 | [[ -n "${REMOVEKEYBOARD_PRIVATE}" && "${CHAT[ID]}" == "${USER[ID]}" ]] && remove_keyboard "${CHAT[ID]}" &
57 |
58 | # uncommet to fix first letter upper case because of smartphone auto correction
59 | #[[ "${MESSAGE}" =~ ^/[[:upper:]] ]] && MESSAGE="${MESSAGE:0:1}$(tr '[:upper:]' '[:lower:]' <<<"${MESSAGE:1:1}")${MESSAGE:2}"
60 | case "${MESSAGE}" in
61 | ##################
62 | # example command, replace them by your own
63 | '/echo'*) # example echo command
64 | send_normal_message "${CHAT[ID]}" "${MESSAGE}"
65 | ;;
66 |
67 | ##########
68 | # command overwrite examples
69 | # return 0 -> run default command afterwards
70 | # return 1 -> skip possible default commands
71 | '/info'*) # output date in front of regular info
72 | send_normal_message "${CHAT[ID]}" "$(date)"
73 | return 0
74 | ;;
75 | '/kickme'*) # this will replace the /kickme command
76 | send_markdownv2_mesage "${CHAT[ID]}" "This bot will *not* kick you!"
77 | return 1
78 | ;;
79 | esac
80 | }
81 |
82 | mycallbacks() {
83 | #######################
84 | # callbacks from buttons attached to messages will be processed here
85 | case "${iBUTTON[USER_ID]}+${iBUTTON[CHAT_ID]}" in
86 | *) # all other callbacks are processed here
87 | local callback_answer
88 | : # your processing here ...
89 | :
90 | # Telegram needs an ack each callback query, default empty
91 | answer_callback_query "${iBUTTON[ID]}" "${callback_answer}"
92 | ;;
93 | esac
94 | }
95 | myinlines() {
96 | #######################
97 | # this fuinction is called only if you has set INLINE=1 !!
98 | # shellcheck disable=SC2128
99 | iQUERY="${iQUERY,,}"
100 |
101 |
102 | case "${iQUERY}" in
103 | ##################
104 | # example inline command, replace it by your own
105 | "image "*) # search images with yahoo
106 | local search="${iQUERY#* }"
107 | answer_inline_multi "${iQUERY[ID]}" "$(my_image_search "${search}")"
108 | ;;
109 | esac
110 | }
111 |
112 | #####################
113 | # place your processing functions here
114 |
115 | # example inline processing function, not really useful
116 | # $1 search parameter
117 | my_image_search(){
118 | local image result sep="" count="1"
119 | result="$(wget --user-agent 'Mozilla/5.0' -qO - "https://images.search.yahoo.com/search/images?p=$1" | sed 's/\n"test/${TEST}.sh" <"${LOGFILE}" <>"${LOGFILE}"
40 | diff -q "${TESTDIR}/${file}" "${REFDIR}/${file}" >>"${LOGFILE}" || { printf "%s\n" "${NOSUCCESS} Fail diff ${file}!"; FAIL="1"; }
41 | done
42 | [ "${FAIL}" != "0" ] && exit "${FAIL}"
43 | printf "%s\n" "${SUCCESS}"
44 |
45 | trap exit 1 EXIT
46 | cd "${TESTDIR}" || exit
47 |
48 | printf "%s\n" "Test if ${JSONSHFILE} exists ..."
49 | [ ! -x "${JSONSHFILE}" ] && { printf "%s\n" "${NOSUCCESS} json.sh not found"; exit 1; }
50 |
51 | printf "Test Sourcing of bashbot.sh ...\n"
52 | # shellcheck source=./bashbot.sh
53 | source "${TESTDIR}/bashbot.sh" source
54 |
55 | printf "Test Sourcing of commands.sh ...\n"
56 | source "${TESTDIR}/commands.sh" source
57 |
58 | trap '' EXIT
59 | cd "${DIRME}" || exit 1
60 |
61 | printf "%s\n" "${SUCCESS}"
62 |
63 |
--------------------------------------------------------------------------------
/test/c-init-test/blocked.jssh:
--------------------------------------------------------------------------------
1 | ["blocked_user_or_chat_id"] "name and reason"
2 |
--------------------------------------------------------------------------------
/test/c-init-test/botacl:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/test/c-init-test/botconfig.jssh:
--------------------------------------------------------------------------------
1 | ["bot_config_key"] "config_key_value"
2 | ["bottoken"] "123456789:BASHBOTTESTSCRIPTbashbottestscript_"
3 | ["botadmin"] "?"
4 |
--------------------------------------------------------------------------------
/test/c-init-test/count.jssh:
--------------------------------------------------------------------------------
1 | ["counted_user_chat_id"] "num_messages_seen"
2 |
--------------------------------------------------------------------------------
/test/c-init-test/count.test:
--------------------------------------------------------------------------------
1 | ["counted_user_id"] "num_messages_seen"
2 | ["712677"] "2"
3 | ["-1001189446"] "29"
4 | ["-1001288661"] "6"
5 | ["-1001433755"] "4"
6 | ["-408138"] "2"
7 | ["1246831"] "7"
8 | ["-1001186489"] "4"
9 | ["-1001259400"] "8"
10 | ["791626"] "18"
11 | ["-1001293952"] "4"
12 | ["-1001435141"] "7"
13 | ["733039"] "2"
14 | ["-1001319011"] "6"
15 | ["-1001220313"] "15"
16 | ["26122"] "3"
17 | ["988411"] "8"
18 | ["908527"] "6"
19 | ["-1001450413"] "58"
20 | ["748933"] "2"
21 | ["-1001425571"] "5"
22 | ["788295"] "3"
23 | ["586928"] "45"
24 | ["-1001359971"] "7"
25 | ["1069707"] "19"
26 | ["-1001189446"] "30"
27 | ["-1001189446"] "31"
28 |
--------------------------------------------------------------------------------
/test/c-init-test/stats.out:
--------------------------------------------------------------------------------
1 | A total of 272 messages from 24 users are processed.
2 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #### $$VERSION$$ v1.52-1-g0dae2db
3 |
4 | # include common functions and definitions
5 | # shellcheck source=test/ALL-tests.inc.sh
6 | source "./ALL-tests.inc.sh"
7 |
8 | set -e
9 |
10 | # source bashbot.sh functionw
11 | cd "${TESTDIR}" || exit 1
12 |
13 | # run JSON.sh with and without options
14 | cd "test" || exit 1
15 | printf "Check JSON.sh ...\n"
16 | JSON="../JSON.sh/JSON.sh"
17 |
18 | for i in 1 2
19 | do
20 | [ "${i}" = "1" ] && printf " ... JSON.sh -b -n\n"
21 | [ "${i}" = "2" ] && printf " ... JSON.sh\n"
22 | set +f
23 | for jsonfile in "${REFDIR}"/*.in
24 | do
25 | set -f
26 | [ "${i}" = "1" ] && "${JSON}" -b -n <"${jsonfile}" >"${jsonfile}.out-${i}"
27 | [ "${i}" = "2" ] && "${JSON}" <"${jsonfile}" >"${jsonfile}.out-${i}"
28 |
29 | # output processed input
30 | diff -c "${jsonfile%.in}.result-${i}" "${jsonfile}.out-${i}" || exit 1
31 | done
32 | printf "%s\n" "${SUCCESS}"
33 | done
34 |
35 | cd "${DIRME}" || exit 1
36 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON26783.log.in:
--------------------------------------------------------------------------------
1 | {"ok":true,"result":[{"update_id":146860898,
2 | "message":{"message_id":6620,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934213,"location":{"latitude":49.630443,"longitude":8.361698},"venue":{"location":{"latitude":49.630443,"longitude":8.361698},"title":"Vannini","address":"K\u00e4mmererstr. 3","foursquare_id":"4bf94ec05ec320a115f889d3"}}}]}
3 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON26783.log.result-1:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 146860898
3 | ["result",0,"message","message_id"] 6620
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","chat","id"] 123456789
11 | ["result",0,"message","chat","first_name"] "Kay"
12 | ["result",0,"message","chat","last_name"] "M"
13 | ["result",0,"message","chat","username"] "Gnadelwartz"
14 | ["result",0,"message","chat","type"] "private"
15 | ["result",0,"message","date"] 1555934213
16 | ["result",0,"message","location","latitude"] 49.630443
17 | ["result",0,"message","location","longitude"] 8.361698
18 | ["result",0,"message","venue","location","latitude"] 49.630443
19 | ["result",0,"message","venue","location","longitude"] 8.361698
20 | ["result",0,"message","venue","title"] "Vannini"
21 | ["result",0,"message","venue","address"] "K\u00e4mmererstr. 3"
22 | ["result",0,"message","venue","foursquare_id"] "4bf94ec05ec320a115f889d3"
23 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON26783.log.result-2:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 146860898
3 | ["result",0,"message","message_id"] 6620
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","from"] {"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"}
11 | ["result",0,"message","chat","id"] 123456789
12 | ["result",0,"message","chat","first_name"] "Kay"
13 | ["result",0,"message","chat","last_name"] "M"
14 | ["result",0,"message","chat","username"] "Gnadelwartz"
15 | ["result",0,"message","chat","type"] "private"
16 | ["result",0,"message","chat"] {"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"}
17 | ["result",0,"message","date"] 1555934213
18 | ["result",0,"message","location","latitude"] 49.630443
19 | ["result",0,"message","location","longitude"] 8.361698
20 | ["result",0,"message","location"] {"latitude":49.630443,"longitude":8.361698}
21 | ["result",0,"message","venue","location","latitude"] 49.630443
22 | ["result",0,"message","venue","location","longitude"] 8.361698
23 | ["result",0,"message","venue","location"] {"latitude":49.630443,"longitude":8.361698}
24 | ["result",0,"message","venue","title"] "Vannini"
25 | ["result",0,"message","venue","address"] "K\u00e4mmererstr. 3"
26 | ["result",0,"message","venue","foursquare_id"] "4bf94ec05ec320a115f889d3"
27 | ["result",0,"message","venue"] {"location":{"latitude":49.630443,"longitude":8.361698},"title":"Vannini","address":"K\u00e4mmererstr. 3","foursquare_id":"4bf94ec05ec320a115f889d3"}
28 | ["result",0,"message"] {"message_id":6620,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934213,"location":{"latitude":49.630443,"longitude":8.361698},"venue":{"location":{"latitude":49.630443,"longitude":8.361698},"title":"Vannini","address":"K\u00e4mmererstr. 3","foursquare_id":"4bf94ec05ec320a115f889d3"}}
29 | ["result",0] {"update_id":146860898,"message":{"message_id":6620,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934213,"location":{"latitude":49.630443,"longitude":8.361698},"venue":{"location":{"latitude":49.630443,"longitude":8.361698},"title":"Vannini","address":"K\u00e4mmererstr. 3","foursquare_id":"4bf94ec05ec320a115f889d3"}}}
30 | ["result"] [{"update_id":146860898,"message":{"message_id":6620,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934213,"location":{"latitude":49.630443,"longitude":8.361698},"venue":{"location":{"latitude":49.630443,"longitude":8.361698},"title":"Vannini","address":"K\u00e4mmererstr. 3","foursquare_id":"4bf94ec05ec320a115f889d3"}}}]
31 | [] {"ok":true,"result":[{"update_id":146860898,"message":{"message_id":6620,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934213,"location":{"latitude":49.630443,"longitude":8.361698},"venue":{"location":{"latitude":49.630443,"longitude":8.361698},"title":"Vannini","address":"K\u00e4mmererstr. 3","foursquare_id":"4bf94ec05ec320a115f889d3"}}}]}
32 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON30458.log.in:
--------------------------------------------------------------------------------
1 | {"ok":true,"result":[{"update_id":146860896,
2 | "message":{"message_id":6618,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934195,"voice":{"duration":1,"mime_type":"audio/ogg","file_id":"AwADAgADKQMAAh638UnbhHGzIMozZgI","file_size":3963}}}]}
3 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON30458.log.result-1:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 146860896
3 | ["result",0,"message","message_id"] 6618
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","chat","id"] 123456789
11 | ["result",0,"message","chat","first_name"] "Kay"
12 | ["result",0,"message","chat","last_name"] "M"
13 | ["result",0,"message","chat","username"] "Gnadelwartz"
14 | ["result",0,"message","chat","type"] "private"
15 | ["result",0,"message","date"] 1555934195
16 | ["result",0,"message","voice","duration"] 1
17 | ["result",0,"message","voice","mime_type"] "audio/ogg"
18 | ["result",0,"message","voice","file_id"] "AwADAgADKQMAAh638UnbhHGzIMozZgI"
19 | ["result",0,"message","voice","file_size"] 3963
20 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON30458.log.result-2:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 146860896
3 | ["result",0,"message","message_id"] 6618
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","from"] {"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"}
11 | ["result",0,"message","chat","id"] 123456789
12 | ["result",0,"message","chat","first_name"] "Kay"
13 | ["result",0,"message","chat","last_name"] "M"
14 | ["result",0,"message","chat","username"] "Gnadelwartz"
15 | ["result",0,"message","chat","type"] "private"
16 | ["result",0,"message","chat"] {"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"}
17 | ["result",0,"message","date"] 1555934195
18 | ["result",0,"message","voice","duration"] 1
19 | ["result",0,"message","voice","mime_type"] "audio/ogg"
20 | ["result",0,"message","voice","file_id"] "AwADAgADKQMAAh638UnbhHGzIMozZgI"
21 | ["result",0,"message","voice","file_size"] 3963
22 | ["result",0,"message","voice"] {"duration":1,"mime_type":"audio/ogg","file_id":"AwADAgADKQMAAh638UnbhHGzIMozZgI","file_size":3963}
23 | ["result",0,"message"] {"message_id":6618,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934195,"voice":{"duration":1,"mime_type":"audio/ogg","file_id":"AwADAgADKQMAAh638UnbhHGzIMozZgI","file_size":3963}}
24 | ["result",0] {"update_id":146860896,"message":{"message_id":6618,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934195,"voice":{"duration":1,"mime_type":"audio/ogg","file_id":"AwADAgADKQMAAh638UnbhHGzIMozZgI","file_size":3963}}}
25 | ["result"] [{"update_id":146860896,"message":{"message_id":6618,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934195,"voice":{"duration":1,"mime_type":"audio/ogg","file_id":"AwADAgADKQMAAh638UnbhHGzIMozZgI","file_size":3963}}}]
26 | [] {"ok":true,"result":[{"update_id":146860896,"message":{"message_id":6618,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":123456789,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934195,"voice":{"duration":1,"mime_type":"audio/ogg","file_id":"AwADAgADKQMAAh638UnbhHGzIMozZgI","file_size":3963}}}]}
27 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON32034.log.in:
--------------------------------------------------------------------------------
1 | {"ok":true,"result":[{"update_id":146860897,
2 | "message":{"message_id":6619,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":586928566,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934204,"contact":{"phone_number":"222222","first_name":"ADAC Pannenhilfe","vcard":"BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD"}}}]}
3 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON32034.log.result-1:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 146860897
3 | ["result",0,"message","message_id"] 6619
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","chat","id"] 586928566
11 | ["result",0,"message","chat","first_name"] "Kay"
12 | ["result",0,"message","chat","last_name"] "M"
13 | ["result",0,"message","chat","username"] "Gnadelwartz"
14 | ["result",0,"message","chat","type"] "private"
15 | ["result",0,"message","date"] 1555934204
16 | ["result",0,"message","contact","phone_number"] "222222"
17 | ["result",0,"message","contact","first_name"] "ADAC Pannenhilfe"
18 | ["result",0,"message","contact","vcard"] "BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD"
19 |
--------------------------------------------------------------------------------
/test/d-JSON.sh-test/JSON32034.log.result-2:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 146860897
3 | ["result",0,"message","message_id"] 6619
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","from"] {"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"}
11 | ["result",0,"message","chat","id"] 586928566
12 | ["result",0,"message","chat","first_name"] "Kay"
13 | ["result",0,"message","chat","last_name"] "M"
14 | ["result",0,"message","chat","username"] "Gnadelwartz"
15 | ["result",0,"message","chat","type"] "private"
16 | ["result",0,"message","chat"] {"id":586928566,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"}
17 | ["result",0,"message","date"] 1555934204
18 | ["result",0,"message","contact","phone_number"] "222222"
19 | ["result",0,"message","contact","first_name"] "ADAC Pannenhilfe"
20 | ["result",0,"message","contact","vcard"] "BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD"
21 | ["result",0,"message","contact"] {"phone_number":"222222","first_name":"ADAC Pannenhilfe","vcard":"BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD"}
22 | ["result",0,"message"] {"message_id":6619,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":586928566,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934204,"contact":{"phone_number":"222222","first_name":"ADAC Pannenhilfe","vcard":"BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD"}}
23 | ["result",0] {"update_id":146860897,"message":{"message_id":6619,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":586928566,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934204,"contact":{"phone_number":"222222","first_name":"ADAC Pannenhilfe","vcard":"BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD"}}}
24 | ["result"] [{"update_id":146860897,"message":{"message_id":6619,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":586928566,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934204,"contact":{"phone_number":"222222","first_name":"ADAC Pannenhilfe","vcard":"BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD"}}}]
25 | [] {"ok":true,"result":[{"update_id":146860897,"message":{"message_id":6619,"from":{"id":123456789,"is_bot":false,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","language_code":"de"},"chat":{"id":586928566,"first_name":"Kay","last_name":"M","username":"Gnadelwartz","type":"private"},"date":1555934204,"contact":{"phone_number":"222222","first_name":"ADAC Pannenhilfe","vcard":"BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD"}}}]}
26 |
--------------------------------------------------------------------------------
/test/d-process_inline-test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #===============================================================================
3 | #
4 | # FILE: d-process_inline-test.sh
5 | #
6 | # USAGE: must run only from dev/all-tests.sh
7 | #
8 | # DESCRIPTION: test response to inline messages
9 | #
10 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
11 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
12 | #
13 | #### $$VERSION$$ v1.52-1-g0dae2db
14 | #===============================================================================
15 |
16 | # include common functions and definitions
17 | # shellcheck source=test/ALL-tests.inc.sh
18 | source "./ALL-tests.inc.sh"
19 |
20 | set -e
21 |
22 | # source bashbot.sh functionw
23 | cd "${TESTDIR}" || exit 1
24 | # shellcheck source=./bashbot.sh
25 | source "${TESTDIR}/bashbot.sh" source
26 | # shellcheck source=./bashbot.sh
27 | source "${TESTDIR}/modules/answerInline.sh" source
28 |
29 | # overwrite get_file for test
30 | get_file() {
31 | printf "%s\n" "$1"
32 | }
33 |
34 | # get telegram input from file
35 | export UPDATE UPD
36 | UPDATE="$(cat "${INPUTFILE}")"
37 | declare -A UPD
38 | source <( printf 'UPD=( %s )' "$(sed <<<"${UPDATE}" -E -e 's/\t/=/g' -e 's/=(true|false)/="\1"/')" )
39 |
40 | # run process_message with and without python
41 | printf "Check process_inline ...\n"
42 | printf " ... with JsonDecode Bash\n"
43 | set -x
44 | { process_inline_query "0"; set +x; } >>"${LOGFILE}" 2>&1;
45 |
46 | # output processed input
47 | print_array "iQUERY" >"${OUTPUTFILE}"
48 | compare_sorted "${REFFILE}" "${OUTPUTFILE}" || exit 1
49 |
50 | printf "%s\n" "${SUCCESS}"
51 |
52 | cd "${DIRME}" || exit 1
53 |
--------------------------------------------------------------------------------
/test/d-process_inline-test/d-process_inline-test.input:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 1234567890
3 | ["result",0,"inline_query","id"] "987654321"
4 | ["result",0,"inline_query","query"] "message"
5 | ["result",0,"inline_query","from","id"] 123456789
6 | ["result",0,"inline_query","from","is_bot"] false
7 | ["result",0,"inline_query","from","first_name"] "Kay"
8 | ["result",0,"inline_query","from","last_name"] "M"
9 | ["result",0,"inline_query","from","username"] "Gnadelwartz"
10 | ["result",0,"inline_query","from","language_code"] "de"
11 |
12 |
--------------------------------------------------------------------------------
/test/d-process_inline-test/d-process_inline-test.result:
--------------------------------------------------------------------------------
1 | iQUERY: 0 message
2 | iQUERY: FIRST_NAME Kay
3 | iQUERY: LAST_NAME M
4 | iQUERY: USER_ID 123456789
5 | iQUERY: USERNAME Gnadelwartz
6 |
--------------------------------------------------------------------------------
/test/d-process_message-test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #===============================================================================
3 | #
4 | # FILE: d-process_message-test.sh
5 | #
6 | # USAGE: must run only from dev/all-tests.sh
7 | #
8 | # DESCRIPTION: test receiving messages
9 | #
10 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
11 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
12 | #
13 | #### $$VERSION$$ v1.52-1-g0dae2db
14 | #===============================================================================
15 |
16 | # include common functions and definitions
17 | # shellcheck source=test/ALL-tests.inc.sh
18 | source "./ALL-tests.inc.sh"
19 |
20 | set -e
21 |
22 | # source bashbot.sh functionw
23 | cd "${TESTDIR}" || exit 1
24 | # shellcheck source=./bashbot.sh
25 | source "${TESTDIR}/bashbot.sh" source
26 | # shellcheck source=./bashbot.sh
27 | source "${TESTDIR}/commands.sh" source
28 |
29 | # overwrite get_file for test
30 | get_file() {
31 | printf "%s\n" "$1"
32 | }
33 |
34 | # get telegram input from file
35 | export UPDATE
36 | declare -Ax UPD
37 |
38 | # run process_message --------------
39 | ARRAYS="USER CHAT REPLYTO FORWARD URLS CONTACT CAPTION LOCATION MESSAGE VENUE SERVICE NEWMEMBER LEFTMEMBER PINNED"
40 |
41 | printf "Check process_message ...\n"
42 |
43 | for testfile in ${INPUTFILELIST}
44 | do
45 | printf " ... %s\n" "${testfile##*/}"
46 | testref="${testfile%.input}.result"
47 | UPDATE="$(< "${testfile}")"
48 | Json2Array 'UPD' <"${testfile}"
49 | set -x
50 | { pre_process_message "0"; process_message "0"; set +x; } >>"${LOGFILE}" 2>&1;
51 | USER[ID]="123456789"; CHAT[ID]="123456789"
52 |
53 | # output processed input
54 | # shellcheck disable=SC2086
55 | print_array ${ARRAYS} >"${OUTPUTFILE}"
56 | compare_sorted "${testref}" "${OUTPUTFILE}" || exit 1
57 | printf "%s\n" "${SUCCESS}"
58 |
59 | done
60 |
61 | cd "${DIRME}" || exit 1
62 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-left_chat_member.input:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 123456789
3 | ["result",0,"message","message_id"] 123456789
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","chat","id"] -123456789
11 | ["result",0,"message","chat","title"] "Testgruppe bot only test"
12 | ["result",0,"message","chat","type"] "group"
13 | ["result",0,"message","chat","all_members_are_administrators"] true
14 | ["result",0,"message","date"] 1592372719
15 |
16 | ["result",0,"message","left_chat_participant","id"] 123456789
17 | ["result",0,"message","left_chat_participant","is_bot"] false
18 | ["result",0,"message","left_chat_participant","first_name"] "Kay"
19 | ["result",0,"message","left_chat_participant","last_name"] "M"
20 | ["result",0,"message","left_chat_participant","username"] "Gnadelwartz"
21 | ["result",0,"message","left_chat_member","id"] 123456789
22 | ["result",0,"message","left_chat_member","is_bot"] false
23 | ["result",0,"message","left_chat_member","first_name"] "Kay"
24 | ["result",0,"message","left_chat_member","last_name"] "M"
25 | ["result",0,"message","left_chat_member","username"] "Gnadelwartz"
26 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-left_chat_member.result:
--------------------------------------------------------------------------------
1 | USER: FIRST_NAME Kay
2 | USER: ID 123456789
3 | USER: LAST_NAME M
4 | USER: USERNAME Gnadelwartz
5 | CHAT: ALL_ADMIN true
6 | CHAT: FIRST_NAME
7 | CHAT: ID 123456789
8 | CHAT: LAST_NAME
9 | CHAT: TITLE Testgruppe bot only test
10 | CHAT: TYPE group
11 | CHAT: USERNAME
12 | CAPTION: 0
13 | LOCATION: LATITUDE
14 | LOCATION: LONGITUDE
15 | MESSAGE: 0 /_left_chat_member Kay M
16 | MESSAGE: CAPTION
17 | MESSAGE: DICE
18 | MESSAGE: ID 123456789
19 | SERVICE: 0 yes
20 | SERVICE: LEFTMEMBER 123456789
21 | LEFTMEMBER: FIRST_NAME Kay
22 | LEFTMEMBER: ID
23 | LEFTMEMBER: ISBOT false
24 | LEFTMEMBER: LAST_NAME M
25 | LEFTMEMBER: USERNAME Kay M
26 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-mesage.result:
--------------------------------------------------------------------------------
1 | USER: FIRST_NAME Kay
2 | USER: ID 123456789
3 | USER: LAST_NAME M
4 | USER: USERNAME Gnadelwartz
5 | CHAT: ALL_ADMIN
6 | CHAT: FIRST_NAME Test
7 | CHAT: ID 123456789
8 | CHAT: LAST_NAME Bot
9 | CHAT: TITLE BotTestTitle
10 | CHAT: TYPE private
11 | CHAT: USERNAME BotTest
12 | REPLYTO: 0 Ich bin der Deal-O-Mat Bot. Für eine Liste der Befehle sende /help
13 | REPLYTO: FIRST_NAME dealzbot
14 | REPLYTO: ID 6542
15 | REPLYTO: LAST_NAME
16 | REPLYTO: UID 987654321
17 | REPLYTO: USERNAME Deal_O_Mat_bot
18 | FORWARD: FIRST_NAME Kay
19 | FORWARD: ID 6541
20 | FORWARD: LAST_NAME M
21 | FORWARD: UID 123456789
22 | FORWARD: USERNAME Gnadelwartz
23 | URLS: AUDIO audio-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
24 | URLS: DOCUMENT document-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
25 | URLS: PHOTO photo-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
26 | URLS: STICKER sticker-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
27 | URLS: VIDEO video-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
28 | URLS: VOICE voice-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
29 | CONTACT: FIRST_NAME ADAC
30 | CONTACT: LAST_NAME Pannenhilfe
31 | CONTACT: NUMBER 222222
32 | CONTACT: USER_ID
33 | CONTACT: VCARD BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD
34 | CAPTION: 0 Myproteine kein spell check
35 | LOCATION: LATITUDE 49.631824
36 | LOCATION: LONGITUDE 8.377072
37 | MESSAGE: 0 😂😝👌☺❤😕😈#⃣🌏🎉🙊🙉☕🚀✈🚂💯✔〽🔚
38 | MESSAGE: ID 6541
39 | MESSAGE: CAPTION Myproteine kein spell check
40 | MESSAGE: DICE
41 | VENUE: ADDRESS Am Rhein 1
42 | VENUE: FOURSQUARE 4c4321afce54e21eee980d1a
43 | VENUE: LATITUDE 49.631824
44 | VENUE: LONGITUDE 8.377072
45 | VENUE: TITLE Kolb's Biergarten
46 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-message.result:
--------------------------------------------------------------------------------
1 | USER: FIRST_NAME Kay
2 | USER: ID 123456789
3 | USER: LAST_NAME M
4 | USER: USERNAME Gnadelwartz
5 | CHAT: ALL_ADMIN
6 | CHAT: FIRST_NAME Test
7 | CHAT: ID 123456789
8 | CHAT: LAST_NAME Bot
9 | CHAT: TITLE BotTestTitle
10 | CHAT: TYPE private
11 | CHAT: USERNAME BotTest
12 | REPLYTO: 0 Ich bin der Deal-O-Mat Bot. Für eine Liste der Befehle sende /help
13 | REPLYTO: FIRST_NAME dealzbot
14 | REPLYTO: ID 6542
15 | REPLYTO: LAST_NAME
16 | REPLYTO: UID 987654321
17 | REPLYTO: USERNAME Deal_O_Mat_bot
18 | FORWARD: FIRST_NAME Kay
19 | FORWARD: ID 6541
20 | FORWARD: LAST_NAME M
21 | FORWARD: UID 123456789
22 | FORWARD: USERNAME Gnadelwartz
23 | URLS: AUDIO audio-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
24 | URLS: DOCUMENT document-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
25 | URLS: PHOTO photo-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
26 | URLS: STICKER sticker-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
27 | URLS: VIDEO video-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
28 | URLS: VOICE voice-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
29 | CONTACT: FIRST_NAME ADAC
30 | CONTACT: LAST_NAME Pannenhilfe
31 | CONTACT: NUMBER 222222
32 | CONTACT: USER_ID
33 | CONTACT: VCARD BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD
34 | CAPTION: 0 Myproteine kein spell check
35 | LOCATION: LATITUDE 49.631824
36 | LOCATION: LONGITUDE 8.377072
37 | MESSAGE: 0 😂😝👌☺❤😕😈#⃣🌏🎉🙊🙉☕🚀✈🚂💯✔〽🔚
38 | MESSAGE: CAPTION Myproteine kein spell check
39 | MESSAGE: DICE
40 | MESSAGE: ID 6541
41 | VENUE: ADDRESS Am Rhein 1
42 | VENUE: FOURSQUARE 4c4321afce54e21eee980d1a
43 | VENUE: LATITUDE 49.631824
44 | VENUE: LONGITUDE 8.377072
45 | VENUE: TITLE Kolb's Biergarten
46 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-new_chat_member.input:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 123456789
3 | ["result",0,"message","message_id"] 123456789
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","chat","id"] -123456789
11 | ["result",0,"message","chat","title"] "Testgruppe bot only test"
12 | ["result",0,"message","chat","type"] "group"
13 | ["result",0,"message","chat","all_members_are_administrators"] true
14 | ["result",0,"message","date"] 1592372719
15 |
16 | ["result",0,"message","new_chat_participant","id"] 123456789
17 | ["result",0,"message","new_chat_participant","is_bot"] false
18 | ["result",0,"message","new_chat_participant","first_name"] "Kay"
19 | ["result",0,"message","new_chat_participant","last_name"] "M"
20 | ["result",0,"message","new_chat_participant","username"] "Gnadelwartz"
21 | ["result",0,"message","new_chat_member","id"] 123456789
22 | ["result",0,"message","new_chat_member","is_bot"] false
23 | ["result",0,"message","new_chat_member","first_name"] "Kay"
24 | ["result",0,"message","new_chat_member","last_name"] "M"
25 | ["result",0,"message","new_chat_member","username"] "Gnadelwartz"
26 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-new_chat_member.result:
--------------------------------------------------------------------------------
1 | USER: FIRST_NAME Kay
2 | USER: ID 123456789
3 | USER: LAST_NAME M
4 | USER: USERNAME Gnadelwartz
5 | CHAT: ALL_ADMIN true
6 | CHAT: FIRST_NAME
7 | CHAT: ID 123456789
8 | CHAT: LAST_NAME
9 | CHAT: TITLE Testgruppe bot only test
10 | CHAT: TYPE group
11 | CHAT: USERNAME
12 | CAPTION: 0
13 | LOCATION: LATITUDE
14 | LOCATION: LONGITUDE
15 | MESSAGE: 0 /_new_chat_member 123456789 Gnadelwartz
16 | MESSAGE: CAPTION
17 | MESSAGE: DICE
18 | MESSAGE: ID 123456789
19 | SERVICE: 0 yes
20 | SERVICE: NEWMEMBER 123456789
21 | SERVICE: NEWPHOTO
22 | SERVICE: NEWTITLE
23 | NEWMEMBER: FIRST_NAME Kay
24 | NEWMEMBER: ID 123456789
25 | NEWMEMBER: ISBOT false
26 | NEWMEMBER: LAST_NAME M
27 | NEWMEMBER: USERNAME Gnadelwartz
28 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-new_chat_picture.input:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 123456789
3 | ["result",0,"message","message_id"] 123456789
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","chat","id"] -123456789
11 | ["result",0,"message","chat","title"] "Testgruppe bot only test"
12 | ["result",0,"message","chat","type"] "group"
13 | ["result",0,"message","chat","all_members_are_administrators"] true
14 | ["result",0,"message","date"] 1592372719
15 |
16 | ["result",0,"message","new_chat_photo",0,"file_id"] "AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANhAAM3SAMAARoE"
17 | ["result",0,"message","new_chat_photo",0,"file_unique_id"] "AQADK6S6ki4AAzdIAwAB"
18 | ["result",0,"message","new_chat_photo",0,"file_size"] 5939
19 | ["result",0,"message","new_chat_photo",0,"width"] 160
20 | ["result",0,"message","new_chat_photo",0,"height"] 160
21 | ["result",0,"message","new_chat_photo",1,"file_id"] "AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANiAAM4SAMAARoE"
22 | ["result",0,"message","new_chat_photo",1,"file_unique_id"] "AQADK6S6ki4AAzhIAwAB"
23 | ["result",0,"message","new_chat_photo",1,"file_size"] 14124
24 | ["result",0,"message","new_chat_photo",1,"width"] 320
25 | ["result",0,"message","new_chat_photo",1,"height"] 320
26 | ["result",0,"message","new_chat_photo",2,"file_id"] "AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANjAAM5SAMAARoE"
27 | ["result",0,"message","new_chat_photo",2,"file_unique_id"] "AQADK6S6ki4AAzlIAwAB"
28 | ["result",0,"message","new_chat_photo",2,"file_size"] 34052
29 | ["result",0,"message","new_chat_photo",2,"width"] 640
30 | ["result",0,"message","new_chat_photo",2,"height"] 640
31 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-new_chat_picture.result:
--------------------------------------------------------------------------------
1 | USER: FIRST_NAME Kay
2 | USER: ID 123456789
3 | USER: LAST_NAME M
4 | USER: USERNAME Gnadelwartz
5 | CHAT: ALL_ADMIN true
6 | CHAT: FIRST_NAME
7 | CHAT: ID 123456789
8 | CHAT: LAST_NAME
9 | CHAT: TITLE Testgruppe bot only test
10 | CHAT: TYPE group
11 | CHAT: USERNAME
12 | CAPTION: 0
13 | LOCATION: LATITUDE
14 | LOCATION: LONGITUDE
15 | MESSAGE: 0 /_new_chat_photo 123456789 AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANhAAM3SAMAARoE
16 | MESSAGE: CAPTION
17 | MESSAGE: DICE
18 | MESSAGE: ID 123456789
19 | SERVICE: 0 yes
20 | SERVICE: NEWPHOTO AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANhAAM3SAMAARoE
21 | SERVICE: NEWTITLE
22 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-new_chat_title.input:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 123456789
3 | ["result",0,"message","message_id"] 123456789
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","chat","id"] -123456789
11 | ["result",0,"message","chat","title"] "Testgruppe bot only test"
12 | ["result",0,"message","chat","type"] "group"
13 | ["result",0,"message","chat","all_members_are_administrators"] true
14 | ["result",0,"message","date"] 1592372719
15 |
16 | ["result",0,"message","new_chat_title"] "new Testgruppe bot only"
17 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-new_chat_title.result:
--------------------------------------------------------------------------------
1 | USER: FIRST_NAME Kay
2 | USER: ID 123456789
3 | USER: LAST_NAME M
4 | USER: USERNAME Gnadelwartz
5 | CHAT: ALL_ADMIN true
6 | CHAT: FIRST_NAME
7 | CHAT: ID 123456789
8 | CHAT: LAST_NAME
9 | CHAT: TITLE Testgruppe bot only test
10 | CHAT: TYPE group
11 | CHAT: USERNAME
12 | CAPTION: 0
13 | LOCATION: LATITUDE
14 | LOCATION: LONGITUDE
15 | MESSAGE: 0 /_new_chat_title 123456789 new Testgruppe bot only
16 | MESSAGE: CAPTION
17 | MESSAGE: DICE
18 | MESSAGE: ID 123456789
19 | SERVICE: 0 yes
20 | SERVICE: NEWPHOTO
21 | SERVICE: NEWTITLE new Testgruppe bot only
22 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-pinned_message.input:
--------------------------------------------------------------------------------
1 | ["ok"] true
2 | ["result",0,"update_id"] 123456789
3 | ["result",0,"message","message_id"] 123456789
4 | ["result",0,"message","from","id"] 123456789
5 | ["result",0,"message","from","is_bot"] false
6 | ["result",0,"message","from","first_name"] "Kay"
7 | ["result",0,"message","from","last_name"] "M"
8 | ["result",0,"message","from","username"] "Gnadelwartz"
9 | ["result",0,"message","from","language_code"] "de"
10 | ["result",0,"message","chat","id"] -123456789
11 | ["result",0,"message","chat","title"] "Testgruppe bot only test"
12 | ["result",0,"message","chat","type"] "group"
13 | ["result",0,"message","chat","all_members_are_administrators"] true
14 | ["result",0,"message","date"] 1592372719
15 |
16 | ["result",0,"message","pinned_message","message_id"] 3022
17 | ["result",0,"message","pinned_message","from","id"] 796814662
18 | ["result",0,"message","pinned_message","from","is_bot"] true
19 | ["result",0,"message","pinned_message","from","first_name"] "DealOMat"
20 | ["result",0,"message","pinned_message","from","username"] "Deal_O_Mat_bot"
21 | ["result",0,"message","pinned_message","chat","id"] -1001220313778
22 | ["result",0,"message","pinned_message","chat","title"] "Testgruppe bot only test"
23 | ["result",0,"message","pinned_message","chat","type"] "supergroup"
24 | ["result",0,"message","pinned_message","date"] 1593121152
25 | ["result",0,"message","pinned_message","text"] "new pinned Message"
26 |
27 | ["result",0,"message","new_chat_title"] "new Testgruppe bot only"
28 |
--------------------------------------------------------------------------------
/test/d-process_message-test/d-process_message-test-pinned_message.result:
--------------------------------------------------------------------------------
1 | USER: FIRST_NAME Kay
2 | USER: ID 123456789
3 | USER: LAST_NAME M
4 | USER: USERNAME Gnadelwartz
5 | CHAT: ALL_ADMIN true
6 | CHAT: FIRST_NAME
7 | CHAT: ID 123456789
8 | CHAT: LAST_NAME
9 | CHAT: TITLE Testgruppe bot only test
10 | CHAT: TYPE group
11 | CHAT: USERNAME
12 | CAPTION: 0
13 | LOCATION: LATITUDE
14 | LOCATION: LONGITUDE
15 | MESSAGE: 0 /_new_pinned_message 123456789 3022 new pinned Message
16 | MESSAGE: CAPTION
17 | MESSAGE: DICE
18 | MESSAGE: ID 123456789
19 | SERVICE: 0 yes
20 | SERVICE: NEWPHOTO
21 | SERVICE: NEWTITLE new Testgruppe bot only
22 | SERVICE: PINNED 3022
23 | PINNED: ID 3022
24 | PINNED: MESSAGE new pinned Message
25 |
--------------------------------------------------------------------------------
/test/d-send_message-test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #===============================================================================
3 | #
4 | # FILE: d-send_message-test.sh
5 | #
6 | # USAGE: must run only from dev/all-tests.sh
7 | #
8 | # DESCRIPTION: test sending messages
9 | #
10 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
11 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
12 | #
13 | #### $$VERSION$$ v1.52-1-g0dae2db
14 | #===============================================================================
15 |
16 | # include common functions and definitions
17 | # shellcheck source=test/ALL-tests.inc.sh
18 | source "./ALL-tests.inc.sh"
19 |
20 | set -e
21 | set +f
22 |
23 | cd "${TESTDIR}" || exit 1
24 |
25 | # source bashbot.sh function, uncomment if you want to test functions
26 | # shellcheck source=./bashbot.sh
27 | source "${TESTDIR}/bashbot.sh" source
28 | # shellcheck source=./bashbot.sh
29 | source "${TESTDIR}/commands.sh" source
30 |
31 | _is_function send_message || printf "Send Message not found!\n"
32 |
33 | # start writing your tests here ...
34 |
35 | # over write sendJson to output parameter only
36 | sendEmpty() {
37 | printf 'chat:%s\tJSON:%s\nURL:%s\n\n' "$1" "$2" "$3"
38 | }
39 |
40 | sendJson() {
41 | printf 'chat:%s\tJSON:%s\nURL:%s\n\n' "$1" "$2" "$3"
42 | }
43 | sendUpload() {
44 | #JSON:"document":"/tmp/allowed/this_is_my.doc","caption":"Text plus absolute file will appear in chat""
45 | printf 'chat:%s\tJSON:"%s":"%s","caption":"%s"\nURL:%s\n\n' "$1" "$2" "$3" "$5" "$4"
46 | }
47 |
48 | # send text input to send_message
49 |
50 | printf " Send line ..."
51 |
52 | # create dummy files for upload
53 | ALLOW='/tmp/allowed'
54 | FILE_REGEX="${ALLOW}/.*"
55 | [ -d "${ALLOW}" ] || mkdir "${ALLOW}"
56 | touch "${ALLOW}/this_is_my.gif" "${ALLOW}/this_is_my.doc"
57 | touch "${DATADIR}/this_is_my.gif" "${DATADIR}/this_is_my.doc"
58 |
59 | while read -r line ; do
60 | set -x; set +e
61 | send_message "123456" "${line}" >>"${OUTPUTFILE}"
62 | set +x; set -e
63 | printf "."
64 | done < "${INPUTFILE}" 2>>"${LOGFILE}"
65 | [ -d "${ALLOW}" ] && rm -rf "${ALLOW}"
66 |
67 | printf " done.\n"
68 |
69 | { compare_sorted "${REFFILE}" "${OUTPUTFILE}" || exit 1; } | cat -v
70 | rm -f "${REFFILE}.sort"
71 |
72 | printf " ... all \"send_message\" functions seems to work as expected.\n"
73 |
74 | printf "%s\n" "${SUCCESS}"
75 |
76 |
77 |
--------------------------------------------------------------------------------
/test/d-send_message-test/d-send_message-test.input:
--------------------------------------------------------------------------------
1 | # test for text only output
2 | This is a normal text
3 | This is a normal text mynewlinestartshere with a line break
4 | html_parse_mode This is a HTML text
5 | html_parse_mode This is a HTML text mynewlinestartshere with a line break
6 | markdown_parse_mode This is a *MARKDOWN* text
7 | markdown_parse_mode This is a *MARKDOWN* text mynewlinestartshere with a line break
8 |
9 | # test for keyboard, file, venue output
10 | Text plus keyboard will appear in chat mykeyboardstartshere [ "Yep, sure" , "No, highly unlikely" ]
11 | Text plus location will appear in chat mylatstartshere la10 mylongstartshere lo20
12 | Text plus vuene will appear in chat mylatstartshere la10 mylongstartshere lo20 mytitlestartshere my home myaddressstartshere Diagon Alley N. 37
13 |
14 | # test for new inline button
15 | Text plus keyboard will appear in chat mybtextstartshere Button Text myburlstartshere https://www...
16 | STABILO 88/240 Fineliner point 88 mynewlinestartshere mynewlinestartshere [https://images-na.ssl-images-amazon.com/images/I/41oypA3kmHL.l_SX300.jpg] mynewlinestartshere mybtextstartshere Bei Amazon ansehen ... myburlstartshere https://www.amazon.de/dp/B014TN3JYW mytextstartshere second part of text mynewlinestartshere plus newline.
17 |
18 | # test for sendfile
19 | Text plus absolute file will appear in chat myfilelocationstartshere /tmp/allowed/this_is_my.gif
20 | Text plus absolute file will appear in chat myfilelocationstartshere /tmp/allowed/this_is_my.doc
21 | Text plus relative file will appear in chat myfilelocationstartshere this_is_my.gif
22 | Text plus relative file will appear in chat myfilelocationstartshere this_is_my.doc
23 | THIS IS OUTSIDE allowed myfilelocationstartshere /home/user/NOTallowed/this_is_my.dif
24 | THIS DOES NOT EXIST myfilelocationstartshere /tmp/allowed/this_does_not_exist.gif
25 | THIS DOES NOT EXIST myfilelocationstartshere this_does_not_exist.gif
26 |
27 |
--------------------------------------------------------------------------------
/test/d-send_message-test/d-send_message-test.result:
--------------------------------------------------------------------------------
1 | chat:123456 JSON:"text":"\# test for text only output"
2 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
3 |
4 | chat:123456 JSON:"text":"This is a normal text"
5 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
6 |
7 | chat:123456 JSON:"text":"This is a normal text\nwith a line break"
8 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
9 |
10 | chat:123456 JSON:"text":" This is a HTML<\/b> text","parse_mode":"html"
11 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
12 |
13 | chat:123456 JSON:"text":" This is a HTML<\/b> text\nwith a line break","parse_mode":"html"
14 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
15 |
16 | chat:123456 JSON:"text":" This is a \*MARKDOWN\* text","parse_mode":"markdown"
17 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
18 |
19 | chat:123456 JSON:"text":" This is a \*MARKDOWN\* text\nwith a line break","parse_mode":"markdown"
20 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
21 |
22 | chat:123456 JSON:"text":"\# test for keyboard\, file\, venue output"
23 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
24 |
25 | chat:123456 JSON:"text":"Text plus keyboard will appear in chat", "reply_markup": {"keyboard": [ [ "Yep, sure" , "No, highly unlikely" ] ] , "one_time_keyboard":true}
26 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
27 |
28 | chat:123456 JSON:"latitude": la10, "longitude": lo20
29 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendLocation
30 |
31 | chat:123456 JSON:"latitude": la10, "longitude": lo20, "address": "Diagon Alley N. 37", "title": "my home"
32 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendVenue
33 |
34 | chat:123456 JSON:"text":"\# test for new inline button"
35 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
36 |
37 | chat:123456 JSON:"text":"Text plus keyboard will appear in chat", "reply_markup": {"inline_keyboard": [ [{"text":"Button Text", "url":"https://www..."}] ]}
38 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
39 |
40 | chat:123456 JSON:"text":"STABILO 88\/240 Fineliner point 88\n\n[https:\/\/images\-na\.ssl\-images\-amazon\.com\/images\/I\/41oypA3kmHL\.l_SX300\.jpg]\nsecond part of text\nplus newline\.", "reply_markup": {"inline_keyboard": [ [{"text":"Bei Amazon ansehen \.\.\.", "url":"https://www.amazon.de/dp/B014TN3JYW"}] ]}
41 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
42 |
43 | chat:123456 JSON:"text":"\# test for sendfile"
44 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
45 |
46 | chat:123456 JSON:"photo":"/tmp/allowed/this_is_my.gif","caption":"Text plus absolute file will appear in chat"
47 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendPhoto
48 |
49 | chat:123456 JSON:"action": "upload_photo"
50 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendChatAction
51 |
52 | chat:123456 JSON:"document":"/tmp/allowed/this_is_my.doc","caption":"Text plus absolute file will appear in chat"
53 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendDocument
54 |
55 | chat:123456 JSON:"action": "upload_document"
56 | URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendChatAction
57 |
58 |
--------------------------------------------------------------------------------
/test/d-user_is-test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #===============================================================================
3 | #
4 | # FILE: d-user_is-test.sh
5 | #
6 | # USAGE: must run only from dev/all-tests.sh
7 | #
8 | # DESCRIPTION: test user ACLs
9 | #
10 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
11 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
12 | #
13 | #### $$VERSION$$ v1.52-1-g0dae2db
14 | #===============================================================================
15 |
16 | # include common functions and definitions
17 | # shellcheck source=test/ALL-tests.inc.sh
18 | source "./ALL-tests.inc.sh"
19 |
20 | set -e
21 | set +f
22 |
23 | cd "${TESTDIR}" || exit 1
24 |
25 | # reset BOTADMIN
26 | printf '["botadmin"] "?"\n' >>"${ADMINFILE}" # auto mode
27 |
28 | # source bashbot.sh function, uncomment if you want to test functions
29 | # shellcheck source=./bashbot.sh
30 | source "${TESTDIR}/bashbot.sh" source
31 | # shellcheck source=./bashbot.sh
32 | source "${TESTDIR}/commands.sh" source
33 |
34 | # start writing your tests here ...
35 |
36 | # first user asking for botadmin will botadmin
37 | printf "Check \"user_is_botadmin\" ...\n"
38 |
39 | printf "BOTADMIN ...\n"
40 | user_is_botadmin "BOTADMIN" || exit 1 # should never fail
41 | printf "NOBOTADMIN ...\n"
42 | user_is_botadmin "NOBOTADMIN" && exit 1 # should fail
43 | printf "BOTADMIN ...\n"
44 | user_is_botadmin "BOTADMIN" || exit 1 # same name as first one, should work
45 |
46 | printf "Check config file ...\n"
47 | if [ "$(getConfigKey "botadmin")" = "BOTADMIN" ]; then
48 | printf " ... \"user_is_botadmin\" seems to work as expected.\n"
49 | else
50 | exit 1
51 | fi
52 | printf "%s\n" "${SUCCESS}"
53 |
54 | # lets see If UAC works ...
55 | printf "Check \"user_is_allowed\" ...\n"
56 |
57 | printf " ... with not rules\n"
58 | user_is_allowed "NOBOTADMIN" "ANYTHING" && exit 1 # should always fail because no rules exist
59 | user_is_allowed "BOTADMIN" "ANYTHING" && exit 1 # should fail even is BOTADMIN
60 | printf "%s\n" "${SUCCESS}"
61 |
62 | printf " ... with BOTADMIN:*:*\n"
63 | printf 'BOTADMIN:*:*\n' >"${ACLFILE}" # RULE allow BOTADMIN everything
64 |
65 | user_is_allowed "BOTADMIN" "ANYTHING" || exit 1 # should work now
66 | user_is_allowed "NOBOTADMIN" "ANYTHING" && exit 1 # should fail because user is not listed
67 | printf "%s\n" "${SUCCESS}"
68 |
69 | printf " ... with NOBOTAMIN:SOMETHING:*\n"
70 | printf 'NOBOTADMIN:SOMETHING:*\n' >>"${ACLFILE}" # RULE allow NOBOTADMIN something
71 |
72 | user_is_allowed "BOTADMIN" "ANYTHING" || exit 1 # should work
73 | user_is_allowed "BOTADMIN" "SOMETHING" || exit 1 # should work
74 | user_is_allowed "NOBOTADMIN" "SOMETHING" || exit 1 # should work now
75 | user_is_allowed "NOBOTADMIN" "ANYTHING" && exit 1 # should fail because only SOMETHING is listed
76 |
77 | printf "%s\n" "${SUCCESS}"
78 |
79 | printf " ... \"user_is_allowed\" seems to work as expected.\n"
80 |
81 |
--------------------------------------------------------------------------------
/test/e-env-test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #===============================================================================
3 | #
4 | # FILE: e-env-test.sh
5 | #
6 | # USAGE: must run only from dev/all-tests.sh
7 | #
8 | # DESCRIPTION: test BASHBOT_xxx variables working as expected
9 | #
10 | # LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
11 | # AUTHOR: KayM (gnadelwartz), kay@rrr.de
12 | #
13 | #### $$VERSION$$ v1.52-1-g0dae2db
14 | #===============================================================================
15 |
16 | # include common functions and definitions
17 | # shellcheck source=test/ALL-tests.inc.sh
18 | source "./ALL-tests.inc.sh"
19 |
20 | set -e
21 |
22 | #cd "${TESTDIR}" || exit 1
23 |
24 | # source bashbot.sh function, uncomment if you want to test functions
25 | # shellcheck source=./bashbot.sh
26 | # source "\/bashbot.sh" source
27 |
28 | # start writing your tests here ...
29 | # test setting of env variables to different locations
30 |
31 | export BASHBOT_ETC="${TESTDIR}/env/etc/bashbot"
32 | export BASHBOT_VAR="${TESTDIR}/env/var/bashbot"
33 | export BASHBOT_JSONSH="${TESTDIR}/env/local/bin/JSON.sh"
34 | BASHBOT_BIN="${TESTDIR}/env/local/bin"
35 |
36 | # create dirs
37 | mkdir -p "${BASHBOT_ETC}" || exit 1
38 | mkdir -p "${BASHBOT_VAR}" || exit 1
39 | mkdir -p "${BASHBOT_BIN}" || exit 1
40 |
41 | # cp bashbot files to new locations
42 | set +f
43 | # shellcheck disable=SC2086
44 | cp ${TESTDIR}/*commands.sh "${BASHBOT_ETC}" || exit 1
45 | set -f
46 | cp -r "${TESTDIR}/bashbot.sh" "${TESTDIR}/modules" "${TESTDIR}/JSON.sh/JSON.sh" "${BASHBOT_BIN}" || exit 1
47 |
48 | TESTFILES="${TOKENFILE} ${ACLFILE}"
49 |
50 |
51 | printf "Check first run in ENVIRONMENT ...\n"
52 | mkdir "${BASHBOT_VAR}/${DATADIR}"
53 |
54 | # run bashbot first time with init
55 | "${BASHBOT_BIN}/bashbot.sh" init >"${LOGFILE}" <>"${LOGFILE}"
85 | if ! diff -q "${BASHBOT_ETC}/${file}" "${REFDIR}/${file}" >>"${LOGFILE}"; then printf "%s\n" "${NOSUCCESS} Fail diff ${file}!"; FAIL="1"; fi
86 |
87 | done
88 |
89 | printf " ... BASHBOT_ETC seems to work!\n"
90 | printf "%s\n" "${SUCCESS}"
91 |
--------------------------------------------------------------------------------
/test/e-env-test/blocked.jssh:
--------------------------------------------------------------------------------
1 | ["blocked_user_or_chat_id"] "name and reason"
2 |
--------------------------------------------------------------------------------
/test/e-env-test/botacl:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/test/e-env-test/botconfig.jssh:
--------------------------------------------------------------------------------
1 | ["bot_config_key"] "config_key_value"
2 | ["bottoken"] "123456789:BASHBOTTESTSCRIPTbashbottestscript_"
3 | ["botadmin"] "?"
4 |
--------------------------------------------------------------------------------
/test/e-env-test/count.jssh:
--------------------------------------------------------------------------------
1 | ["counted_user_chat_id"] "num_messages_seen"
2 |
--------------------------------------------------------------------------------