Merge pull request #69 from topkecleon/develop

Sync Master with Develop Security changes
This commit is contained in:
Kay Marquardt 2019-04-11 08:13:52 +02:00 committed by GitHub
commit 035627011a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 217 additions and 99 deletions

View File

@ -17,10 +17,8 @@ Elsewhere, consider it released under the [WTFPLv2](http://www.wtfpl.net/txt/cop
## Install bashbot ## Install bashbot
1. Go to the directory you want to install bashbot, e.g. 1. Go to the directory you want to install bashbot, e.g.
- your $HOME directory (install and run with your user-ID)
- your $HOME directory (install and run with your user-ID) - /usr/local if you want to run as service
- /usr/local if you want to run as service
2. Clone the repository: 2. Clone the repository:
``` ```
git clone --recursive https://github.com/topkecleon/telegram-bot-bash git clone --recursive https://github.com/topkecleon/telegram-bot-bash
@ -75,4 +73,4 @@ No - its not less (in)secure as any other Bot written in any other language. But
If you feel that there's something missing or if you found a bug, feel free to submit a pull request! If you feel that there's something missing or if you found a bug, feel free to submit a pull request!
#### $$VERSION$$ v0.50-13-g4d5d386 #### $$VERSION$$ v0.51-0-g4ddd122

111
README.txt Normal file
View File

@ -0,0 +1,111 @@
bashbot
-------
A Telegram bot written in bash.
Depends on http://github.com/tmux/tmux[tmux]. Uses
http://github.com/dominictarr/JSON.sh[JSON.sh].
Written by Drew (@topkecleon), Daniil Gentili (@danogentili), and Kay M
(@gnadelwartz).
Contributions by JuanPotato, BigNerd95, TiagoDanin, and iicc1.
https://github.com/topkecleon/telegram-bot-bash/releases[Download from
github]
Released to the public domain wherever applicable. Elsewhere, consider
it released under the http://www.wtfpl.net/txt/copying/[WTFPLv2].
Install bashbot
~~~~~~~~~~~~~~~
1. Go to the directory you want to install bashbot, e.g.
* your $HOME directory (install and run with your user-ID)
* /usr/local if you want to run as service
1. Clone the repository:
+
....
git clone --recursive https://github.com/topkecleon/telegram-bot-bash
....
2. Change to directory `telegram-bot.bash`, run `./bashbot.sh init` and
follow the instructions. At this stage you are asked for your Bots token
given by botfather.
Getting started
~~~~~~~~~~~~~~~
* link:doc/1_firstbot.md[Create your first telegram bot]
* link:doc/2_usage.md[Make your own Bot]
* Managing your own Bot
* Recieve data
* Send Messages
* Send files, location etc.
* link:doc/3_advanced.md[Advatage Features]
* Interactive Chats
* Background Jobs
* Inline queries
* link:doc/4_expert.md[Expert Use]
* Handling UTF-8
* Run as other user or system service
* Scedule bashbot from Cron
Security Considerations
~~~~~~~~~~~~~~~~~~~~~~~
Running a Telegram Bot means you are conneted to the public, you never
know whats send to your Bot.
Bash scripts in general are not designed to be bullet proof, so consider
this Bot as a proof of concept. More concret examples of security
problems is bash's 'quoting hell' and globbing.
https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells[Implications
of wrong quoting]
Whenever you are processing input from outside your bot you should
disable globbing (set -f) and carefully quote everthing.
To improve you scripts we recommend to lint them with
https://www.shellcheck.net/[shellcheck]. This can be done online or you
can https://github.com/koalaman/shellcheck#installing[install shellcheck
locally]. bashbot itself is also linted by shellcheck.
Run your Bot as a restricted user
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Every file your bot can write is in danger to be overwritten/deleted, In
case of bad handling of user input every file your Bot can read is in
danger of being disclosed.
Never run your Bot as root, this is the most dangerous you can do!
Usually the user 'nobody' has almost no rigths on Unix/Linux systems.
See Expert use on how to run your Bot as an other user.
Secure your Bot installation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Everyone who can read your Bot files can extract your Bots data.
Especially your Bot Token in `token` must be protected against other
users. No one exept you should have write access to the Bot files. The
Bot itself need write access to `count` and `tmp-bot-bash` only, all
other files should be write protected.
Runing `./bashbot.sh init` sets the Bot permissions to reasonable
default values as a starting point.
Is this Bot insecure?
^^^^^^^^^^^^^^^^^^^^^
No - its not less (in)secure as any other Bot written in any other
language. But you should know about the implications ...
That's it!
~~~~~~~~~~
If you feel that there's something missing or if you found a bug, feel
free to submit a pull request!
latexmath:[\[VERSION\]] v0.6-dev2-0-g143c122
++++++++++++++++++++++++++++++++++++++++++++

View File

@ -7,7 +7,7 @@
# This file is public domain in the USA and all free countries. # This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
# #
#### $$VERSION$$ v0.5-0-gfd81668 #### $$VERSION$$ v0.51-0-g4ddd122
SHELL=/bin/sh SHELL=/bin/sh

View File

@ -1,7 +1,10 @@
#!/bin/sh #!/bin/sh
# description: Start or stop telegram-bash-bot # description: Start or stop telegram-bash-bot
# #
#### $$VERSION$$ v0.5-0-gfd81668 #### $$VERSION$$ v0.51-0-g4ddd122
# shellcheck disable=SC2009
# shellcheck disable=SC2181
# #
### BEGIN INIT INFO ### BEGIN INIT INFO
# Provides: bashbot # Provides: bashbot

View File

@ -10,7 +10,7 @@
# This file is public domain in the USA and all free countries. # This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
# #
#### $$VERSION$$ v0.5-2-g09678a1 #### $$VERSION$$ v0.51-0-g4ddd122
# #
# Exit Codes: # Exit Codes:
# - 0 sucess (hopefully) # - 0 sucess (hopefully)
@ -29,8 +29,9 @@ if [ -t 1 ] && [ "$TERM" != "" ]; then
fi fi
# get location of bashbot.sh an change to bashbot dir # get location of bashbot.sh an change to bashbot dir
SCRIPT="./$(basename $0)" SCRIPT="./$(basename "$0")"
SCRIPTDIR="$(dirname $0)" SCRIPTDIR="$(dirname "$0")"
RUNUSER="$USER" # USER is overwritten as array, $USER may not work later on...
if ! cd "${SCRIPTDIR}" ; then if ! cd "${SCRIPTDIR}" ; then
echo -e "${RED}ERROR: Can't change to ${SCRIPTDIR} ...${NC}" echo -e "${RED}ERROR: Can't change to ${SCRIPTDIR} ...${NC}"
@ -52,7 +53,7 @@ if [ ! -f "token" ]; then
$CLEAR $CLEAR
echo -e "${RED}TOKEN MISSING.${NC}" echo -e "${RED}TOKEN MISSING.${NC}"
echo -e "${ORANGE}PLEASE WRITE YOUR TOKEN HERE${NC}" echo -e "${ORANGE}PLEASE WRITE YOUR TOKEN HERE${NC}"
read token read -r token
echo "$token" >> "token" echo "$token" >> "token"
fi fi
@ -98,7 +99,7 @@ FORWARD_URL=$URL'/forwardMessage'
INLINE_QUERY=$URL'/answerInlineQuery' INLINE_QUERY=$URL'/answerInlineQuery'
ME_URL=$URL'/getMe' ME_URL=$URL'/getMe'
DELETE_URL=$URL'/deleteMessage' DELETE_URL=$URL'/deleteMessage'
ME=$(curl -s $ME_URL | ./JSON.sh/JSON.sh -s | egrep '\["result","username"\]' | cut -f 2 | cut -d '"' -f 2) ME=$(curl -s "$ME_URL" | ./JSON.sh/JSON.sh -s | grep '\["result","username"\]' | cut -f 2 | cut -d '"' -f 2)
FILE_URL='https://api.telegram.org/file/bot'$TOKEN'/' FILE_URL='https://api.telegram.org/file/bot'$TOKEN'/'
@ -113,47 +114,48 @@ urlencode() {
send_message() { send_message() {
local text arg keyboard file lat long title address sent
[ "$2" = "" ] && return 1 [ "$2" = "" ] && return 1
local chat="$1" local chat="$1"
local text="$(echo "$2" | sed 's/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ mylongstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')" text="$(echo "$2" | sed 's/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ mylongstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')"
local arg="$3" arg="$3"
[ "$3" != "safe" ] && { [ "$arg" != "safe" ] && {
text="$(echo "$text" | sed 's/ mynewlinestartshere /\r\n/g')" # hack for linebreaks in startproc scripts text="$(echo "$text" | sed 's/ mynewlinestartshere /\r\n/g')" # hack for linebreaks in startproc scripts
local no_keyboard="$(echo $2 | sed '/mykeyboardendshere/!d;s/.*mykeyboardendshere.*/mykeyboardendshere/')" no_keyboard="$(echo "$2" | sed '/mykeyboardendshere/!d;s/.*mykeyboardendshere.*/mykeyboardendshere/')"
local keyboard="$(echo "$2" | sed '/mykeyboardstartshere /!d;s/.*mykeyboardstartshere //g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ mylongstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')" keyboard="$(echo "$2" | sed '/mykeyboardstartshere /!d;s/.*mykeyboardstartshere //g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ mylongstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')"
local file="$(echo "$2" | sed '/myfilelocationstartshere /!d;s/.*myfilelocationstartshere //g;s/ mykeyboardstartshere.*//g;s/ mylatstartshere.*//g;s/ mylongstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')" file="$(echo "$2" | sed '/myfilelocationstartshere /!d;s/.*myfilelocationstartshere //g;s/ mykeyboardstartshere.*//g;s/ mylatstartshere.*//g;s/ mylongstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')"
local lat="$(echo "$2" | sed '/mylatstartshere /!d;s/.*mylatstartshere //g;s/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylongstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')" lat="$(echo "$2" | sed '/mylatstartshere /!d;s/.*mylatstartshere //g;s/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylongstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')"
local long="$(echo "$2" | sed '/mylongstartshere /!d;s/.*mylongstartshere //g;s/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')" long="$(echo "$2" | sed '/mylongstartshere /!d;s/.*mylongstartshere //g;s/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ mytitlestartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')"
local title="$(echo "$2" | sed '/mytitlestartshere /!d;s/.*mylongstartshere //g;s/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')" title="$(echo "$2" | sed '/mytitlestartshere /!d;s/.*mylongstartshere //g;s/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ myaddressstartshere.*//g;s/ mykeyboardendshere.*//g')"
local address="$(echo "$2" | sed '/myaddressstartshere /!d;s/.*mylongstartshere //g;s/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ mytitlestartshere.*//g;s/ mykeyboardendshere.*//g')" address="$(echo "$2" | sed '/myaddressstartshere /!d;s/.*mylongstartshere //g;s/ mykeyboardstartshere.*//g;s/ myfilelocationstartshere.*//g;s/ mylatstartshere.*//g;s/ mytitlestartshere.*//g;s/ mykeyboardendshere.*//g')"
} }
if [ "$no_keyboard" != "" ]; then if [ "$no_keyboard" != "" ]; then
echo "remove_keyboard $chat $text" > $TMPDIR/prova echo "remove_keyboard $chat $text" > ${TMPDIR:-.}/prova
remove_keyboard "$chat" "$text" remove_keyboard "$chat" "$text"
local sent=y sent=y
fi fi
if [ "$keyboard" != "" ]; then if [ "$keyboard" != "" ]; then
send_keyboard "$chat" "$text" "$keyboard" send_keyboard "$chat" "$text" "$keyboard"
local sent=y sent=y
fi fi
if [ "$file" != "" ]; then if [ "$file" != "" ]; then
send_file "$chat" "$file" "$text" send_file "$chat" "$file" "$text"
local sent=y sent=y
fi fi
if [ "$lat" != "" -a "$long" != "" -a "$address" = "" -a "$title" = "" ]; then if [ "$lat" != "" ] && [ "$long" != "" ] && [ "$address" = "" ] && [ "$title" = "" ]; then
send_location "$chat" "$lat" "$long" send_location "$chat" "$lat" "$long"
local sent=y sent=y
fi fi
if [ "$lat" != "" -a "$long" != "" -a "$address" != "" -a "$title" != "" ]; then if [ "$lat" != "" ] && [ "$long" != "" ] && [ "$address" != "" ] && [ "$title" != "" ]; then
send_venue "$chat" "$lat" "$long" "$title" "$address" send_venue "$chat" "$lat" "$long" "$title" "$address"
local sent=y sent=y
fi fi
if [ "$sent" != "y" ];then if [ "$sent" != "y" ];then
send_text "$chat" "$text" send_text "$chat" "$text"
@ -291,9 +293,9 @@ send_keyboard() {
local keyboard=init local keyboard=init
OLDIFS=$IFS OLDIFS=$IFS
IFS=$(echo -en "\"") IFS=$(echo -en "\"")
for f in $*;do [ "$f" != " " ] && local keyboard="$keyboard, [\"$f\"]";done for f in "$@" ;do [ "$f" != " " ] && keyboard="$keyboard, [\"$f\"]";done
IFS=$OLDIFS IFS=$OLDIFS
local keyboard=${keyboard/init, /} keyboard=${keyboard/init, /}
res="$(curl -s "$MSG_URL" --header "content-type: multipart/form-data" -F "chat_id=$chat" -F "text=$text" -F "reply_markup={\"keyboard\": [$keyboard],\"one_time_keyboard\": true}")" res="$(curl -s "$MSG_URL" --header "content-type: multipart/form-data" -F "chat_id=$chat" -F "text=$text" -F "reply_markup={\"keyboard\": [$keyboard],\"one_time_keyboard\": true}")"
} }
@ -305,27 +307,28 @@ remove_keyboard() {
} }
get_file() { get_file() {
[ "$1" != "" ] && echo $FILE_URL$(curl -s "$GET_URL" -F "file_id=$1" | ./JSON.sh/JSON.sh -s | egrep '\["result","file_path"\]' | cut -f 2 | cut -d '"' -f 2) [ "$1" != "" ] && echo "$FILE_URL$(curl -s "$GET_URL" -F "file_id=$1" | ./JSON.sh/JSON.sh -s | grep '\["result","file_path"\]' | cut -f 2 | cut -d '"' -f 2)"
} }
send_file() { send_file() {
[ "$2" = "" ] && return [ "$2" = "" ] && return
local CAPTION
local chat_id=$1 local chat_id=$1
local file=$2 local file=$2
echo "$file" | grep -qE $FILE_REGEX || return echo "$file" | grep -qE "$FILE_REGEX" || return
local ext="${file##*.}" local ext="${file##*.}"
case $ext in case $ext in
mp3|flac) mp3|flac)
CUR_URL=$AUDIO_URL CUR_URL=$AUDIO_URL
WHAT=audio WHAT=audio
STATUS=upload_audio STATUS=upload_audio
local CAPTION="$3" CAPTION="$3"
;; ;;
png|jpg|jpeg|gif) png|jpg|jpeg|gif)
CUR_URL=$PHO_URL CUR_URL=$PHO_URL
WHAT=photo WHAT=photo
STATUS=upload_photo STATUS=upload_photo
local CAPTION="$3" CAPTION="$3"
;; ;;
webp) webp)
CUR_URL=$STICKER_URL CUR_URL=$STICKER_URL
@ -336,7 +339,7 @@ send_file() {
CUR_URL=$VIDEO_URL CUR_URL=$VIDEO_URL
WHAT=video WHAT=video
STATUS=upload_video STATUS=upload_video
local CAPTION="$3" CAPTION="$3"
;; ;;
ogg) ogg)
@ -348,10 +351,10 @@ send_file() {
CUR_URL=$DOCUMENT_URL CUR_URL=$DOCUMENT_URL
WHAT=document WHAT=document
STATUS=upload_document STATUS=upload_document
local CAPTION="$3" CAPTION="$3"
;; ;;
esac esac
send_action $chat_id $STATUS send_action "$chat_id" "$STATUS"
res="$(curl -s "$CUR_URL" -F "chat_id=$chat_id" -F "$WHAT=@$file" -F "caption=$CAPTION")" res="$(curl -s "$CUR_URL" -F "chat_id=$chat_id" -F "$WHAT=@$file" -F "caption=$CAPTION")"
} }
@ -370,7 +373,7 @@ send_location() {
send_venue() { send_venue() {
[ "$5" = "" ] && return [ "$5" = "" ] && return
[ "$6" != "" ] add="-F \"foursquare_id=$6\"" [ "$6" != "" ] add="-F \"foursquare_id=$6\""
res="$(curl -s "$VENUE_URL" -F "chat_id=$1" -F "latitude=$2" -F "longitude=$3" -F "title=$4" -F "address=$5" $add)" res="$(curl -s "$VENUE_URL" -F "chat_id=$1" -F "latitude=$2" -F "longitude=$3" -F "title=$4" -F "address=$5")"
} }
@ -381,16 +384,16 @@ forward() {
background() { background() {
echo "${CHAT[ID]}:$2:$1" >"$TMPDIR/${copname}$2-back.cmd" echo "${CHAT[ID]}:$2:$1" >"${TMPDIR:-.}/${copname}$2-back.cmd"
startproc "$1" "back-$2-" startproc "$1" "back-$2-"
} }
startproc() { startproc() {
killproc "$2" killproc "$2"
local fifo="$2${copname}" # add $1 to copname, so we can have more than one running script per chat local fifo="$2${copname}" # add $1 to copname, so we can have more than one running script per chat
mkfifo "$TMPDIR/${fifo}" mkfifo "${TMPDIR:-.}/${fifo}"
TMUX= tmux new-session -d -s "${fifo}" "$1 &>$TMPDIR/${fifo}; echo imprettydarnsuredatdisisdaendofdacmd>$TMPDIR/${fifo}" tmux new-session -d -s "${fifo}" "$1 &>${TMPDIR:-.}/${fifo}; echo imprettydarnsuredatdisisdaendofdacmd>${TMPDIR:-.}/${fifo}"
TMUX= tmux new-session -d -s sendprocess_${fifo} "bash $SCRIPT outproc ${CHAT[ID]} ${fifo}" tmux new-session -d -s "sendprocess_${fifo}" "bash $SCRIPT outproc ${CHAT[ID]} ${fifo}"
} }
@ -404,16 +407,16 @@ checkproc() {
killback() { killback() {
killproc "back-$1-" killproc "back-$1-"
rm -f "$TMPDIR/${copname}$1-back.cmd" rm -f "${TMPDIR:-.}/${copname}$1-back.cmd"
} }
killproc() { killproc() {
local fifo="$1${copname}" local fifo="$1${copname}"
(tmux kill-session -t "${fifo}"; echo imprettydarnsuredatdisisdaendofdacmd>$TMPDIR/${fifo}; tmux kill-session -t sendprocess_${fifo}; rm -f -r $TMPDIR/${fifo})2>/dev/null (tmux kill-session -t "${fifo}"; echo imprettydarnsuredatdisisdaendofdacmd>"${TMPDIR:-.}/${fifo}"; tmux kill-session -t "sendprocess_${fifo}"; rm -f -r "${TMPDIR:-.}/${fifo}")2>/dev/null
} }
inproc() { inproc() {
tmux send-keys -t $copname "$MESSAGE ${URLS[*]} tmux send-keys -t "$copname" "${MESSAGE[0]} ${URLS[*]}
" "
} }
process_updates() { process_updates() {
@ -427,7 +430,7 @@ process_updates() {
done done
} }
process_client() { process_client() {
local TMP="$TMPDIR/$RANDOM$RANDOM-MESSAGE" local TMP="${TMPDIR:-.}/$RANDOM$RANDOM-MESSAGE"
echo "$UPDATE" >"$TMP" echo "$UPDATE" >"$TMP"
# Message # Message
MESSAGE[0]="$(echo -e "$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","text"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")" | sed 's#\\/#/#g')" MESSAGE[0]="$(echo -e "$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","text"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")" | sed 's#\\/#/#g')"
@ -492,7 +495,7 @@ process_client() {
# Location # Location
LOCATION[LONGITUDE]="$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","location","longitude"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")" LOCATION[LONGITUDE]="$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","location","longitude"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")"
LOCATION[LATITUDE]="$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","location","latitude"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")" LOCATION[LATITUDE]="$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","location","latitude"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")"
NAME="$(echo ${URLS[*]} | sed 's/.*\///g')" NAME="$(echo "${URLS[*]}" | sed 's/.*\///g')"
rm "$TMP" rm "$TMP"
# Tmux # Tmux
@ -501,17 +504,17 @@ process_client() {
source commands.sh source commands.sh
tmpcount="COUNT${CHAT[ID]}" tmpcount="COUNT${CHAT[ID]}"
cat ${COUNT} | grep -q "$tmpcount" || echo "$tmpcount">>${COUNT} grep -q "$tmpcount" <"${COUNT}" >/dev/null 2>&1 || echo "$tmpcount">>${COUNT}
# To get user count execute bash bashbot.sh count # To get user count execute bash bashbot.sh count
} }
# source the script with source as param to use functions in other scripts # source the script with source as param to use functions in other scripts
while [ "$1" == "startbot" ]; do { while [ "$1" == "startbot" ]; do {
UPDATE="$(curl -s $UPD_URL$OFFSET | ./JSON.sh/JSON.sh)" UPDATE="$(curl -s "$UPD_URL$OFFSET" | ./JSON.sh/JSON.sh)"
# Offset # Offset
OFFSET="$(echo "$UPDATE" | egrep '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)" OFFSET="$(echo "$UPDATE" | grep '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)"
OFFSET=$((OFFSET+1)) OFFSET=$((OFFSET+1))
if [ "$OFFSET" != "1" ]; then if [ "$OFFSET" != "1" ]; then
@ -529,46 +532,45 @@ case "$1" in
"outproc") "outproc")
until [ "$line" = "imprettydarnsuredatdisisdaendofdacmd" ];do until [ "$line" = "imprettydarnsuredatdisisdaendofdacmd" ];do
line="" line=""
read -t 10 line read -r -t 10 line
[ "$line" != "" -a "$line" != "imprettydarnsuredatdisisdaendofdacmd" ] && send_message "$2" "$line" [ "$line" != "" ] && [ "$line" != "imprettydarnsuredatdisisdaendofdacmd" ] && send_message "$2" "$line"
done <$TMPDIR/$3 done <"${TMPDIR:-.}/$3"
rm -f -r $TMPDIR/$3 rm -f -r "${TMPDIR:-.}/$3"
;; ;;
"count") "count")
echo "A total of $(wc -l <"${COUNT}") users used me." echo "A total of $(wc -l <"${COUNT}") users used me."
exit exit
;; ;;
"broadcast") "broadcast")
USERS="$(wc -l <"${COUNT}")" NUMCOUNT="$(wc -l <"${COUNT}")"
echo "Sending the broadcast $* to $USERS users." echo "Sending the broadcast $* to $NUMCOUNT users."
[ "$USERS" -gt "300" ] && sleep="sleep 0.5" [ "$NUMCOUNT" -gt "300" ] && sleep="sleep 0.5"
shift shift
for f in "$(cat ${COUNT})";do send_message ${f//COUNT} "$*"; $sleep;done while read -r f; do send_message "${f//COUNT}" "$*"; $sleep; done <"${COUNT}"
;; ;;
"start") "start")
$CLEAR $CLEAR
tmux kill-session -t $ME&>/dev/null tmux kill-session -t "$ME" &>/dev/null
tmux new-session -d -s $ME "bash $SCRIPT startbot $ME" && echo -e "${GREEN}Bot started successfully.${NC}" tmux new-session -d -s "$ME" "bash $SCRIPT startbot" && echo -e "${GREEN}Bot started successfully.${NC}"
echo "Tmux session name $ME" || echo -e "${RED}An error occurred while starting the bot. ${NC}" echo "Tmux session name $ME" || echo -e "${RED}An error occurred while starting the bot. ${NC}"
send_markdown_message "${CHAT[ID]}" "*Bot started*" send_markdown_message "${CHAT[ID]}" "*Bot started*"
;; ;;
"init") # adjust users and permissions "init") # adjust users and permissions
MYUSER="$USER" [[ "$(id -u)" -eq "0" ]] && RUNUSER="nobody"
[[ "$(id -u)" -eq "0" ]] && MYUSER="nobody" echo -n "Enter User to run basbot [$RUNUSER]: "
echo -n "Enter User to run basbot [$MYUSER]: " read -r TOUSER
read TOUSER [ "$TOUSER" = "" ] && TOUSER="$RUNUSER"
[ "$TOUSER" = "" ] && TOUSER="$MYUSER" if ! compgen -u "$TOUSER" >/dev/null 2>&1; then
if ! compgen -u "$TOUSER" 2>&1 >/dev/null; then
echo -e "${RED}User \"$TOUSER\" not found!${NC}" echo -e "${RED}User \"$TOUSER\" not found!${NC}"
exit 3 exit 3
else else
echo "Adjusting user in bashbot.rc ..." echo "Adjusting user in bashbot.rc ..."
sed -i '/^[# ]*runas=/ s/runas=.*$/runas="'$TOUSER'"/' bashbot.rc sed -i '/^[# ]*runas=/ s/runas=.*$/runas="'$TOUSER'"/' bashbot.rc
echo "Adjusting Owner and Permissions ..." echo "Adjusting Owner and Permissions ..."
chown -R "$TOUSER" . * chown -R "$TOUSER" . ./*
chmod 711 . chmod 711 .
chmod -R a-w * chmod -R a-w ./*
chmod -R u+w "$COUNT" "$TMPDIR" *.log 2>/dev/null chmod -R u+w "$COUNT" "$TMPDIR" ./*.log 2>/dev/null
chmod -R o-r,o-w "$COUNT" "$TMPDIR" token 2>/dev/null chmod -R o-r,o-w "$COUNT" "$TMPDIR" token 2>/dev/null
ls -la ls -la
exit exit
@ -577,8 +579,8 @@ case "$1" in
"background" | "resumeback") "background" | "resumeback")
$CLEAR $CLEAR
echo -e "${GREEN}Restart background processes ...${NC}" echo -e "${GREEN}Restart background processes ...${NC}"
for FILE in "${TMPDIR}/"*-back.cmd; do for FILE in "${TMPDIR:-.}/"*-back.cmd; do
if [ "$FILE" == "${TMPDIR}/*-back.cmd" ]; then if [ "$FILE" == "${TMPDIR:-.}/*-back.cmd" ]; then
echo -e "${RED}No background processes to start.${NC}"; break echo -e "${RED}No background processes to start.${NC}"; break
else else
RESTART="$(cat "$FILE")" RESTART="$(cat "$FILE")"
@ -588,10 +590,10 @@ case "$1" in
JOB="${JOB%:*}" JOB="${JOB%:*}"
fifo="back-${JOB}-${ME}_${CHAT[ID]}" # compose fifo from jobname, $ME (botname) and CHAT[ID] fifo="back-${JOB}-${ME}_${CHAT[ID]}" # compose fifo from jobname, $ME (botname) and CHAT[ID]
echo "restartbackground ${PROG} ${fifo}" echo "restartbackground ${PROG} ${fifo}"
( tmux kill-session -t "${fifo}"; tmux kill-session -t sendprocess_${fifo}; rm -f -r $TMPDIR/${fifo}) 2>/dev/null ( tmux kill-session -t "${fifo}"; tmux kill-session -t "sendprocess_${fifo}"; rm -f -r "${TMPDIR:-.}/${fifo}") 2>/dev/null
mkfifo "$TMPDIR/${fifo}" mkfifo "${TMPDIR:-.}/${fifo}"
TMUX= tmux new-session -d -s "${fifo}" "${PROG} &>$TMPDIR/${fifo}; echo imprettydarnsuredatdisisdaendofdacmd>$TMPDIR/${fifo}" tmux new-session -d -s "${fifo}" "${PROG} &>${TMPDIR:-.}/${fifo}; echo imprettydarnsuredatdisisdaendofdacmd>${TMPDIR:-.}/${fifo}"
TMUX= tmux new-session -d -s sendprocess_${fifo} "bash $SCRIPT outproc ${CHAT[ID]} ${fifo}" tmux new-session -d -s "sendprocess_${fifo}" "bash $SCRIPT outproc ${CHAT[ID]} ${fifo}"
fi fi
done done
;; ;;
@ -604,8 +606,8 @@ case "$1" in
"killback" | "suspendback") "killback" | "suspendback")
$CLEAR $CLEAR
echo -e "${GREEN}Stopping background processes ...${NC}" echo -e "${GREEN}Stopping background processes ...${NC}"
for FILE in "${TMPDIR}/"*-back.cmd; do for FILE in "${TMPDIR:-.}/"*-back.cmd; do
if [ "$FILE" == "${TMPDIR}/*-back.cmd" ]; then if [ "$FILE" == "${TMPDIR:-.}/*-back.cmd" ]; then
echo -e "${RED}No background processes.${NC}"; break echo -e "${RED}No background processes.${NC}"; break
else else
REMOVE="$(cat "$FILE")" REMOVE="$(cat "$FILE")"
@ -613,13 +615,13 @@ case "$1" in
fifo="back-${JOB%:*}-${ME}_${REMOVE%%:*}" fifo="back-${JOB%:*}-${ME}_${REMOVE%%:*}"
echo "killbackground ${fifo}" echo "killbackground ${fifo}"
[ "$1" == "killback" ] && rm -f "$FILE" # remove job [ "$1" == "killback" ] && rm -f "$FILE" # remove job
( tmux kill-session -t "${fifo}"; tmux kill-session -t sendprocess_${fifo}; rm -f -r $TMPDIR/${fifo}) 2>/dev/null ( tmux kill-session -t "${fifo}"; tmux kill-session -t "sendprocess_${fifo}"; rm -f -r "${TMPDIR:-.}/${fifo}") 2>/dev/null
fi fi
done done
;; ;;
"help") "help")
$CLEAR $CLEAR
less "README.md" less "README.txt"
exit exit
;; ;;
"attach") "attach")
@ -638,7 +640,7 @@ esac
# warn if root # warn if root
if [[ "$(id -u)" -eq "0" ]] ; then if [[ "$(id -u)" -eq "0" ]] ; then
echo -e "\n${ORANGE}WARNING: ${SCRIPT} was started as ROOT (UID 0)!${NC}" echo -e "\\n${ORANGE}WARNING: ${SCRIPT} was started as ROOT (UID 0)!${NC}"
echo -e "${ORANGE}You are at HIGH RISK when processing user input with root privilegs!${NC}" echo -e "${ORANGE}You are at HIGH RISK when processing user input with root privilegs!${NC}"
fi fi

View File

@ -4,7 +4,10 @@
# This file is public domain in the USA and all free countries. # This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
# #
#### $$VERSION$$ v0.5-0-gfd81668 #### $$VERSION$$ v0.51-0-g4ddd122
#
# shellcheck disable=SC2154
# shellcheck disable=SC2034
# adjust your language setting here, e.g.when run from other user or cron. # adjust your language setting here, e.g.when run from other user or cron.
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
@ -26,11 +29,11 @@ if [ "$1" = "source" ];then
else else
if ! tmux ls | grep -v send | grep -q "$copname"; then if ! tmux ls | grep -v send | grep -q "$copname"; then
[ ! -z "${URLS[*]}" ] && { [ ! -z "${URLS[*]}" ] && {
curl -s ${URLS[*]} -o $NAME curl -s "${URLS[*]}" -o "$NAME"
send_file "${CHAT[ID]}" "$NAME" "$CAPTION" send_file "${CHAT[ID]}" "$NAME" "$CAPTION"
rm -f "$NAME" rm -f "$NAME"
} }
[ ! -z ${LOCATION[*]} ] && send_location "${CHAT[ID]}" "${LOCATION[LATITUDE]}" "${LOCATION[LONGITUDE]}" [ ! -z "${LOCATION[*]}" ] && send_location "${CHAT[ID]}" "${LOCATION[LATITUDE]}" "${LOCATION[LONGITUDE]}"
# Inline # Inline
if [ $INLINE == 1 ]; then if [ $INLINE == 1 ]; then
@ -61,7 +64,7 @@ else
case "$MESSAGE" in case "$MESSAGE" in
'/question') '/question')
checkproc checkproc
if [ $res -gt 0 ] ; then if [ "$res" -gt 0 ] ; then
startproc "./question" startproc "./question"
else else
send_normal_message "${CHAT[ID]}" "$MESSAGE already running ..." send_normal_message "${CHAT[ID]}" "$MESSAGE already running ..."
@ -70,7 +73,7 @@ else
'/run-notify') '/run-notify')
myback="notify"; checkback "$myback" myback="notify"; checkback "$myback"
if [ $res -gt 0 ] ; then if [ "$res" -gt 0 ] ; then
background "./notify 60" "$myback" # notify every 60 seconds background "./notify 60" "$myback" # notify every 60 seconds
else else
send_normal_message "${CHAT[ID]}" "Background command $myback already running ..." send_normal_message "${CHAT[ID]}" "Background command $myback already running ..."
@ -78,7 +81,7 @@ else
;; ;;
'/stop-notify') '/stop-notify')
myback="notify"; checkback "$myback" myback="notify"; checkback "$myback"
if [ $res -eq 0 ] ; then if [ "$res" -eq 0 ] ; then
killback "$myback" killback "$myback"
send_normal_message "${CHAT[ID]}" "Background command $myback canceled." send_normal_message "${CHAT[ID]}" "Background command $myback canceled."
else else
@ -120,10 +123,10 @@ Get the code in my [GitHub](http://github.com/topkecleon/telegram-bot-bash)
'/cancel') '/cancel')
checkprog checkprog
if [ $res -eq 0 ] ; then killproc && send_message "${CHAT[ID]}" "Command canceled.";else send_message "${CHAT[ID]}" "No command is currently running.";fi if [ "$res" -eq 0 ] ; then killproc && send_message "${CHAT[ID]}" "Command canceled.";else send_message "${CHAT[ID]}" "No command is currently running.";fi
;; ;;
*) *)
if tmux ls | grep -v send | grep -q $copname;then inproc; else send_message "${CHAT[ID]}" "$MESSAGE" "safe";fi if tmux ls | grep -v send | grep -q "$copname";then inproc; else send_message "${CHAT[ID]}" "$MESSAGE" "safe";fi
;; ;;
esac esac
fi fi

View File

@ -70,5 +70,5 @@ git clone --recursive https://github.com/topkecleon/telegram-bot-bash
``` ```
3. Change to directory ```telegram-bot.bash```, run ```./bashbot.sh init``` and follow the instructions. At this stage you are asked for your Bots token given by botfather. 3. Change to directory ```telegram-bot.bash```, run ```./bashbot.sh init``` and follow the instructions. At this stage you are asked for your Bots token given by botfather.
#### $$VERSION$$ v0.50-13-g4d5d386 #### $$VERSION$$ v0.51-0-g4ddd122

View File

@ -147,6 +147,6 @@ Allowed values: typing for text messages, upload_photo for photos, record_video
send_action "${CHAT[ID]}" "action" send_action "${CHAT[ID]}" "action"
``` ```
#### $$VERSION$$ v0.50-13-g4d5d386 #### $$VERSION$$ v0.51-0-g4ddd122

View File

@ -97,5 +97,5 @@ To send stickers through an *inline query*:
answer_inline_query "$iQUERY_ID" "cached_sticker" "identifier for the sticker" answer_inline_query "$iQUERY_ID" "cached_sticker" "identifier for the sticker"
``` ```
#### $$VERSION$$ v0.50-13-g4d5d386 #### $$VERSION$$ v0.51-0-g4ddd122

View File

@ -101,5 +101,6 @@ An example crontab is provided in ```bashbot.cron```.
- If you are running bashbot with your user-ID, copy the examples lines to your crontab and remove username ```nobody```. - If you are running bashbot with your user-ID, copy the examples lines to your crontab and remove username ```nobody```.
- if you run bashbot as an other user or a system service edit ```bashbot.cron``` to fit your needs and replace username```nobody``` with the username you want to run bashbot. copy the modified file to ```/etc/cron.d/bashbot``` - if you run bashbot as an other user or a system service edit ```bashbot.cron``` to fit your needs and replace username```nobody``` with the username you want to run bashbot. copy the modified file to ```/etc/cron.d/bashbot```
#### $$VERSION$$ v0.50-13-g4d5d386
#### $$VERSION$$ v0.51-0-g4ddd122

2
notify
View File

@ -2,7 +2,7 @@
# This file is public domain in the USA and all free countries. # This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#### $$VERSION$$ v0.5-0-gfd81668 #### $$VERSION$$ v0.51-0-g4ddd122
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment

View File

@ -3,7 +3,7 @@
# This file is public domain in the USA and all free countries. # This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying) # Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#### $$VERSION$$ v0.5-0-gfd81668 #### $$VERSION$$ v0.51-0-g4ddd122
# adjust your language setting here # adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment # https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
@ -16,11 +16,11 @@ unset IFS
echo "Why hello there. echo "Why hello there.
Would you like some tea (y/n)?" Would you like some tea (y/n)?"
read answer read -r answer
[[ $answer =~ ^([yY][eE][sS]|[yY])$ ]] && echo "OK then, here you go: http://www.rivertea.com/blog/wp-content/uploads/2013/12/Green-Tea.jpg" || echo "OK then." [[ $answer =~ ^([yY][eE][sS]|[yY])$ ]] && echo "OK then, here you go: http://www.rivertea.com/blog/wp-content/uploads/2013/12/Green-Tea.jpg" || echo "OK then."
until [ "$SUCCESS" = "y" ] ;do until [ "$SUCCESS" = "y" ] ;do
echo 'Do you like Music? mykeyboardstartshere "Yass!" "No"' echo 'Do you like Music? mykeyboardstartshere "Yass!" "No"'
read answer read -r answer
case $answer in case $answer in
'Yass!') echo "Goody! mykeyboardendshere";SUCCESS=y;; 'Yass!') echo "Goody! mykeyboardendshere";SUCCESS=y;;
'No') echo "Well that's weird. mykeyboardendshere";SUCCESS=y;; 'No') echo "Well that's weird. mykeyboardendshere";SUCCESS=y;;

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
#### $$VERSION$$ v0.50-13-g4d5d386 #### $$VERSION$$ v0.51-0-g4ddd122
# shellcheck disable=SC2016 # shellcheck disable=SC2016
# #
# Easy Versioning in git: # Easy Versioning in git: