mirror of
https://github.com/octoleo/telegram-bot-bash.git
synced 2024-12-26 04:17:46 +00:00
commit
d15b4f5070
20
README.html
20
README.html
@ -223,8 +223,8 @@ Written by Drew (@topkecleon) and Kay M (@gnadelwartz).
|
||||
<p>Released to the public domain wherever applicable. Elsewhere, consider it released under the <a href="http://www.wtfpl.net/txt/copying/">WTFPLv2</a>.</p>
|
||||
<p>Linted by <a href="https://github.com/koalaman/shellcheck">#ShellCheck</a></p>
|
||||
<h2>Prerequisites</h2>
|
||||
<p>Uses <a href="http://github.com/dominictarr/JSON.sh">JSON.sh</a> and the magic of sed.</p>
|
||||
<p>Bashbot is written in bash. It depends on commands typically available in a Linux/Unix Environment. For more concrete information on the common commands provided by recent versions of <a href="https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands">coreutils</a>, <a href="https://en.wikipedia.org/wiki/BusyBox#Commands">busybox</a> or <a href="https://landley.net/toybox/help.html">toybox</a>, see <a href="doc/7_develop.md#common-commands">Developer Notes</a>.</p>
|
||||
<p>Uses <a href="http://github.com/dominictarr/JSON.sh">JSON.sh</a>/<a href="https://github.com/step-/JSON.awk">JSON.awk</a> and the magic of sed.</p>
|
||||
<p>Bashbot is written in bash. It depends on commands typically available in a Linux/Unix Environment. For more information on commands provided by recent versions of <a href="https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands">coreutils</a>, <a href="https://en.wikipedia.org/wiki/BusyBox#Commands">busybox</a> or <a href="https://landley.net/toybox/help.html">toybox</a>, see <a href="doc/7_develop.md#common-commands">Developer Notes</a>.</p>
|
||||
<p><strong>Note for MacOS and BSD Users:</strong> Bashbot will not run without installing additional software as it uses modern bash and (gnu) grep/sed features. See <a href="doc/0_install.md">Install Bashbot</a>.</p>
|
||||
<p><strong>Note for embedded systems:</strong> You need to install a "real" bash as the vanilla installation of busybox or toybox is not sufficient. See <a href="doc/0_install.md">Install Bashbot</a>.</p>
|
||||
<p>Bashbot <a href="https://github.com/topkecleon/telegram-bot-bash">Documentation</a> and <a href="https://github.com/topkecleon/telegram-bot-bash/releases">Downloads</a> are available on <a href="https://www.github.com">www.github.com</a>.</p>
|
||||
@ -284,7 +284,8 @@ Written by Drew (@topkecleon) and Kay M (@gnadelwartz).
|
||||
<li>Setup your environment</li>
|
||||
<li>Bashbot test suite</li>
|
||||
</ul></li>
|
||||
<li><a href="examples/README.md">Examples Directory</a></li>
|
||||
<li><a href="examples">Examples Directory</a></li>
|
||||
<li><a href="examples/webhook">Webhook Example</a></li>
|
||||
</ul>
|
||||
<h3>Your very first bashbot in a nutshell</h3>
|
||||
<p>To install and run bashbot you need access to a Linux/Unix command line with bash, a <a href="https://telegram.org">Telegram client</a> and a mobile phone <a href="https://telegramguide.com/create-a-telegram-account/">with a Telegram account</a>.</p>
|
||||
@ -340,7 +341,7 @@ It features background tasks and interactive chats, and can serve as an interfac
|
||||
<p>Running a Telegram Bot means it is connected to the public and you never know what's send to your Bot.</p>
|
||||
<p>Bash scripts in general are not designed to be bulletproof, so consider this Bot as a proof of concept. Bash programmers often struggle with 'quoting hell' and globbing, see <a href="https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells">Implications of wrong quoting</a>.</p>
|
||||
<p>Whenever you are processing input from untrusted sources (messages, files, network) you must be as careful as possible (e.g. set IFS appropriately, disable globbing with <code>set -f</code> and quote everything). In addition remove unused scripts and examples from your Bot (e.g. everything in <code>example/</code>) and disable/remove all unused bot commands.</p>
|
||||
<p>It's important to escape or remove <code>$</code> in input from user, files or network (<em>as bashbot does</em>). One of the powerful features of Unix shells is variable and command substitution using <code>${}</code> and<code>$()</code> can lead to remote code execution (RCE) or remote information disclosure (RID) bugs if unescaped <code>$</code> is included in untrusted input (e.g. <code>$$</code> or <code>$(rm -rf /*)</code>).</p>
|
||||
<p>It's important to escape or remove <code>$</code> in input from user, files or network (<em>as bashbot does</em>). One of the powerful features of Unix shells is variable and command substitution using <code>${}</code> and <code>$()</code> can lead to remote code execution (RCE) or remote information disclosure (RID) bugs if unescaped <code>$</code> is included in untrusted input (e.g. <code>$$</code> or <code>$(rm -rf /*)</code>).</p>
|
||||
<p>A powerful tool to improve your scripts is <code>shellcheck</code>. You can <a href="https://www.shellcheck.net/">use it online</a> or <a href="https://github.com/koalaman/shellcheck#installing">install shellcheck locally</a>. Shellcheck is used extensively in bashbot development to ensure a high code quality (e.g. it's not allowed to push changes without passing all shellcheck tests). In addition bashbot has a <a href="doc/7_develop.md">test suite</a> to check if important functionality is working as expected.</p>
|
||||
<h3>Use printf whenever possible</h3>
|
||||
<p>If you're writing a script that accepts external input (e.g. from the user as arguments or the file system), you shouldn't use echo to display it. <a href="https://unix.stackexchange.com/a/6581">Use printf whenever possible</a>.</p>
|
||||
@ -349,8 +350,9 @@ It features background tasks and interactive chats, and can serve as an interfac
|
||||
<p><strong>Never run your Bot as root, this is the most dangerous you can do!</strong> Usually the user 'nobody' has almost no rights on Linux/Unix systems. See <a href="doc/4_expert.md">Expert use</a> on how to run your Bot as an other user.</p>
|
||||
<h3>Secure your Bot installation</h3>
|
||||
<p><strong>Your Bot configuration must not be readable by other users.</strong> Everyone who can read your Bots token is able to act as your Bot and has access to all chats the Bot is in!</p>
|
||||
<p>Everyone with read access to your Bot files can extract your Bots data. Especially your Bot config in<code>config.jssh</code> must be protected against other users. No one except you should have write access to the Bot files. The Bot should be restricted to have write access to<code>count.jssh</code> and <code>data-bot-bash</code> only, all other files must be write protected.</p>
|
||||
<p>To set access rights for your bashbot installation to a reasonable default run<code>sudo ./bashbot.sh init</code> after every update or change to your installation directory.</p>
|
||||
<p>Everyone with read access to your Bot files can extract your Bots data. Especially your Bot config in <code>config.jssh</code> must be protected against other users. No one except you should have write access to the Bot files. The Bot should be restricted to have write access to <code>count.jssh</code>, <code>data-bot-bash/</code> and <code>logs/</code> only, all other files must be write protected.</p>
|
||||
<p>To set access rights for your bashbot installation to a reasonable default run <code>sudo ./bashbot.sh init</code> after every update or change to your installation directory.</p>
|
||||
<p><em>Note</em>: Keep old log files in a safe place or even better delete them, they are GDPR relevant and <a href="https://github.com/topkecleon/telegram-bot-bash/issues/174">may contain information</a> you don't want to be public.</p>
|
||||
<h2>FAQ</h2>
|
||||
<h3>Is this Bot insecure?</h3>
|
||||
<p>Bashbot is not more (in)secure than a Bot written in another language. We have done our best to make it as secure as possible. But YOU are responsible for the bot commands you wrote and you should know about the risks ...</p>
|
||||
@ -364,8 +366,8 @@ It features background tasks and interactive chats, and can serve as an interfac
|
||||
<li>no database, not event driven, not object oriented ...</li>
|
||||
</ul>
|
||||
<h3>Can I have the single bashbot.sh file back?</h3>
|
||||
<p>At the beginning bashbot was simply the file<code>bashbot.sh</code> that you could copy everywhere and run the bot. Now we have 'commands.sh', 'mycommands.sh', 'modules/*.sh' and much more.</p>
|
||||
<p>Hey no problem, if you are finished with your cool bot, run<code>dev/make-standalone.sh</code> to create a stripped down version of your bot containing only 'bashbot.sh' and 'commands.sh'! For more information see <a href="doc/7_develop.md">Create a stripped down version of your Bot</a>.</p>
|
||||
<p>At the beginning bashbot was simply the file <code>bashbot.sh</code> that you could copy everywhere and run the bot. Now we have 'commands.sh', 'mycommands.sh', 'modules/*.sh' and much more.</p>
|
||||
<p>Hey no problem, if you are finished with your cool bot, run <code>dev/make-standalone.sh</code> to create a stripped down version of your bot containing only 'bashbot.sh' and 'commands.sh'! For more information see <a href="doc/7_develop.md">Create a stripped down version of your Bot</a>.</p>
|
||||
<h3>Can I send messages from CLI and scripts?</h3>
|
||||
<p>Of course you can send messages from command line and scripts! Simply install bashbot as <a href="#Your-really-first-bashbot-in-a-nutshell">described here</a>, send the message '/start' to set yourself as botadmin and then stop the bot with <code>./bashbot.sh stop</code>.</p>
|
||||
<p>Bashbot provides some ready to use scripts for sending messages from command line in <code>bin/</code> dir, e.g. <code>send_message.sh</code>.</p>
|
||||
@ -390,6 +392,6 @@ It features background tasks and interactive chats, and can serve as an interfac
|
||||
<p>@Gnadelwartz</p>
|
||||
<h2>That's it all guys!</h2>
|
||||
<p>If you feel that there's something missing or if you found a bug, feel free to submit a pull request!</p>
|
||||
<h4>$$VERSION$$ v1.30-0-g3266427</h4>
|
||||
<h4>$$VERSION$$ v1.40-dev-34-g1440d56</h4>
|
||||
</body>
|
||||
</html>
|
||||
|
21
README.md
21
README.md
@ -11,10 +11,10 @@ Elsewhere, consider it released under the [WTFPLv2](http://www.wtfpl.net/txt/cop
|
||||
Linted by [#ShellCheck](https://github.com/koalaman/shellcheck)
|
||||
|
||||
## Prerequisites
|
||||
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh) and the magic of sed.
|
||||
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh)/[JSON.awk](https://github.com/step-/JSON.awk) and the magic of sed.
|
||||
|
||||
Bashbot is written in bash. It depends on commands typically available in a Linux/Unix Environment.
|
||||
For more concrete information on the common commands provided by recent versions of [coreutils](https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands), [busybox](https://en.wikipedia.org/wiki/BusyBox#Commands) or [toybox](https://landley.net/toybox/help.html), see [Developer Notes](doc/7_develop.md#common-commands).
|
||||
For more information on commands provided by recent versions of [coreutils](https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands), [busybox](https://en.wikipedia.org/wiki/BusyBox#Commands) or [toybox](https://landley.net/toybox/help.html), see [Developer Notes](doc/7_develop.md#common-commands).
|
||||
|
||||
**Note for MacOS and BSD Users:** Bashbot will not run without installing additional software as it uses modern bash and (gnu) grep/sed features. See [Install Bashbot](doc/0_install.md).
|
||||
|
||||
@ -63,7 +63,8 @@ Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and [Do
|
||||
* Modules, addons, events
|
||||
* Setup your environment
|
||||
* Bashbot test suite
|
||||
* [Examples Directory](examples/README.md)
|
||||
* [Examples Directory](examples)
|
||||
* [Webhook Example](examples/webhook)
|
||||
|
||||
### Your very first bashbot in a nutshell
|
||||
|
||||
@ -146,7 +147,7 @@ Whenever you are processing input from untrusted sources (messages, files, netwo
|
||||
from your Bot (e.g. everything in `example/`) and disable/remove all unused bot commands.
|
||||
|
||||
It's important to escape or remove `$` in input from user, files or network (_as bashbot does_).
|
||||
One of the powerful features of Unix shells is variable and command substitution using `${}` and`$()` can lead to remote code execution (RCE) or remote information disclosure (RID) bugs if unescaped `$` is included in untrusted input (e.g. `$$` or `$(rm -rf /*)`).
|
||||
One of the powerful features of Unix shells is variable and command substitution using `${}` and `$()` can lead to remote code execution (RCE) or remote information disclosure (RID) bugs if unescaped `$` is included in untrusted input (e.g. `$$` or `$(rm -rf /*)`).
|
||||
|
||||
A powerful tool to improve your scripts is `shellcheck`. You can [use it online](https://www.shellcheck.net/) or
|
||||
[install shellcheck locally](https://github.com/koalaman/shellcheck#installing). Shellcheck is used extensively in bashbot development
|
||||
@ -168,9 +169,11 @@ For the same reason every file your Bot can read is in danger of being disclosed
|
||||
### Secure your Bot installation
|
||||
**Your Bot configuration must not be readable by other users.** Everyone who can read your Bots token is able to act as your Bot and has access to all chats the Bot is in!
|
||||
|
||||
Everyone with read access to your Bot files can extract your Bots data. Especially your Bot config in`config.jssh` must be protected against other users. No one except you should have write access to the Bot files. The Bot should be restricted to have write access to`count.jssh` and `data-bot-bash` only, all other files must be write protected.
|
||||
Everyone with read access to your Bot files can extract your Bots data. Especially your Bot config in `config.jssh` must be protected against other users. No one except you should have write access to the Bot files. The Bot should be restricted to have write access to `count.jssh`, `data-bot-bash/` and `logs/` only, all other files must be write protected.
|
||||
|
||||
To set access rights for your bashbot installation to a reasonable default run`sudo ./bashbot.sh init` after every update or change to your installation directory.
|
||||
To set access rights for your bashbot installation to a reasonable default run `sudo ./bashbot.sh init` after every update or change to your installation directory.
|
||||
|
||||
*Note*: Keep old log files in a safe place or even better delete them, they are GDPR relevant and [may contain information](https://github.com/topkecleon/telegram-bot-bash/issues/174) you don't want to be public.
|
||||
|
||||
## FAQ
|
||||
|
||||
@ -188,9 +191,9 @@ Well, that's a damn good question... maybe because I'm a Unix admin from the sto
|
||||
- no database, not event driven, not object oriented ...
|
||||
|
||||
### Can I have the single bashbot.sh file back?
|
||||
At the beginning bashbot was simply the file`bashbot.sh` that you could copy everywhere and run the bot. Now we have 'commands.sh', 'mycommands.sh', 'modules/*.sh' and much more.
|
||||
At the beginning bashbot was simply the file `bashbot.sh` that you could copy everywhere and run the bot. Now we have 'commands.sh', 'mycommands.sh', 'modules/*.sh' and much more.
|
||||
|
||||
Hey no problem, if you are finished with your cool bot, run`dev/make-standalone.sh` to create a stripped down version of your bot containing only
|
||||
Hey no problem, if you are finished with your cool bot, run `dev/make-standalone.sh` to create a stripped down version of your bot containing only
|
||||
'bashbot.sh' and 'commands.sh'! For more information see [Create a stripped down version of your Bot](doc/7_develop.md).
|
||||
|
||||
### Can I send messages from CLI and scripts?
|
||||
@ -238,4 +241,4 @@ See `mycommnds.sh.dist` for an example.
|
||||
|
||||
If you feel that there's something missing or if you found a bug, feel free to submit a pull request!
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
49
README.txt
49
README.txt
@ -39,18 +39,21 @@ Linted by #ShellCheck
|
||||
|
||||
Prerequisites
|
||||
|
||||
Uses JSON.sh [http://github.com/dominictarr/JSON.sh] and the magic of sed.
|
||||
Uses JSON.sh [http://github.com/dominictarr/JSON.sh]/JSON.awk [https://github.com/step-/
|
||||
JSON.awk] and the magic of sed.
|
||||
Bashbot is written in bash. It depends on commands typically available in a Linux/Unix
|
||||
Environment. For more concrete information on the common commands provided by recent
|
||||
versions of coreutils [https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands],
|
||||
busybox or toybox, see Developer_Notes.
|
||||
Environment. For more information on commands provided by recent versions of coreutils
|
||||
[https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands], busybox [https://
|
||||
en.wikipedia.org/wiki/BusyBox#Commands] or toybox [https://landley.net/toybox/help.html],
|
||||
see Developer Notes [doc/7_develop.md#common-commands].
|
||||
Note for MacOS and BSD Users: Bashbot will not run without installing additional software
|
||||
as it uses modern bash and (gnu) grep/sed features. See Install Bashbot [doc/
|
||||
0_install.md].
|
||||
Note for embedded systems: You need to install a "real" bash as the vanilla installation
|
||||
of busybox or toybox is not sufficient. See Install Bashbot [doc/0_install.md].
|
||||
Bashbot Documentation [https://github.com/topkecleon/telegram-bot-bash] and Downloads are
|
||||
available on www.github.com.
|
||||
Bashbot Documentation [https://github.com/topkecleon/telegram-bot-bash] and Downloads
|
||||
[https://github.com/topkecleon/telegram-bot-bash/releases] are available on www.github.com
|
||||
[https://www.github.com].
|
||||
|
||||
Documentation
|
||||
|
||||
@ -109,13 +112,15 @@ Documentation
|
||||
o Setup your environment
|
||||
o Bashbot test suite
|
||||
|
||||
* Examples Directory [examples/README.md]
|
||||
* Examples Directory [examples]
|
||||
* Webhook Example [examples/webhook]
|
||||
|
||||
|
||||
Your very first bashbot in a nutshell
|
||||
|
||||
To install and run bashbot you need access to a Linux/Unix command line with bash, a
|
||||
Telegram client [https://telegram.org] and a mobile phone with_a_Telegram_account.
|
||||
Telegram client [https://telegram.org] and a mobile phone with a Telegram account [https:/
|
||||
/telegramguide.com/create-a-telegram-account/].
|
||||
First you need to create a new Telegram Bot token [doc/1_firstbot.md] for your bot and
|
||||
write it down.
|
||||
Now open a Linux/Unix terminal with bash, create a new directory, change to it and install
|
||||
@ -197,13 +202,14 @@ f and quote everything). In addition remove unused scripts and examples from you
|
||||
(e.g. everything in example/) and disable/remove all unused bot commands.
|
||||
It's important to escape or remove $ in input from user, files or network (as bashbot
|
||||
does). One of the powerful features of Unix shells is variable and command substitution
|
||||
using ${} and$() can lead to remote code execution (RCE) or remote information disclosure
|
||||
using ${} and $() can lead to remote code execution (RCE) or remote information disclosure
|
||||
(RID) bugs if unescaped $ is included in untrusted input (e.g. $$ or $(rm -rf /*)).
|
||||
A powerful tool to improve your scripts is shellcheck. You can use it online [https://
|
||||
www.shellcheck.net/] or install_shellcheck_locally. Shellcheck is used extensively in
|
||||
bashbot development to ensure a high code quality (e.g. it's not allowed to push changes
|
||||
without passing all shellcheck tests). In addition bashbot has a test_suite to check if
|
||||
important functionality is working as expected.
|
||||
www.shellcheck.net/] or install shellcheck locally [https://github.com/koalaman/
|
||||
shellcheck#installing]. Shellcheck is used extensively in bashbot development to ensure a
|
||||
high code quality (e.g. it's not allowed to push changes without passing all shellcheck
|
||||
tests). In addition bashbot has a test suite [doc/7_develop.md] to check if important
|
||||
functionality is working as expected.
|
||||
|
||||
Use printf whenever possible
|
||||
|
||||
@ -226,11 +232,14 @@ Secure your Bot installation
|
||||
Your Bot configuration must not be readable by other users. Everyone who can read your
|
||||
Bots token is able to act as your Bot and has access to all chats the Bot is in!
|
||||
Everyone with read access to your Bot files can extract your Bots data. Especially your
|
||||
Bot config inconfig.jssh must be protected against other users. No one except you should
|
||||
have write access to the Bot files. The Bot should be restricted to have write access
|
||||
tocount.jssh and data-bot-bash only, all other files must be write protected.
|
||||
To set access rights for your bashbot installation to a reasonable default runsudo ./
|
||||
Bot config in config.jssh must be protected against other users. No one except you should
|
||||
have write access to the Bot files. The Bot should be restricted to have write access to
|
||||
count.jssh, data-bot-bash/ and logs/ only, all other files must be write protected.
|
||||
To set access rights for your bashbot installation to a reasonable default run sudo ./
|
||||
bashbot.sh init after every update or change to your installation directory.
|
||||
Note: Keep old log files in a safe place or even better delete them, they are GDPR
|
||||
relevant and may contain information [https://github.com/topkecleon/telegram-bot-bash/
|
||||
issues/174] you don't want to be public.
|
||||
|
||||
FAQ
|
||||
|
||||
@ -258,9 +267,9 @@ Nevertheless there are more reasons from my side:
|
||||
|
||||
Can I have the single bashbot.sh file back?
|
||||
|
||||
At the beginning bashbot was simply the filebashbot.sh that you could copy everywhere and
|
||||
At the beginning bashbot was simply the file bashbot.sh that you could copy everywhere and
|
||||
run the bot. Now we have 'commands.sh', 'mycommands.sh', 'modules/*.sh' and much more.
|
||||
Hey no problem, if you are finished with your cool bot, rundev/make-standalone.sh to
|
||||
Hey no problem, if you are finished with your cool bot, run dev/make-standalone.sh to
|
||||
create a stripped down version of your bot containing only 'bashbot.sh' and 'commands.sh'!
|
||||
For more information see Create a stripped down version of your Bot [doc/7_develop.md].
|
||||
|
||||
@ -309,5 +318,5 @@ That's it all guys!
|
||||
If you feel that there's something missing or if you found a bug, feel free to submit a
|
||||
pull request!
|
||||
|
||||
$$VERSION$$ v1.30-0-g3266427
|
||||
$$VERSION$$ v1.40-dev-34-g1440d56
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
# this addon counts how many files, e.g. stickers, are sent to
|
||||
# a chat and takes actions if threshold is reached
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
# used events:
|
||||
#
|
||||
|
@ -4,7 +4,7 @@
|
||||
# Addons can register to bashbot events at startup
|
||||
# by providing their name and a callback per event
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#
|
||||
# If an event occurs each registered event function is called.
|
||||
#
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# tested on: ubuntu, opensuse, debian
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
# shellcheck disable=SC2009
|
||||
# shellcheck disable=SC2181
|
||||
|
||||
|
610
bashbot.sh
610
bashbot.sh
@ -30,16 +30,9 @@ BOTCOMMANDS="-h help init start stop status suspendback resumeback killb
|
||||
# 8 - curl/wget missing
|
||||
# 10 - not bash!
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
##################################################################
|
||||
|
||||
# emmbeded system may claim bash but it is not
|
||||
# check for bash like ARRAY handlung
|
||||
if ! (unset a; set -A a a; eval "a=(a b)"; eval '[ -n "${a[1]}" ]'; ) > /dev/null 2>&1; then
|
||||
printf "Error: Current shell does not support ARRAY's, may be busybox ash shell. pls install a real bash!\n"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# are we running in a terminal?
|
||||
NN="\n"
|
||||
if [ -t 1 ] && [ -n "${TERM}" ]; then
|
||||
@ -51,6 +44,7 @@ if [ -t 1 ] && [ -n "${TERM}" ]; then
|
||||
NC='\e[0m'
|
||||
NN="${NC}\n"
|
||||
fi
|
||||
declare -r INTERACTIVE RED GREEN ORANGE GREY NC NN
|
||||
|
||||
# telegram uses utf-8 characters, check if we have an utf-8 charset
|
||||
if [ "${LANG}" = "${LANG%[Uu][Tt][Ff]*}" ]; then
|
||||
@ -89,7 +83,8 @@ _is_function() {
|
||||
# if $2 is not given or is not a positive number zero is assumed
|
||||
_round_float() {
|
||||
local digit="$2"; [[ "$2" =~ ^[${o9o9o9}]+$ ]] || digit="0"
|
||||
{ LC_ALL=C.utf-8 printf "%.${digit}f" "$1"; } 2>/dev/null
|
||||
: "$(LC_ALL=C printf "%.${digit}f" "$1" 2>/dev/null)"
|
||||
printf "%s" "${_//,/.}" # make more LANG independent
|
||||
}
|
||||
# date is external, printf is much faster
|
||||
_date(){
|
||||
@ -104,6 +99,12 @@ getConfigKey() {
|
||||
[[ "$1" =~ ^[-${azAZo9},._]+$ ]] || return 3
|
||||
[ -r "${BOTCONFIG}.jssh" ] && sed -n 's/\["'"$1"'"\]\t*"\(.*\)"/\1/p' "${BOTCONFIG}.jssh" | tail -n 1
|
||||
}
|
||||
# escape / remove text characters for json strings, eg. " -> \"
|
||||
# $1 string
|
||||
# output escaped string
|
||||
JsonEscape(){
|
||||
sed 's/\([-"`´,§$%&/(){}#@!?*.\t]\)/\\\1/g' <<< "$1"
|
||||
}
|
||||
# check if $1 seems a valid token
|
||||
# return true if token seems to be valid
|
||||
check_token(){
|
||||
@ -172,9 +173,21 @@ RUNDIR="$(dirname "$0")"
|
||||
|
||||
MODULEDIR="${SCRIPTDIR}/modules"
|
||||
|
||||
# adjust locations based on source and real name
|
||||
[[ "${SCRIPT}" != "${REALME}" || "$1" == "source" ]] && SOURCE="yes"
|
||||
# adjust stuff for source, use return from source without source
|
||||
alias exit_source='exit'
|
||||
if [[ "${SCRIPT}" != "${REALME}" || "$1" == "source" ]]; then
|
||||
SOURCE="yes"
|
||||
[ -z "$1" ] && alias exit_source='printf "Exit from source ...\n";return'
|
||||
fi
|
||||
|
||||
# emmbeded system may claim bash but it is not
|
||||
# check for bash like ARRAY handlung
|
||||
if ! (unset a; set -A a a; eval "a=(a b)"; eval '[ -n "${a[1]}" ]'; ) > /dev/null 2>&1; then
|
||||
printf "Error: Current shell does not support ARRAY's, may be busybox ash shell. pls install a real bash!\n"
|
||||
exit_source 10
|
||||
fi
|
||||
|
||||
# adjust path variables
|
||||
if [ -n "${BASHBOT_HOME}" ]; then
|
||||
SCRIPTDIR="${BASHBOT_HOME}"
|
||||
else
|
||||
@ -184,7 +197,7 @@ fi
|
||||
[ -z "${BASHBOT_VAR}" ] && BASHBOT_VAR="${BASHBOT_HOME}"
|
||||
|
||||
ADDONDIR="${BASHBOT_ETC:-.}/addons"
|
||||
RUNUSER="${USER}" # USER is overwritten by bashbot array :-(, save original
|
||||
RUNUSER="${USER}" # save original USER
|
||||
|
||||
# provide help
|
||||
case "$1" in
|
||||
@ -207,16 +220,18 @@ esac
|
||||
# OK, ENVIRONMENT is set up, let's do some additional tests
|
||||
if [[ -z "${SOURCE}" && -z "${BASHBOT_HOME}" ]] && ! cd "${RUNDIR}" ; then
|
||||
printf "${RED}ERROR: Can't change to ${RUNDIR} ...${NN}"
|
||||
exit 1
|
||||
exit_source 1
|
||||
fi
|
||||
RUNDIR="."
|
||||
[ ! -w "." ] && printf "${ORANGE}WARNING: ${RUNDIR} is not writeable!${NN}"
|
||||
|
||||
# check if JSON.sh is available
|
||||
JSONSHFILE="${BASHBOT_JSONSH:-${SCRIPTDIR}/JSON.sh/JSON.sh}"
|
||||
[ ! -x "${JSONSHFILE}" ] &&\
|
||||
printf "${RED}ERROR:${NC} ${JSONSHFILE} ${RED}does not exist, are we in dev environment?${NN}${GREY}%s${NN}\n"\
|
||||
"\$JSONSHFILE is set wrong or bashbot is not installed correctly, see doc/0_install.md" && exit 3
|
||||
if [ ! -x "${JSONSHFILE}" ]; then
|
||||
printf "${RED}ERROR:${NC} ${JSONSHFILE} ${RED}does not exist, are we in dev environment?${NN}${GREY}%s${NN}\n"\
|
||||
"\$JSONSHFILE is set wrong or bashbot is not installed correctly, see doc/0_install.md"
|
||||
exit_source 3
|
||||
fi
|
||||
|
||||
# file locations based on ENVIRONMENT
|
||||
BOTCONFIG="${BASHBOT_ETC:-.}/botconfig"
|
||||
@ -264,7 +279,7 @@ if [ -z "${BOTTOKEN}" ]; then
|
||||
# check data dir file
|
||||
if [ ! -w "${DATADIR}" ]; then
|
||||
printf "${RED}ERROR: ${DATADIR} does not exist or is not writeable!.${NN}"
|
||||
exit 2
|
||||
exit_source 2
|
||||
fi
|
||||
# setup count file
|
||||
if [ ! -f "${COUNTFILE}.jssh" ]; then
|
||||
@ -272,7 +287,7 @@ if [ -z "${BOTTOKEN}" ]; then
|
||||
elif [ ! -w "${COUNTFILE}.jssh" ]; then
|
||||
printf "${RED}ERROR: Can't write to ${COUNTFILE}!.${NN}"
|
||||
ls -l "${COUNTFILE}.jssh"
|
||||
exit 2
|
||||
exit_source 2
|
||||
fi
|
||||
# setup blocked file
|
||||
if [ ! -f "${BLOCKEDFILE}.jssh" ]; then
|
||||
@ -301,7 +316,7 @@ if [ -z "${BOTTOKEN}" ]; then
|
||||
BOTTOKEN="$(getConfigKey "bottoken")"
|
||||
else
|
||||
printf "\n${RED}Error: Can't recover from missing bot token! Remove ${BOTCONFIG}.jssh and run${NC} bashbot.sh init\n"
|
||||
exit 7
|
||||
exit_source 7
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@ -324,7 +339,7 @@ fi
|
||||
|
||||
##################
|
||||
# here we start with the real stuff
|
||||
BASHBOT_RETRY="" # retry by default
|
||||
BASHBOT_RETRY="" # retry by default
|
||||
|
||||
URL="${BASHBOT_URL:-https://api.telegram.org/bot}${BOTTOKEN}"
|
||||
ME_URL=${URL}'/getMe'
|
||||
@ -336,11 +351,18 @@ declare -rx SCRIPT SCRIPTDIR MODULEDIR RUNDIR ADDONDIR BOTACL DATADIR COUNTFILE
|
||||
declare -rx BOTTOKEN URL ME_URL
|
||||
|
||||
declare -ax CMD
|
||||
declare -Ax UPD BOTSENT USER MESSAGE URLS CONTACT LOCATION CHAT FORWARD REPLYTO VENUE iQUERY
|
||||
declare -Ax UPD BOTSENT USER MESSAGE URLS CONTACT LOCATION CHAT FORWARD REPLYTO VENUE iQUERY iBUTTON
|
||||
declare -Ax SERVICE NEWMEMBER LEFTMEMBER PINNED MIGRATE
|
||||
export res CAPTION ME
|
||||
|
||||
|
||||
###############
|
||||
# load modules
|
||||
for module in "${MODULEDIR:-.}"/*.sh ; do
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
if ! _is_function "$(basename "${module}")" && [ -r "${module}" ]; then source "${module}" "source"; fi
|
||||
done
|
||||
|
||||
##################
|
||||
# read commands file if we are not sourced
|
||||
COMMANDS="${BASHBOT_ETC:-.}/commands.sh"
|
||||
@ -350,14 +372,9 @@ if [ -r "${COMMANDS}" ]; then
|
||||
else
|
||||
[ -z "${SOURCE}" ] && printf "${RED}Warning: ${COMMANDS} does not exist or is not readable!.${NN}"
|
||||
fi
|
||||
debug_checks "start SOURCE=${SOURCE:-no}" "$@"
|
||||
# no debug checks on source
|
||||
[ -z "${SOURCE}" ] && debug_checks "start" "$@"
|
||||
|
||||
###############
|
||||
# load modules
|
||||
for module in "${MODULEDIR:-.}"/*.sh ; do
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
if ! _is_function "$(basename "${module}")" && [ -r "${module}" ]; then source "${module}" "source"; fi
|
||||
done
|
||||
|
||||
#####################
|
||||
# BASHBOT INTERNAL functions
|
||||
@ -368,7 +385,7 @@ sed '1ia' </dev/null 2>/dev/null || printf "${ORANGE}Warning: You may run on a B
|
||||
#jsonDB is now mandatory
|
||||
if ! _is_function jssh_newDB; then
|
||||
printf "${RED}ERROR: Mandatory module jsonDB is missing or not readable!${NN}"
|
||||
exit 6
|
||||
exit_source 6
|
||||
fi
|
||||
|
||||
# $1 URL, $2 filename in DATADIR
|
||||
@ -416,10 +433,11 @@ delete_message() {
|
||||
sendJson "$1" '"message_id": '"$2"'' "${DELETE_URL}"
|
||||
}
|
||||
|
||||
# get download url for file id, $1 file_id
|
||||
get_file() {
|
||||
[ -z "$1" ] && return
|
||||
sendJson "" '"file_id": "'"$1"'"' "${URL}/getFile"
|
||||
printf '%s\n' "${URL}"/"$(JsonGetString <<< "${res}" '"result","file_path"')"
|
||||
printf "%s\n" "${URL}/${UPD["result,file_path"]}"
|
||||
}
|
||||
|
||||
# iconv used to filter out broken utf characters, if not installed fake it
|
||||
@ -436,13 +454,14 @@ sendJson(){
|
||||
local json chat=""
|
||||
if [ -n "$1" ]; then
|
||||
chat='"chat_id":'"$1"','
|
||||
[[ "$1" == *[!${o9o9o9}-]* ]] && chat='"chat_id":"'"$1"' NAN",' # chat id not a number!
|
||||
[[ "$1" == *[!${o9o9o9}-]* ]] && chat='"chat_id":"'"$1"' NAN",' # chat id not a number!
|
||||
fi
|
||||
# compose final json
|
||||
json='{'"${chat} $(iconv -f utf-8 -t utf-8 -c <<<"$2")"'}'
|
||||
if [ -n "${BASHBOTDEBUG}" ] ; then
|
||||
log_update "sendJson (${DETECTED_CURL}) CHAT=${chat#*:} JSON=${2:0:100} URL=${3##*/}"
|
||||
log_message "DEBUG sendJson ==========\n$("${JSONSHFILE}" -b -n <<<"${json}" 2>&1)"
|
||||
# mask " and \ , remove newline from json
|
||||
log_message "DEBUG sendJson ==========\n$("${JSONSHFILE}" -b -n <<<"$(sed -E -e 's/\\"/+/g' -e 's/\\/\\\\/g' -e 's/(\r|\n)//g' <<<"${json}")" 2>&1)"
|
||||
fi
|
||||
# chat id not a number
|
||||
if [[ "${chat}" == *"NAN\"," ]]; then
|
||||
@ -458,6 +477,7 @@ sendJson(){
|
||||
[ -n "${BASHBOT_EVENT_SEND[*]}" ] && event_send "send" "${@}" &
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# curl / wget specific functions
|
||||
#
|
||||
@ -519,7 +539,7 @@ else
|
||||
else
|
||||
printf "${RED}Error: curl and wget not found, install curl!${NN}"
|
||||
fi
|
||||
exit 8
|
||||
exit_source 8
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -557,8 +577,8 @@ sendJsonResult(){
|
||||
[ -n "${BASHBOTDEBUG}" ] && log_message "New Result ==========\n$1"
|
||||
BOTSENT[OK]="${UPD["ok"]}"
|
||||
if [ "${BOTSENT[OK]}" = "true" ]; then
|
||||
BOTSENT[ID]="${UPD["result","message_id"]}"
|
||||
BOTSENT[CHAT]="${UPD["result","chat","id"]}"
|
||||
BOTSENT[ID]="${UPD["result,message_id"]}"
|
||||
BOTSENT[CHAT]="${UPD["result,chat,id"]}"
|
||||
[ -n "${UPD["result"]}" ] && BOTSENT[RESULT]="${UPD["result"]}"
|
||||
return
|
||||
# hot path everything OK!
|
||||
@ -567,7 +587,7 @@ sendJsonResult(){
|
||||
if [ -n "$1" ]; then
|
||||
BOTSENT[ERROR]="${UPD["error_code"]}"
|
||||
BOTSENT[DESCRIPTION]="${UPD["description"]}"
|
||||
[ -n "${UPD["parameters","retry_after"]}" ] && BOTSENT[RETRY]="${UPD["parameters","retry_after"]}"
|
||||
[ -n "${UPD["parameters,retry_after"]}" ] && BOTSENT[RETRY]="${UPD["parameters,retry_after"]}"
|
||||
else
|
||||
BOTSENT[OK]="false"
|
||||
BOTSENT[ERROR]="999"
|
||||
@ -616,13 +636,6 @@ sendJsonResult(){
|
||||
fi
|
||||
} >>"${ERRORLOG}"
|
||||
|
||||
# escape / remove text characters for json strings, eg. " -> \"
|
||||
# $1 string
|
||||
# output escaped string
|
||||
JsonEscape(){
|
||||
sed 's/\([-"`´,§$%&/(){}#@!?*.\t]\)/\\\1/g' <<< "$1"
|
||||
}
|
||||
|
||||
# convert common telegram entities to JSON
|
||||
# title caption description markup inlinekeyboard
|
||||
title2Json(){
|
||||
@ -659,83 +672,9 @@ JsonDecode() {
|
||||
printf "%b\n" "${out}${remain}"
|
||||
}
|
||||
|
||||
JsonGetString() {
|
||||
sed -n -e '0,/\['"$1"'\]/ s/\['"$1"'\][ \t]"\(.*\)"$/\1/p'
|
||||
}
|
||||
JsonGetLine() {
|
||||
sed -n -e '0,/\['"$1"'\]/ s/\['"$1"'\][ \t]//p'
|
||||
}
|
||||
JsonGetValue() {
|
||||
sed -n -e '0,/\['"$1"'\]/ s/\['"$1"'\][ \t]\([0-9.,]*\).*/\1/p'
|
||||
}
|
||||
|
||||
################
|
||||
# processing of updates starts here
|
||||
process_updates() {
|
||||
local max num debug="$1"
|
||||
max="$(grep -F ',"update_id"]' <<< "${UPDATE}" | tail -1 | cut -d , -f 2 )"
|
||||
Json2Array 'UPD' <<<"${UPDATE}"
|
||||
for ((num=0; num<=max; num++)); do
|
||||
process_client "${num}" "${debug}"
|
||||
done
|
||||
}
|
||||
|
||||
process_client() {
|
||||
local num="$1" debug="$2"
|
||||
pre_process_message "${num}"
|
||||
# log message on debug
|
||||
[[ -n "${debug}" ]] && log_message "New Message ==========\n$(grep -F '["result",'"${num}" <<<"${UPDATE}")"
|
||||
|
||||
# check for users / groups to ignore
|
||||
jssh_updateArray_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
||||
[ -n "${USER[ID]}" ] && [[ -n "${BASHBOTBLOCKED[${USER[ID]}]}" || -n "${BASHBOTBLOCKED[${CHAT[ID]}]}" ]] && return
|
||||
|
||||
# process per message type
|
||||
if [ -z "${iQUERY[ID]}" ]; then
|
||||
if grep -qs -e '\["result",'"${num}"',"edited_message"' <<<"${UPDATE}"; then
|
||||
# edited message
|
||||
UPDATE="${UPDATE//,${num},\"edited_message\",/,${num},\"message\",}"
|
||||
Json2Array 'UPD' <<<"${UPDATE}"
|
||||
MESSAGE[0]="/_edited_message "
|
||||
fi
|
||||
process_message "${num}" "${debug}"
|
||||
printf "%(%c)T: update received FROM=%s CHAT=%s CMD=%s\n" -1 "${USER[USERNAME]:0:20} (${USER[ID]})"\
|
||||
"${CHAT[USERNAME]:0:20}${CHAT[TITLE]:0:30} (${CHAT[ID]})"\
|
||||
"${MESSAGE:0:30}${CAPTION:0:30}${URLS[*]:0:30}" >>"${UPDATELOG}"
|
||||
else
|
||||
process_inline "${num}" "${debug}"
|
||||
printf "%(%c)T: iQuery received FROM=%s iQUERY=%s\n" -1\
|
||||
"${iQUERY[USERNAME]:0:20} (${iQUERY[USER_ID]})" "${iQUERY[0]}" >>"${UPDATELOG}"
|
||||
fi
|
||||
#####
|
||||
# process inline and message events
|
||||
# first classic command dispatcher
|
||||
# shellcheck source=./commands.sh
|
||||
source "${COMMANDS}" "${debug}" &
|
||||
|
||||
# then all registered addons
|
||||
if [ -z "${iQUERY[ID]}" ]; then
|
||||
event_message "${debug}"
|
||||
else
|
||||
event_inline "${debug}"
|
||||
fi
|
||||
|
||||
# last count users
|
||||
jssh_countKeyDB_async "${CHAT[ID]}" "${COUNTFILE}"
|
||||
}
|
||||
|
||||
declare -Ax BASHBOT_EVENT_INLINE BASHBOT_EVENT_MESSAGE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLYTO BASHBOT_EVENT_FORWARD BASHBOT_EVENT_SEND
|
||||
declare -Ax BASHBOT_EVENT_CONTACT BASHBOT_EVENT_LOCATION BASHBOT_EVENT_FILE BASHBOT_EVENT_TEXT BASHBOT_EVENT_TIMER BASHBOT_BLOCKED
|
||||
|
||||
start_timer(){
|
||||
# send alarm every ~60 s
|
||||
while :; do
|
||||
sleep 59.5
|
||||
kill -ALRM $$
|
||||
done;
|
||||
}
|
||||
|
||||
EVENT_SEND="0"
|
||||
declare -Ax BASHBOT_EVENT_SEND
|
||||
event_send() {
|
||||
# max recursion level 5 to avoid fork bombs
|
||||
(( EVENT_SEND++ )); [ "${EVENT_SEND}" -gt "5" ] && return
|
||||
@ -746,425 +685,36 @@ event_send() {
|
||||
done
|
||||
}
|
||||
|
||||
EVENT_TIMER="0"
|
||||
event_timer() {
|
||||
local key timer debug="$1"
|
||||
(( EVENT_TIMER++ ))
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_TIMER[@]}"
|
||||
do
|
||||
timer="${key##*,}"
|
||||
[[ ! "${timer}" =~ ^-*[1-9][0-9]*$ ]] && continue
|
||||
if [ "$(( EVENT_TIMER % timer ))" = "0" ]; then
|
||||
_exec_if_function "${BASHBOT_EVENT_TIMER[${key}]}" "timer" "${key}" "${debug}"
|
||||
[ "$(( EVENT_TIMER % timer ))" -lt "0" ] && \
|
||||
unset BASHBOT_EVENT_TIMER["${key}"]
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
event_inline() {
|
||||
local key debug="$1"
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_INLINE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_INLINE[${key}]}" "inline" "${key}" "${debug}"
|
||||
done
|
||||
}
|
||||
event_message() {
|
||||
local key debug="$1"
|
||||
# ${MESSAEG[*]} event_message
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_MESSAGE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_MESSAGE[${key}]}" "message" "${key}" "${debug}"
|
||||
done
|
||||
|
||||
# ${TEXT[*]} event_text
|
||||
if [ -n "${MESSAGE[0]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_TEXT[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_TEXT[${key}]}" "text" "${key}" "${debug}"
|
||||
done
|
||||
|
||||
# ${CMD[*]} event_cmd
|
||||
if [ -n "${CMD[0]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_CMD[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_CMD[${key}]}" "command" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
# ${REPLYTO[*]} event_replyto
|
||||
if [ -n "${REPLYTO[UID]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_REPLYTO[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_REPLYTO[${key}]}" "replyto" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${FORWARD[*]} event_forward
|
||||
if [ -n "${FORWARD[UID]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_FORWARD[@]}"
|
||||
do
|
||||
_exec_if_function && "${BASHBOT_EVENT_FORWARD[${key}]}" "forward" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${CONTACT[*]} event_contact
|
||||
if [ -n "${CONTACT[FIRST_NAME]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_CONTACT[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_CONTACT[${key}]}" "contact" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${VENUE[*]} event_location
|
||||
# ${LOCATION[*]} event_location
|
||||
if [ -n "${LOCATION[LONGITUDE]}" ] || [ -n "${VENUE[TITLE]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_LOCATION[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_LOCATION[${key}]}" "location" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${URLS[*]} event_file
|
||||
# NOTE: compare again #URLS -1 blanks!
|
||||
if [[ "${URLS[*]}" != " " ]]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_FILE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_FILE[${key}]}" "file" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
}
|
||||
pre_process_message(){
|
||||
local num="$1"
|
||||
# unset everything to not have old values
|
||||
CMD=( ); iQUERY=( ); MESSAGE=(); CHAT=(); USER=(); CONTACT=(); LOCATION=(); unset CAPTION
|
||||
REPLYTO=( ); FORWARD=( ); URLS=(); VENUE=( ); SERVICE=( ); NEWMEMBER=( ); LEFTMEMBER=( ); PINNED=( ); MIGRATE=( )
|
||||
iQUERY[ID]="${UPD["result",${num},"inline_query","id"]}"
|
||||
CHAT[ID]="${UPD["result",${num},"message","chat","id"]}"
|
||||
USER[ID]="${UPD["result",${num},"message","from","id"]}"
|
||||
[ -z "${CHAT[ID]}" ] && CHAT[ID]="${UPD["result",${num},"edited_message","chat","id"]}"
|
||||
[ -z "${USER[ID]}" ] && USER[ID]="${UPD["result",${num},"edited_message","from","id"]}"
|
||||
# always true
|
||||
return 0
|
||||
}
|
||||
process_inline() {
|
||||
local num="$1"
|
||||
iQUERY[0]="$(JsonDecode "${UPD["result",${num},"inline_query","query"]}")"
|
||||
iQUERY[USER_ID]="${UPD["result",${num},"inline_query","from","id"]}"
|
||||
iQUERY[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"inline_query","from","first_name"]}")"
|
||||
iQUERY[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"inline_query","from","last_name"]}")"
|
||||
iQUERY[USERNAME]="$(JsonDecode "${UPD["result",${num},"inline_query","from","username"]}")"
|
||||
# always true
|
||||
return 0
|
||||
}
|
||||
process_message() {
|
||||
local num="$1"
|
||||
# Message
|
||||
MESSAGE[0]+="$(JsonDecode "${UPD["result",${num},"message","text"]}" | sed 's|\\/|/|g')"
|
||||
MESSAGE[ID]="${UPD["result",${num},"message","message_id"]}"
|
||||
|
||||
# Chat ID is now parsed when update is received
|
||||
CHAT[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","chat","last_name"]}")"
|
||||
CHAT[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","chat","first_name"]}")"
|
||||
CHAT[USERNAME]="$(JsonDecode "${UPD["result",${num},"message","chat","username"]}")"
|
||||
# set real name as username if empty
|
||||
[ -z "${CHAT[USERNAME]}" ] && CHAT[USERNAME]="${CHAT[FIRST_NAME]} ${CHAT[LAST_NAME]}"
|
||||
CHAT[TITLE]="$(JsonDecode "${UPD["result",${num},"message","chat","title"]}")"
|
||||
CHAT[TYPE]="$(JsonDecode "${UPD["result",${num},"message","chat","type"]}")"
|
||||
CHAT[ALL_ADMIN]="${UPD["result",${num},"message","chat","all_members_are_administrators"]}"
|
||||
|
||||
# user ID is now parsed when update is received
|
||||
#USER[ID]="${UPD["result",${num},"message","from","id"]}"
|
||||
USER[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","from","first_name"]}")"
|
||||
USER[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","from","last_name"]}")"
|
||||
USER[USERNAME]="$(JsonDecode "${UPD["result",${num},"message","from","username"]}")"
|
||||
# set real name as username if empty
|
||||
[ -z "${USER[USERNAME]}" ] && USER[USERNAME]="${USER[FIRST_NAME]} ${USER[LAST_NAME]}"
|
||||
|
||||
# in reply to message from
|
||||
if [ -n "${UPD["result",${num},"message","reply_to_message","from","id"]}" ]; then
|
||||
REPLYTO[UID]="${UPD["result",${num},"message","reply_to_message","from","id"]}"
|
||||
REPLYTO[0]="$(JsonDecode "${UPD["result",${num},"message","reply_to_message","text"]}")"
|
||||
REPLYTO[ID]="${UPD["result",${num},"message","reply_to_message","message_id"]}"
|
||||
REPLYTO[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","reply_to_message","from","first_name"]}")"
|
||||
REPLYTO[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","reply_to_message","from","last_name"]}")"
|
||||
REPLYTO[USERNAME]="$(JsonDecode "${UPD["result",${num},"message","reply_to_message","from","username"]}")"
|
||||
fi
|
||||
|
||||
# forwarded message from
|
||||
if [ -n "${UPD["result",${num},"message","forward_from","id"]}" ]; then
|
||||
FORWARD[UID]="${UPD["result",${num},"message","forward_from","id"]}"
|
||||
FORWARD[ID]="${MESSAGE[ID]}" # same as message ID
|
||||
FORWARD[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","forward_from","first_name"]}")"
|
||||
FORWARD[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","forward_from","last_name"]}")"
|
||||
FORWARD[USERNAME]="$(JsonDecode "${UPD["result",${num},"message","forward_from","username"]}")"
|
||||
fi
|
||||
|
||||
# get file URL from telegram, check for any of them!
|
||||
if grep -qs -e '\["result",'"${num}"',"message","[avpsd].*,"file_id"\]' <<<"${UPDATE}"; then
|
||||
URLS[AUDIO]="$(get_file "${UPD["result",${num},"message","audio","file_id"]}")"
|
||||
URLS[DOCUMENT]="$(get_file "${UPD["result",${num},"message","document","file_id"]}")"
|
||||
URLS[PHOTO]="$(get_file "${UPD["result",${num},"message","photo",0,"file_id"]}")"
|
||||
URLS[STICKER]="$(get_file "${UPD["result",${num},"message","sticker","file_id"]}")"
|
||||
URLS[VIDEO]="$(get_file "${UPD["result",${num},"message","video","file_id"]}")"
|
||||
URLS[VOICE]="$(get_file "${UPD["result",${num},"message","voice","file_id"]}")"
|
||||
fi
|
||||
# Contact, must have phone_number
|
||||
if [ -n "${UPD["result",${num},"message","contact","phone_number"]}" ]; then
|
||||
CONTACT[USER_ID]="$(JsonDecode "${UPD["result",${num},"message","contact","user_id"]}")"
|
||||
CONTACT[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","contact","first_name"]}")"
|
||||
CONTACT[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","contact","last_name"]}")"
|
||||
CONTACT[NUMBER]="${UPD["result",${num},"message","contact","phone_number"]}"
|
||||
CONTACT[VCARD]="$(JsonGetString '"result",'"${num}"',"message","contact","vcard"' <<<"${UPDATE}")"
|
||||
fi
|
||||
|
||||
# venue, must have a position
|
||||
if [ -n "${UPD["result",${num},"message","venue","location","longitude"]}" ]; then
|
||||
VENUE[TITLE]="$(JsonDecode "${UPD["result",${num},"message","venue","title"]}")"
|
||||
VENUE[ADDRESS]="$(JsonDecode "${UPD["result",${num},"message","venue","address"]}")"
|
||||
VENUE[LONGITUDE]="${UPD["result",${num},"message","venue","location","longitude"]}"
|
||||
VENUE[LATITUDE]="${UPD["result",${num},"message","venue","location","latitude"]}"
|
||||
VENUE[FOURSQUARE]="${UPD["result",${num},"message","venue","foursquare_id"]}"
|
||||
fi
|
||||
|
||||
# Caption
|
||||
CAPTION="$(JsonDecode "${UPD["result",${num},"message","caption"]}")"
|
||||
|
||||
# Location
|
||||
LOCATION[LONGITUDE]="${UPD["result",${num},"message","location","longitude"]}"
|
||||
LOCATION[LATITUDE]="${UPD["result",${num},"message","location","latitude"]}"
|
||||
|
||||
# service messages, group or channel only!
|
||||
if [[ "${CHAT[ID]}" == "-"* ]] ; then
|
||||
# new chat member
|
||||
if [ -n "${UPD["result",${num},"message","new_chat_member","id"]}" ]; then
|
||||
SERVICE[NEWMEMBER]="${UPD["result",${num},"message","new_chat_member","id"]}"
|
||||
NEWMEMBER[ID]="${SERVICE[NEWMEMBER]}"
|
||||
NEWMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","new_chat_member","first_name"]}")"
|
||||
NEWMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","new_chat_member","last_name"]}")"
|
||||
NEWMEMBER[USERNAME]="$(JsonDecode "${UPD["result",${num},"message","new_chat_member","username"]}")"
|
||||
NEWMEMBER[ISBOT]="${UPD["result",${num},"message","new_chat_member","is_bot"]}"
|
||||
[ -z "${MESSAGE[0]}" ] &&\
|
||||
MESSAGE[0]="/_new_chat_member ${NEWMEMBER[ID]} ${NEWMEMBER[USERNAME]:=${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]}}"
|
||||
fi
|
||||
# left chat member
|
||||
if [ -n "${UPD["result",${num},"message","left_chat_member","id"]}" ]; then
|
||||
SERVICE[LEFTMEMBER]="${UPD["result",${num},"message","left_chat_member","id"]}"
|
||||
LEFTMEMBER[ID]="${SERVICE[LEFTMEBER]}"
|
||||
LEFTMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","left_chat_member","first_name"]}")"
|
||||
LEFTMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result",${num},"message","left_chat_member","last_name"]}")"
|
||||
LEFTMEBER[USERNAME]="$(JsonDecode "${UPD["result",${num},"message","left_chat_member","username"]}")"
|
||||
LEFTMEMBER[ISBOT]="${UPD["result",${num},"message","left_chat_member","is_bot"]}"
|
||||
[ -z "${MESSAGE[0]}" ] &&\
|
||||
MESSAGE[0]="/_left_chat_member ${LEFTMEMBER[ID]} ${LEFTMEMBER[USERNAME]:=${LEFTMEMBER[FIRST_NAME]} ${LEFTMEMBER[LAST_NAME]}}"
|
||||
fi
|
||||
# chat title / photo, check for any of them!
|
||||
if grep -qs -e '\["result",'"${num}"',"message","new_chat_[tp]' <<<"${UPDATE}"; then
|
||||
SERVICE[NEWTITLE]="$(JsonDecode "${UPD["result",${num},"message","new_chat_title"]}")"
|
||||
[ -z "${MESSAGE[0]}" ] && [ -n "${SERVICE[NEWTITLE]}" ] &&\
|
||||
MESSAGE[0]="/_new_chat_title ${USER[ID]} ${SERVICE[NEWTITLE]}"
|
||||
SERVICE[NEWPHOTO]="$(get_file "${UPD["result",${num},"message","new_chat_photo",0,"file_id"]}")"
|
||||
[ -z "${MESSAGE[0]}" ] && [ -n "${SERVICE[NEWPHOTO]}" ] &&\
|
||||
MESSAGE[0]="/_new_chat_photo ${USER[ID]} ${SERVICE[NEWPHOTO]}"
|
||||
fi
|
||||
# pinned message
|
||||
if [ -n "${UPD["result",${num},"message","pinned_message","message_id"]}" ]; then
|
||||
SERVICE[PINNED]="${UPD["result",${num},"message","pinned_message","message_id"]}"
|
||||
PINNED[ID]="${SERVICE[PINNED]}"
|
||||
PINNED[MESSAGE]="$(JsonDecode "${UPD["result",${num},"message","pinned_message","text"]}")"
|
||||
[ -z "${MESSAGE[0]}" ] &&\
|
||||
MESSAGE[0]="/_new_pinned_message ${USER[ID]} ${PINNED[ID]} ${PINNED[MESSAGE]}"
|
||||
fi
|
||||
# migrate to super group
|
||||
if [ -n "${UPD["result",${num},"message","migrate_to_chat_id"]}" ]; then
|
||||
MIGRATE[TO]="${UPD["result",${num},"message","migrate_to_chat_id"]}"
|
||||
MIGRATE[FROM]="${UPD["result",${num},"message","migrate_from_chat_id"]}"
|
||||
SERVICE[MIGRATE]="${MIGRATE[FROM]} ${MIGRATE[TO]}"
|
||||
[ -z "${MESSAGE[0]}" ] &&\
|
||||
MESSAGE[0]="/_migrate_group ${SERVICE[MIGRATE]}"
|
||||
fi
|
||||
# set SERVICE to yes if a service message was received
|
||||
[[ "${SERVICE[*]}" =~ ^[[:blank:]]*$ ]] || SERVICE[0]="yes"
|
||||
fi
|
||||
|
||||
# split message in command and args
|
||||
[[ "${MESSAGE[0]}" == "/"* ]] && read -r CMD <<<"${MESSAGE[0]}" && CMD[0]="${CMD[0]%%@*}"
|
||||
# everything went well
|
||||
return 0
|
||||
}
|
||||
|
||||
#########################
|
||||
# main get updates loop, should never terminate
|
||||
declare -A BASHBOTBLOCKED
|
||||
start_bot() {
|
||||
local DEBUGMSG OFFSET=0
|
||||
# adaptive sleep defaults
|
||||
local nextsleep="100"
|
||||
local stepsleep="${BASHBOT_SLEEP_STEP:-100}"
|
||||
local maxsleep="${BASHBOT_SLEEP:-5000}"
|
||||
# startup message
|
||||
DEBUGMSG="Start BASHBOT updates in Mode \"${1:-normal}\" =========="
|
||||
log_update "${DEBUGMSG}"
|
||||
# redirect to Debug.log
|
||||
[[ "$1" == *"debug" ]] && exec &>>"${DEBUGLOG}"
|
||||
log_debug "${DEBUGMSG}"; DEBUGMSG="$1"
|
||||
[[ "${DEBUGMSG}" == "xdebug"* ]] && set -x
|
||||
# cleaup old pipes and empty logfiles
|
||||
find "${DATADIR}" -type p -delete
|
||||
find "${DATADIR}" -size 0 -name "*.log" -delete
|
||||
# load addons on startup
|
||||
for addons in "${ADDONDIR:-.}"/*.sh ; do
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
[ -r "${addons}" ] && source "${addons}" "startbot" "${DEBUGMSG}"
|
||||
done
|
||||
# shellcheck source=./commands.sh
|
||||
source "${COMMANDS}" "startbot"
|
||||
# start timer events
|
||||
if [ -n "${BASHBOT_START_TIMER}" ] ; then
|
||||
# shellcheck disable=SC2064
|
||||
trap "event_timer ${DEBUGMSG}" ALRM
|
||||
start_timer &
|
||||
# shellcheck disable=SC2064
|
||||
trap "kill -9 $!; exit" EXIT INT HUP TERM QUIT
|
||||
fi
|
||||
# cleanup countfile on startup
|
||||
jssh_deleteKeyDB "CLEAN_COUNTER_DATABASE_ON_STARTUP" "${COUNTFILE}"
|
||||
[ -f "${COUNTFILE}.jssh.flock" ] && rm -f "${COUNTFILE}.jssh.flock"
|
||||
# store start time and cleanup botconfig on startup
|
||||
jssh_updateKeyDB "startup" "$(_date)" "${BOTCONFIG}"
|
||||
[ -f "${BOTCONFIG}.jssh.flock" ] && rm -f "${BOTCONFIG}.jssh.flock"
|
||||
# read blocked users
|
||||
jssh_readDB_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
||||
# inform botadmin about start
|
||||
send_normal_message "$(getConfigKey "botadmin")" "Bot $(getConfigKey "botname") started ..." &
|
||||
##########
|
||||
# bot is ready, start processing updates ...
|
||||
while true; do
|
||||
# adaptive sleep in ms rounded to next 0.1 s
|
||||
sleep "$(_round_float "${nextsleep}e-3" "1")"
|
||||
# get next update
|
||||
UPDATE="$(getJson "${URL}/getUpdates?offset=${OFFSET}" 2>/dev/null | "${JSONSHFILE}" -b -n 2>/dev/null | iconv -f utf-8 -t utf-8 -c)"
|
||||
# did we get an response?
|
||||
if [ -n "${UPDATE}" ]; then
|
||||
# we got something, do processing
|
||||
[ "${OFFSET}" = "-999" ] && [ "${nextsleep}" -gt "$((maxsleep*2))" ] &&\
|
||||
log_error "Recovered from timeout/broken/no connection, continue with telegram updates"
|
||||
# escape bash $ expansion bug
|
||||
((nextsleep+= stepsleep , nextsleep= nextsleep>maxsleep ?maxsleep:nextsleep))
|
||||
UPDATE="${UPDATE//$/\\$}"
|
||||
# Offset
|
||||
OFFSET="$(grep <<< "${UPDATE}" '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)"
|
||||
((OFFSET++))
|
||||
|
||||
if [ "${OFFSET}" != "1" ]; then
|
||||
nextsleep="100"
|
||||
process_updates "${DEBUGMSG}"
|
||||
fi
|
||||
else
|
||||
# oops, something bad happened, wait maxsleep*10
|
||||
(( nextsleep=nextsleep*2 , nextsleep= nextsleep>maxsleep*10 ?maxsleep*10:nextsleep ))
|
||||
# second time, report problem
|
||||
if [ "${OFFSET}" = "-999" ]; then
|
||||
log_error "Repeated timeout/broken/no connection on telegram update, sleep $(_round_float "${nextsleep}e-3")s"
|
||||
# try to recover
|
||||
if _is_function bashbotBlockRecover && [ -z "$(getJson "${ME_URL}")" ]; then
|
||||
log_error "Try to recover, calling bashbotBlockRecover ..."
|
||||
bashbotBlockRecover >>"${ERRORLOG}"
|
||||
fi
|
||||
fi
|
||||
OFFSET="-999"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# fallback version, full version is in bin/bashbot_init.in.sh
|
||||
# initialize bot environment, user and permissions
|
||||
bot_init() {
|
||||
[ -n "${BASHBOT_HOME}" ] && cd "${BASHBOT_HOME}" || exit 1
|
||||
local runuser chown touser botname DEBUG="$1"
|
||||
# upgrade from old version
|
||||
# currently no action
|
||||
printf "Check for Update actions ...\n"
|
||||
printf "Done.\n"
|
||||
# load addons on startup
|
||||
printf "Initialize modules and addons ...\n"
|
||||
if [ -n "${BASHBOT_HOME}" ] && ! cd "${BASHBOT_HOME}"; then
|
||||
printf "Can't change to BASHBOT_HOME"
|
||||
exit 1
|
||||
fi
|
||||
# initialize addons
|
||||
printf "Initialize addons ...\n"
|
||||
for addons in "${ADDONDIR:-.}"/*.sh ; do
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
[ -r "${addons}" ] && source "${addons}" "init" "${DEBUG}"
|
||||
[ -r "${addons}" ] && source "${addons}" "init" "$1"
|
||||
done
|
||||
printf "Done.\n"
|
||||
# ask for bashbot user
|
||||
runuser="${RUNUSER}"; [ "${UID}" = "0" ] && runuser="nobody"
|
||||
printf "Enter User to run bashbot [${runuser}]: "
|
||||
read -r chown
|
||||
[ -z "${chown}" ] && chown="${runuser}"; touser="${chown%:*}"
|
||||
# check user ...
|
||||
if ! id "${touser}" &>/dev/null; then
|
||||
printf "${RED}User \"${touser}\" does not exist!${NN}"
|
||||
exit 3
|
||||
elif [[ "${UID}" != "0" && "${touser}" != "${runuser}" ]]; then
|
||||
# different user but not root ...
|
||||
printf "${ORANGE}You are not root, adjusting permissions may fail. Try \"sudo ./bashbot.sh init\"${NN}Press <CTRL+C> to stop or <Enter> to continue..." 1>&2
|
||||
[ -n "${INTERACTIVE}" ] && read -r runuser
|
||||
fi
|
||||
# adjust permissions
|
||||
printf "Adjusting files and permissions for user \"${touser}\" ...\n"
|
||||
printf "Adjusting files and permissions ...\n"
|
||||
chmod 711 .
|
||||
chmod -R o-w ./*
|
||||
chmod -R u+w "${COUNTFILE}"* "${BLOCKEDFILE}"* "${DATADIR}" logs "${LOGDIR}/"*.log 2>/dev/null
|
||||
chmod -R o-r,o-w "${COUNTFILE}"* "${BLOCKEDFILE}"* "${DATADIR}" "${BOTACL}" 2>/dev/null
|
||||
# jsshDB must writeable by owner
|
||||
find . -name '*.jssh*' -exec chmod u+w \{\} +
|
||||
chown -Rf "${chown}" . ./*
|
||||
printf "Done.\n"
|
||||
# adjust values in bashbot.rc
|
||||
if [ -w "bashbot.rc" ]; then
|
||||
printf "Adjust user and botname in bashbot.rc ...\n"
|
||||
sed -i '/^[# ]*runas=/ s|runas=.*$|runas="'"${touser}"'"|' "bashbot.rc"
|
||||
sed -i '/^[# ]*bashbot=/ s|bashbot=.*$|bashbot="cd '"${PWD}"'; '"${PWD}"'/'"${0##*/}"'"|' "bashbot.rc"
|
||||
botname="$(getConfigKey "botname")"
|
||||
[ -n "${botname}" ] && sed -i '/^[# ]*name=/ s|name=.*$|name="'"${botname}"'"|' "bashbot.rc"
|
||||
printf "Done.\n"
|
||||
fi
|
||||
# ask to check bottoken online
|
||||
if [ -z "$(getConfigKey "botid")" ]; then
|
||||
printf "Seems to be your first init. Should I verify your bot token online? (y/N) N\b"
|
||||
read -r ANSWER
|
||||
if [[ "${ANSWER}" =~ ^[Yy] ]]; then
|
||||
printf "${GREEN}Contacting telegram to verify your bot token ...${NN}"
|
||||
$0 botname
|
||||
fi
|
||||
fi
|
||||
# check if botconf seems valid
|
||||
printf "${GREEN}This is your bot config:${NN}"
|
||||
sed 's/^/\t/' "${BOTCONFIG}.jssh" | grep -vF '["bot_config_key"]'
|
||||
if check_token "$(getConfigKey "bottoken")" && [[ "$(getConfigKey "botadmin")" =~ ^[${o9o9o9}]+$ ]]; then
|
||||
printf "Bot config seems to be valid. Should I make a backup copy? (Y/n) Y\b"
|
||||
read -r ANSWER
|
||||
if [[ -z "${ANSWER}" || "${ANSWER}" =~ ^[^Nn] ]]; then
|
||||
printf "Copy bot config to ${BOTCONFIG}.jssh.ok ...\n"
|
||||
cp "${BOTCONFIG}.jssh" "${BOTCONFIG}.jssh.ok"
|
||||
fi
|
||||
else
|
||||
printf "${ORANGE}Bot config may incomplete, pls check.${NN}"
|
||||
fi
|
||||
# show result
|
||||
ls -ld "${DATADIR}" "${LOGDIR}" ./*.jssh* ./*.sh 2>/dev/null
|
||||
_exec_if_function my_init
|
||||
}
|
||||
|
||||
if ! _is_function send_message ; then
|
||||
printf "${RED}ERROR: send_message is not available, did you deactivate ${MODULEDIR}/sendMessage.sh?${NN}"
|
||||
exit 1
|
||||
exit_source 1
|
||||
fi
|
||||
|
||||
# check if JSON.awk exist and has x flag
|
||||
@ -1201,7 +751,7 @@ if [ -z "${SOURCE}" ]; then
|
||||
[ "$1" = "botname" ] && exit
|
||||
;;&
|
||||
# used to send output of background and interactive to chats
|
||||
"outproc") # $2 chat_id $3 identifier of job, internal use only!
|
||||
"outproc") # $2 chat_id $3 identifier of job, internal use only!
|
||||
[ -z "$3" ] && printf "No job identifier\n" && exit 3
|
||||
[ -z "$2" ] && printf "No chat to send to\n" && exit 3
|
||||
ME="$(getConfigKey "botname")"
|
||||
@ -1215,14 +765,16 @@ if [ -z "${SOURCE}" ]; then
|
||||
debug_checks "end outproc" "$@"
|
||||
exit
|
||||
;;
|
||||
# finally starts the read update loop, internal use only1
|
||||
# finally starts the read update loop, internal use only
|
||||
"startbot" )
|
||||
start_bot "$2"
|
||||
_exec_if_function start_bot "$2"
|
||||
debug_checks "end startbot" "$@"
|
||||
exit
|
||||
;;
|
||||
# run after every update to update files and adjust permissions
|
||||
"init")
|
||||
# shellcheck source=./bin/bashbot._init.inc.sh"
|
||||
[ -r "${BASHBOT_HOME:-.}/bin/bashbot_init.inc.sh" ] && source "${BASHBOT_HOME:-.}/bin/bashbot_init.inc.sh"
|
||||
bot_init "$2"
|
||||
debug_checks "end init" "$@"
|
||||
exit
|
||||
@ -1256,14 +808,18 @@ if [ -z "${SOURCE}" ]; then
|
||||
|
||||
# start bot as background job and check if bot is running
|
||||
"start")
|
||||
# shellcheck disable=SC2086
|
||||
SESSION="${ME:-_bot}-startbot"
|
||||
BOTPID="$(proclist "${SESSION}")"
|
||||
# shellcheck disable=SC2086
|
||||
[ -n "${BOTPID}" ] && kill ${BOTPID}
|
||||
nohup "${SCRIPT}" "startbot" "$2" "${SESSION}" &>/dev/null &
|
||||
printf "Session Name: %s\n" "${SESSION}"
|
||||
sleep 1
|
||||
if _is_function process_update; then
|
||||
# shellcheck disable=SC2086
|
||||
[ -n "${BOTPID}" ] && kill ${BOTPID} && printf "${GREY}Stop already running bot ...${NN}"
|
||||
nohup "${SCRIPT}" "startbot" "$2" "${SESSION}" &>/dev/null &
|
||||
printf "Session Name: %s\n" "${SESSION}"
|
||||
sleep 1
|
||||
else
|
||||
printf "${ORANGE}Update processing disabled, bot can only send messages.${NN}"
|
||||
[ -n "${BOTPID}" ] && printf "${ORANGE}Already running bot found ...${NN}"
|
||||
fi
|
||||
if [ -n "$(proclist "${SESSION}")" ]; then
|
||||
printf "${GREEN}Bot started successfully.${NN}"
|
||||
else
|
||||
|
85
bin/any_command.sh
Executable file
85
bin/any_command.sh
Executable file
@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034,SC2059
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/any_command.sh
|
||||
#
|
||||
USAGE='any_command.sh [-h|--help] [--force|--reference] bot_command args ...'
|
||||
#
|
||||
# DESCRIPTION: execute (almost) any bashbot command/function
|
||||
# can be used for testing commands while bot development
|
||||
#
|
||||
# OPTIONS: -- force - execute unknown commands/functions
|
||||
# by default only commands in 6_reference.md are allowed
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 30.01.2021 10:24
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
COMMAND=""
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
|
||||
print_help "$1"
|
||||
|
||||
|
||||
error=""
|
||||
# check options
|
||||
if [[ "$1" = "--force" ]]; then
|
||||
# skip checks
|
||||
shift
|
||||
else
|
||||
# check for --ref
|
||||
ref="$1"; [[ "$1" == "--ref"* ]] && shift
|
||||
if [ "${#1}" -lt 11 ];then
|
||||
printf "${RED}Command must be minimum 11 characters!${NC}\n"
|
||||
error=3
|
||||
fi
|
||||
if [[ "$1" != *"_"* ]];then
|
||||
printf "${RED}Command must contain _ (underscore)!${NC}\n"
|
||||
error=3
|
||||
fi
|
||||
# simple hack to get allowed commands from doc
|
||||
if grep -q "^##### $1" <<<"$(sed -n -e '/^##### _is_/,$ d' -e '/^##### /p' "${BASHBOT_HOME:-..}doc/"6_*)"; then
|
||||
# oiutput reference and exit
|
||||
if [[ "${ref}" == "--ref"* ]]; then
|
||||
sed -n -e '/^##### '"$1"'/,/^##/ p' "${BASHBOT_HOME:-..}doc/"6_*
|
||||
exit
|
||||
fi
|
||||
else
|
||||
printf "Command ${GREY}%s${NC} not found in 6_reference.md, use ${GREY}--force${NC} to execute!\n" "$1"
|
||||
error=4
|
||||
fi
|
||||
[ -n "${error}" ] && exit "${error}"
|
||||
fi
|
||||
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
COMMAND="$1"
|
||||
if [ "$2" == "BOTADMIN" ]; then
|
||||
ARG1="${BOT_ADMIN}"
|
||||
else
|
||||
ARG1="$2"
|
||||
fi
|
||||
|
||||
# clear result and response
|
||||
BOTSENT=()
|
||||
UPD=()
|
||||
|
||||
# send message in selected format
|
||||
"${COMMAND}" "${ARG1}" "${@:3}"
|
||||
|
||||
# output result an telegram response
|
||||
print_result
|
||||
print_response
|
@ -13,12 +13,12 @@
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 18.12.2020 12:27
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
############
|
||||
# set where your bashbot lives
|
||||
export BASHBOT_HOME BASHBOT_ETC BASHBOT_VAR FILE_REGEX
|
||||
export BASHBOT_HOME BASHBOT_ETC BASHBOT_VAR FILE_REGEX ME
|
||||
|
||||
# default: one dir up
|
||||
BASHBOT_HOME="$(cd "${BASH_SOURCE[0]%/*}" >/dev/null 2>&1 && pwd)/../"
|
||||
@ -32,20 +32,21 @@ BASHBOT_ETC="${BASHBOT_HOME}"
|
||||
#####
|
||||
# if files are not readable, eviroment is wrong or bashbot is not initialized
|
||||
|
||||
# source bashbot
|
||||
# check for bashbot
|
||||
if [ ! -r "${BASHBOT_HOME}/bashbot.sh" ]; then
|
||||
printf "%s\n" "Bashbot.sh not found in \"${BASHBOT_HOME}\""
|
||||
exit 4
|
||||
fi
|
||||
|
||||
dev=" Are we in dev or did you forget to run init?"
|
||||
# check for botconfig.jssh readable
|
||||
if [ ! -r "${BASHBOT_ETC}/botconfig.jssh" ]; then
|
||||
printf "%s\n" "Bashbot config file in \"${BASHBOT_ETC}\" does not exist or is not readable."
|
||||
printf "%s\n" "Bashbot config file in \"${BASHBOT_ETC}\" does not exist or is not readable. ${dev}"
|
||||
exit 3
|
||||
fi
|
||||
# check for count.jssh readable
|
||||
if [ ! -r "${BASHBOT_VAR}/count.jssh" ]; then
|
||||
printf "%s\n" "Bashbot count file in \"${BASHBOT_VAR}\" does not exist or is not readable. Did you run bashbot init?"
|
||||
printf "%s\n" "Bashbot count file in \"${BASHBOT_VAR}\" does not exist or is not readable. ${dev}"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
@ -60,6 +61,28 @@ FILE_REGEX="${UPLOADDIR}/.*"
|
||||
# get and check ADMIN and NAME
|
||||
BOT_ADMIN="$(getConfigKey "botadmin")"
|
||||
BOT_NAME="$(getConfigKey "botname")"
|
||||
[[ -z "${BOT_ADMIN}" || "${BOT_ADMIN}" == "?" ]] && printf "%s\n" "${ORANGE}Warning: Botadmin not set, did you forget to sent command${NC} /start"
|
||||
[[ -z "${BOT_NAME}" ]] && printf "%s\n" "${ORANGE}Warning: Botname not set, did you ever run bashbot?"
|
||||
ME="${BOT_NAME}"
|
||||
[[ -z "${BOT_ADMIN}" || "${BOT_ADMIN}" == "?" ]] && printf "%s\n" "${ORANGE}Warning: Botadmin not set, send bot command${NC} /start"
|
||||
[[ -z "${BOT_NAME}" ]] && printf "%s\n" "${ORANGE}Warning: Botname not set, run bashbot.sh botname"
|
||||
|
||||
# output command result or Telegram response
|
||||
print_result() { jssh_printDB "BOTSENT" | sort -r; }
|
||||
print_response() { jssh_printDB "UPD"; }
|
||||
|
||||
# check and output help
|
||||
print_help() {
|
||||
case "$1" in
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: %s\n' "${USAGE}"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '/^#====/,/^#====/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
143
bin/bashbot_init.inc.sh
Normal file
143
bin/bashbot_init.inc.sh
Normal file
@ -0,0 +1,143 @@
|
||||
#!/bin/bash
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bashbot_init.inc.sh
|
||||
#
|
||||
# USAGE: source bashbot_init.inc.sh
|
||||
#
|
||||
# DESCRIPTION: extend / overwrite bashbot initialisation
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 27.01.2021 13:42
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2059
|
||||
|
||||
##########
|
||||
# commands to execute before bot_init() is called
|
||||
|
||||
|
||||
########
|
||||
# called after default init is finished
|
||||
my_init() {
|
||||
: # your init here
|
||||
}
|
||||
|
||||
|
||||
#########
|
||||
#
|
||||
# extended initialisation:
|
||||
#
|
||||
# - uograde old config
|
||||
# - backup of botconfig.jssh
|
||||
# - running bot as service or other user
|
||||
# - copy clean and dist files if not exist
|
||||
# - configure bot for INLINE CALLBACK MEONLY SILENCER
|
||||
#
|
||||
# delete from here to disable extended initialisation
|
||||
bot_init() {
|
||||
if [ -n "${BASHBOT_HOME}" ] && ! cd "${BASHBOT_HOME}"; then
|
||||
printf "Can't change to BASHBOT_HOME"
|
||||
exit 1
|
||||
fi
|
||||
local runuser chown touser botname DEBUG="$1"
|
||||
# upgrade from old version
|
||||
# currently no action
|
||||
printf "Check for Update actions ...\n"
|
||||
printf "Done.\n"
|
||||
# load addons on startup
|
||||
printf "Initialize modules and addons ...\n"
|
||||
for addons in "${ADDONDIR:-.}"/*.sh ; do
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
[ -r "${addons}" ] && source "${addons}" "init" "${DEBUG}"
|
||||
done
|
||||
printf "Done.\n"
|
||||
# ask for bashbot user
|
||||
# shellcheck disable=SC2153
|
||||
runuser="${RUNUSER}"; [ "${UID}" = "0" ] && runuser="nobody"
|
||||
printf "Enter User to run bashbot [${runuser}]: "
|
||||
read -r chown
|
||||
[ -z "${chown}" ] && chown="${runuser}"; touser="${chown%:*}"
|
||||
# check user ...
|
||||
if ! id "${touser}" &>/dev/null; then
|
||||
printf "${RED}User \"${touser}\" does not exist!${NN}"
|
||||
exit 3
|
||||
elif [[ "${UID}" != "0" && "${touser}" != "${runuser}" ]]; then
|
||||
# different user but not root ...
|
||||
printf "${ORANGE}You are not root, adjusting permissions may fail. Try \"sudo ./bashbot.sh init\"${NN}Press <CTRL+C> to stop or <Enter> to continue..." 1>&2
|
||||
[ -n "${INTERACTIVE}" ] && read -r runuser
|
||||
fi
|
||||
# check if mycommands exist
|
||||
if [ ! -r "${BASHBOT_ETC:-.}/mycommands.sh" ]; then
|
||||
printf "Mycommands.sh not found, copy ${GREY}<C>lean file, <E>xamples or <N>one${NC} to mycommands.sh? (c/e/N) N\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[cC] ]] && cp -f "${BASHBOT_ETC:-.}/mycommands.sh.clean" "${BASHBOT_ETC:-.}/mycommands.sh"
|
||||
[[ "${ANSWER}" =~ ^[eE] ]] && cp -f "${BASHBOT_ETC:-.}/mycommands.sh.dist" "${BASHBOT_ETC:-.}/mycommands.sh"
|
||||
# offer to copy config also
|
||||
if [ ! -r "${BASHBOT_ETC:-.}/mycommands.conf" ]; then
|
||||
printf "Mycommands config file not found, copy ${GREY}mycommands.conf.dist${NC} to mycommands.conf? (Y/n) Y\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[nN] ]] || cp -f "${BASHBOT_ETC:-.}/mycommands.conf.dist" "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
fi
|
||||
# adjust INLINE CALLBACK MEONLY SILENCER
|
||||
if [ -w "${BASHBOT_ETC:-.}/mycommands.conf" ]; then
|
||||
printf "Activate processing for ${GREY}<I>nline queries, <C>allback buttons, <B>oth or <N>one${NC} in mycommands.sh? (i/c/b/N) N\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[iIbB] ]] && sed -i '/INLINE="/ s/^.*$/export INLINE="1"/' "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
[[ "${ANSWER}" =~ ^[cCbB] ]] && sed -i '/CALLBACK="/ s/^.*$/export CALLBACK="1"/' "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
printf "Always ignore commands for other Bots in chat ${GREY}(/cmd@other_bot)${NC}? (y/N) N\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[yY] ]] && sed -i '/MEONLY="/ s/^.*$/export MEONLY="1"/' "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
printf "Delete administrative messages in chats ${GREY}(pinned, user join/leave, ...)${NC}? (y/N) N\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[yY] ]] && sed -i '/SILENCER="/ s/^.*$/export SILENCER="yes"/' "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
fi
|
||||
printf "Done.\n"
|
||||
fi
|
||||
# adjust permissions
|
||||
printf "Adjusting files and permissions for user \"${touser}\" ...\n"
|
||||
chmod 711 .
|
||||
chmod -R o-w ./*
|
||||
chmod -R u+w "${COUNTFILE}"* "${BLOCKEDFILE}"* "${DATADIR}" logs "${LOGDIR}/"*.log 2>/dev/null
|
||||
chmod -R o-r,o-w "${COUNTFILE}"* "${BLOCKEDFILE}"* "${DATADIR}" "${BOTACL}" 2>/dev/null
|
||||
# jsshDB must writeable by owner
|
||||
find . -name '*.jssh*' -exec chmod u+w \{\} +
|
||||
chown -Rf "${chown}" . ./*
|
||||
printf "Done.\n"
|
||||
# adjust values in bashbot.rc
|
||||
if [ -w "bashbot.rc" ]; then
|
||||
printf "Adjust user and botname in bashbot.rc ...\n"
|
||||
sed -i '/^[# ]*runas=/ s|runas=.*$|runas="'"${touser}"'"|' "bashbot.rc"
|
||||
sed -i '/^[# ]*bashbot=/ s|bashbot=.*$|bashbot="cd '"${PWD}"'; '"${PWD}"'/'"${0##*/}"'"|' "bashbot.rc"
|
||||
botname="$(getConfigKey "botname")"
|
||||
[ -n "${botname}" ] && sed -i '/^[# ]*name=/ s|name=.*$|name="'"${botname}"'"|' "bashbot.rc"
|
||||
printf "Done.\n"
|
||||
fi
|
||||
# ask to check bottoken online
|
||||
if [ -z "$(getConfigKey "botid")" ]; then
|
||||
printf "Seems to be your first init. Should I verify your bot token online? (y/N) N\b"
|
||||
read -r ANSWER
|
||||
if [[ "${ANSWER}" =~ ^[Yy] ]]; then
|
||||
printf "${GREEN}Contacting telegram to verify your bot token ...${NN}"
|
||||
$0 botname
|
||||
fi
|
||||
fi
|
||||
# check if botconf seems valid
|
||||
printf "${GREEN}This is your bot config:${NN}${GREY}"
|
||||
sed 's/^/\t/' "${BOTCONFIG}.jssh" | grep -vF '["bot_config_key"]'; printf "${NC}"
|
||||
if check_token "$(getConfigKey "bottoken")" && [[ "$(getConfigKey "botadmin")" =~ ^[${o9o9o9}]+$ ]]; then
|
||||
printf "Bot config seems to be valid. Should I make a backup copy? (Y/n) Y\b"
|
||||
read -r ANSWER
|
||||
if [[ -z "${ANSWER}" || "${ANSWER}" =~ ^[^Nn] ]]; then
|
||||
printf "Copy bot config to ${BOTCONFIG}.jssh.ok ...\n"
|
||||
cp "${BOTCONFIG}.jssh" "${BOTCONFIG}.jssh.ok"
|
||||
fi
|
||||
else
|
||||
printf "${ORANGE}Bot config may incomplete, pls check.${NN}"
|
||||
fi
|
||||
# show result
|
||||
printf "${GREY}"; ls -ldp "${DATADIR}" "${LOGDIR}" ./*.jssh* ./*.sh ./*.conf 2>/dev/null; printf "${NC}"
|
||||
_exec_if_function my_init
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/bashbot_stats.sh
|
||||
@ -16,25 +17,12 @@ USAGE='bashbot_stats.sh [-h|--help] [debug]'
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 23.12.2020 20:34
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
case "$1" in
|
||||
"-h"*)
|
||||
printf "usage: %s\n" "${USAGE}"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$1"
|
||||
[ -n "$1" ] && print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/delete_message.sh
|
||||
@ -19,32 +20,17 @@ USAGE='delete_message.sh [-h|--help] "CHAT[ID]" "MESSAGE[ID]" [debug]'
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 03.01.2021 15:37
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
DELETE="delete_message"
|
||||
case "$1" in
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: %s\n' "${USAGE}"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
@ -59,5 +45,4 @@ fi
|
||||
[ "${BOTSENT[OK]}" = "true" ] && BOTSENT[ID]="$2"
|
||||
|
||||
# output send message result
|
||||
jssh_printDB "BOTSENT" | sort -r
|
||||
|
||||
print_result
|
||||
|
54
bin/edit_buttons.sh
Executable file
54
bin/edit_buttons.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/edit_buttons.sh
|
||||
#
|
||||
USAGE='send_message.sh [-h|--help] "CHAT[ID]" "MESSAGE[ID]" "text|url" ...'
|
||||
#
|
||||
# DESCRIPTION: send a send buttons in a row to the given user/group
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# MESSAGE[ID] - ID of MESSAGE with buttons to edit
|
||||
# text|url - buttons to send, each button as "text|url" pair or
|
||||
# "url" only to show url as text also, "" starts new row
|
||||
# "url" not http(s):// or tg:// is sent as callback_data
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# EXAMPLE: 2 buttons on 2 rows, first shows Amazon, second the url as text
|
||||
# send_buttons.sh "Amazon|https://www.amazon.com" "" "https://mydealz.de" ...
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 21.01.2021 08:10
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="edit_inline_keyboard"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug"
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOT_ADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
MESSAGE_ID="$2"
|
||||
shift 2
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "${MESSAGE_ID}" "$(_button_row "$@")"
|
||||
|
||||
# output send message result
|
||||
print_result
|
67
bin/edit_message.sh
Executable file
67
bin/edit_message.sh
Executable file
@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/edit_message.sh
|
||||
#
|
||||
USAGE='send_edit_message.sh [-h|--help] [format|caption] "CHAT[ID]" "MESSAGE[ID]" "message ...." [debug]'
|
||||
#
|
||||
# DESCRIPTION: replace a message in the given user/group
|
||||
#
|
||||
# OPTIONS: format - normal, markdown, html or caption for file caption (optional)
|
||||
# CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# MESSAGE[ID] - message to replace
|
||||
# message - message to send in specified format
|
||||
# if no format is given send_normal_message() format is used
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 23.12.2020 16:52
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="edit_normal_message"
|
||||
case "$1" in
|
||||
"nor"*|"tex"*)
|
||||
SEND="edit_normal_message"
|
||||
shift
|
||||
;;
|
||||
"mark"*)
|
||||
SEND="edit_markdownv2_message"
|
||||
shift
|
||||
;;
|
||||
"htm"*)
|
||||
SEND="edit_html_message"
|
||||
shift
|
||||
;;
|
||||
"cap"*)
|
||||
SEND="edit_message_caption"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${4:-debug}" # $4 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOT_ADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "$2" "$3"
|
||||
|
||||
# output send message result
|
||||
print_result
|
47
bin/kickban_user.sh
Executable file
47
bin/kickban_user.sh
Executable file
@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/kickban_user.sh
|
||||
#
|
||||
USAGE='kickban_user.sh [-h|--help] [-u|--unban] "CHAT[ID]" "USER[ID]" [debug]'
|
||||
#
|
||||
# DESCRIPTION: kickban or unban a user from the given group
|
||||
#
|
||||
# OPTIONS: -u | --unban - unban user
|
||||
# CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# USER[ID] - user to (un)ban
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 25.01.2021 20:34
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
BAN="kick_chat_member"
|
||||
case "$1" in
|
||||
"-u"|"--unban")
|
||||
BAN="unban_chat_member"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
# send message in selected format
|
||||
"${BAN}" "$1" "$2"
|
||||
|
||||
# output send message result
|
||||
print_result
|
42
bin/process_update.sh
Executable file
42
bin/process_update.sh
Executable file
@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034,SC2059
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/process_update.sh
|
||||
#
|
||||
USAGE='process_update.sh [-h|--help] [debug] [<file]'
|
||||
#
|
||||
# DESCRIPTION: processes ONE telegram update read from stdin, e.g. form file or webhook
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 30.01.2021 19:14
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
COMMAND="process_update"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
|
||||
print_help "${1:-nix}"
|
||||
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
# read json from stdin and convert update format
|
||||
json='{"result": ['"$(cat)"']}'
|
||||
UPDATE="$(${JSONSHFILE} -b -n <<<"${json}" 2>/dev/null)"
|
||||
|
||||
# assign to bashbot ARRAY
|
||||
Json2Array 'UPD' <<<"${UPDATE}"
|
||||
|
||||
# process telegram update
|
||||
"${COMMAND}" "0" "$1"
|
||||
|
46
bin/promote_user.sh
Executable file
46
bin/promote_user.sh
Executable file
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/promote_user.sh
|
||||
#
|
||||
USAGE='promote_user.sh [-h|--help] "CHAT[ID]" "USER[ID]" "right[:true|false]" ..'
|
||||
#
|
||||
# DESCRIPTION: promote / denote user rights in given group
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# USER[ID] - user to (un)ban
|
||||
# rights[:true|false] - rights to grant in long or short form,
|
||||
# followed by :true to grant or :false to renove
|
||||
# long: is_anonymous can_change_info can_post_messages can_edit_messages
|
||||
# can_delete_messages can_invite_users can_restrict_members
|
||||
# can_pin_messages can_promote_member`
|
||||
# short: anon change post edit delete invite restrict pin promote
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 25.01.2021 22:34
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
PROMOTE="promote_chat_member"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
# send message in selected format
|
||||
"${PROMOTE}" "$@"
|
||||
|
||||
# output send message result
|
||||
print_result
|
@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2059
|
||||
#
|
||||
@ -27,7 +28,7 @@ USAGE='broadcast_message.sh [-h|--help] [--doit] [--groups|--both|--db=file] [fo
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 16.12.2020 16:14
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
@ -75,23 +76,11 @@ case "$1" in
|
||||
SEND="send_html_message"
|
||||
shift
|
||||
;;
|
||||
'')
|
||||
printf "missing missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: %s\n' "${USAGE}"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n -e '/# shellcheck /d' -e '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$2" # $3 debug
|
||||
|
||||
print_help "$1"
|
||||
|
||||
# read in users from given DB or count.jssh
|
||||
database="${USERDB:-${COUNTFILE}}"
|
||||
|
54
bin/send_buttons.sh
Executable file
54
bin/send_buttons.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_message.sh
|
||||
#
|
||||
USAGE='send_message.sh [-h|--help] "CHAT[ID]" "message" "text|url" ...'
|
||||
#
|
||||
# DESCRIPTION: send a send buttons in a row to the given user/group
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# message - message to send
|
||||
# text|url - buttons to send, each button as "text|url" pair or
|
||||
# "url" not http(s):// or tg:// is sent as callback_data
|
||||
# "url" only to show url as text also, "" starts new row
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# EXAMPLE: 2 buttons on 2 rows, first shows Amazon, second the url as text
|
||||
# send_buttons.sh "Amazon|https://www.amazon.com" "" "https://mydealz.de" ...
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 18.01.2021 11:34
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="send_inline_keyboard"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug"
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOT_ADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
MESSAGE="$2"
|
||||
shift 2
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "${MESSAGE}" "$(_button_row "$@")"
|
||||
|
||||
# output send message result
|
||||
print_result
|
@ -1,79 +0,0 @@
|
||||
#!/bin/bash
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_message.sh
|
||||
#
|
||||
USAGE='send_edit_message.sh [-h|--help] [format|caption] "CHAT[ID]" "MESSAGE[ID]" "message ...." [debug]'
|
||||
#
|
||||
# DESCRIPTION: replace a message in the given user/group
|
||||
#
|
||||
# OPTIONS: format - normal, markdown, html or caption for file caption (optional)
|
||||
# CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# MESSAGE[ID] - message to replace
|
||||
# message - message to send in specified format
|
||||
# if no format is given send_normal_message() format is used
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 23.12.2020 16:52
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="edit_normal_message"
|
||||
case "$1" in
|
||||
"nor"*|"tex"*)
|
||||
SEND="edit_normal_message"
|
||||
shift
|
||||
;;
|
||||
"mark"*)
|
||||
SEND="edit_markdownv2_message"
|
||||
shift
|
||||
;;
|
||||
"htm"*)
|
||||
SEND="edit_html_message"
|
||||
shift
|
||||
;;
|
||||
"cap"*)
|
||||
SEND="edit_message_caption"
|
||||
shift
|
||||
;;
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: %s\n' "${USAGE}"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${4:-debug}" # $4 debug
|
||||
|
||||
####
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOT_ADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "$2" "$3"
|
||||
|
||||
# output send message result
|
||||
jssh_printDB "BOTSENT" | sort -r
|
||||
|
1
bin/send_edit_message.sh
Symbolic link
1
bin/send_edit_message.sh
Symbolic link
@ -0,0 +1 @@
|
||||
edit_message.sh
|
@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_file.sh
|
||||
@ -24,29 +25,16 @@ USAGE='send_file.sh [-h|--help] "CHAT[ID]" "file|URL" "caption ...." [type] [deb
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 25.12.2020 20:24
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="send_file"
|
||||
case "$1" in
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: %s\n' "${USAGE}"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${5:-debug}" # $5 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
@ -64,5 +52,4 @@ FILE="$2"
|
||||
"${SEND}" "${CHAT}" "${FILE}" "$3" "$4"
|
||||
|
||||
# output send message result
|
||||
jssh_printDB "BOTSENT" | sort -r
|
||||
|
||||
print_result
|
||||
|
@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_message.sh
|
||||
@ -21,7 +22,7 @@ USAGE='send_message.sh [-h|--help] [format] "CHAT[ID]" "message ...." [debug]'
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 16.12.2020 11:34
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
@ -40,22 +41,11 @@ case "$1" in
|
||||
SEND="send_html_message"
|
||||
shift
|
||||
;;
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: %s\n' "${USAGE}"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
@ -69,5 +59,4 @@ fi
|
||||
"${SEND}" "${CHAT}" "$2"
|
||||
|
||||
# output send message result
|
||||
jssh_printDB "BOTSENT" | sort -r
|
||||
|
||||
print_result
|
||||
|
27
commands.sh
27
commands.sh
@ -8,14 +8,14 @@
|
||||
# | |__/ / |_| | | | | | |_| | |__ | |____( (_| | | |__ _
|
||||
# |_____/ \___/ |_| |_|\___/ \___) |_______)____|_|\___)_|
|
||||
#
|
||||
# this file *MUST* not be edited! place your config and commands in
|
||||
# the file "mycommands.sh". a clean version is provided as "mycommands.sh.clean"
|
||||
# this file *MUST* not edited! place your config in the file "mycommands.conf"
|
||||
# and commands in "mycommands.sh", a clean version is provided as "mycommands.sh.clean"
|
||||
#
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#
|
||||
|
||||
# bashbot locale defaults to c.UTF-8, adjust locale in mycommands.sh if needed
|
||||
@ -66,6 +66,7 @@ fi
|
||||
# copy "mycommands.sh.dist" to "mycommands.sh" and change the values there
|
||||
# defaults to no inline, all commands and nonsense home dir
|
||||
export INLINE="0"
|
||||
export CALLBACK="0"
|
||||
export MEONLY="0"
|
||||
export FILE_REGEX="${BASHBOT_ETC}/.*"
|
||||
|
||||
@ -76,14 +77,18 @@ export FILE_REGEX="${BASHBOT_ETC}/.*"
|
||||
|
||||
|
||||
if [ -z "$1" ] || [[ "$1" == *"debug"* ]];then
|
||||
# detect inline commands....
|
||||
# no default commands, all processing is done in myinlines()
|
||||
if [ "${INLINE}" != "0" ] && [ -n "${iQUERY[ID]}" ]; then
|
||||
# forward iinline query to optional dispatcher
|
||||
_exec_if_function myinlines
|
||||
#################
|
||||
# detect inline and callback query
|
||||
if [ -n "${iQUERY[ID]}" ]; then
|
||||
# forward inline query to optional dispatcher
|
||||
[ "${INLINE:-0}" != "0" ] && _exec_if_function myinlines
|
||||
|
||||
# regular (global) commands ...
|
||||
# your commands are in mycommands()
|
||||
elif [ -n "${iBUTTON[ID]}" ]; then
|
||||
# forward inline query to optional dispatcher
|
||||
[ "${CALLBACK:-0}" != "0" ] && _exec_if_function mycallbacks
|
||||
|
||||
#################
|
||||
# regular command
|
||||
else
|
||||
|
||||
###################
|
||||
@ -127,7 +132,7 @@ if [ -z "$1" ] || [[ "$1" == *"debug"* ]];then
|
||||
'/help'*)
|
||||
send_markdown_message "${CHAT[ID]}" "${bashbot_help}"
|
||||
;;
|
||||
'/leavechat'*) # bot leave chat if user is admin in chat
|
||||
'/leavechat'*) # bot leave chat if user is admin in chat
|
||||
if user_is_admin "${CHAT[ID]}" "${USER[ID]}" || user_is_allowed "${USER[ID]}" "leave" ; then
|
||||
send_markdown_message "${CHAT[ID]}" "*LEAVING CHAT...*"
|
||||
leave_chat "${CHAT[ID]}"
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Description: run all tests, exit after failed test
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#############################################################
|
||||
|
||||
#shellcheck disable=SC1090
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Description: common stuff for all dev scripts
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#############################################################
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
@ -20,3 +20,5 @@ else
|
||||
printf "Sorry, no git repository %s\n" "$(pwd)" && exit 1
|
||||
fi
|
||||
|
||||
HOOKDIR="dev/hooks"
|
||||
LASTCOMMIT=".git/.lastcommit"
|
||||
|
@ -3,15 +3,21 @@
|
||||
#
|
||||
# works together with git pre-push.sh and ADD all changed files since last push
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
[ ! -f .git/.lastcommit ] && printf "No previous commit or hooks not installed, use \"git add\" instead ... Abort\n" && exit
|
||||
# check for last commit date
|
||||
if [ ! -f "${LASTCOMMIT}" ]; then
|
||||
if ! touch -d "$(git log -1 --format=%cD)" "${LASTCOMMIT}"; then
|
||||
printf "No previous commit found, use \"git add\" instead ... Abort\n"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
set +f
|
||||
FILES="$(find ./* -newer .git/.lastcommit| grep -v -e 'DIST\/' -e 'STANDALONE\/' -e 'JSON.sh')"
|
||||
FILES="$(find ./* -newer "${LASTCOMMIT}" | grep -v -e 'DIST\/' -e 'STANDALONE\/' -e 'JSON.sh')"
|
||||
set -f
|
||||
# FILES="$(find ./* -newer .git/.lastpush)"
|
||||
[ "${FILES}" = "" ] && printf "Nothing changed since last commit ...\n" && exit
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
############
|
||||
# NOTE: you MUST run install-hooks.sh again when updating this file!
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
############
|
||||
# NOTE: you MUST run install-hooks.sh again when updating this file!
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
############
|
||||
# NOTE: you MUST run install-hooks.sh again when updating this file!
|
||||
|
@ -7,7 +7,7 @@
|
||||
#
|
||||
# Usage: source inject-json.sh
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
##############################################################
|
||||
|
||||
# download JSON.sh
|
||||
|
@ -1,13 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# this has to run once atfer git clone
|
||||
# and every time we create new hooks
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
HOOKDIR="dev/hooks"
|
||||
|
||||
printf "Installing hooks..."
|
||||
for hook in pre-commit post-commit pre-push
|
||||
do
|
||||
|
@ -7,7 +7,7 @@
|
||||
#
|
||||
# Options: --notest - skip tests
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
##############################################################
|
||||
|
||||
#shellcheck disable=SC1090
|
||||
|
@ -1,7 +1,9 @@
|
||||
data-bot-bash/*
|
||||
webhook-fifo
|
||||
JSON.awk
|
||||
bashbot.rc
|
||||
mycommands.sh
|
||||
mycommands.conf
|
||||
awk-patch.sh
|
||||
*.jssh*
|
||||
botacl
|
||||
|
@ -7,7 +7,7 @@
|
||||
#
|
||||
# Usage: source make-hmtl
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
##############################################################
|
||||
|
||||
# check for correct dir
|
||||
|
@ -11,7 +11,7 @@
|
||||
# If you your bot is finished you can use make-standalone.sh to create the
|
||||
# the old all-in-one bashbot: bashbot.sh and commands.sh only!
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
###################################################################
|
||||
|
||||
#shellcheck disable=SC1090
|
||||
@ -73,13 +73,14 @@ printf "\n... create unified bashbot.sh\n"
|
||||
# first head of bashbot.sh
|
||||
sed -n '0,/for module in/ p' bashbot.sh | head -n -3
|
||||
|
||||
# then mycommands from first non comment line on
|
||||
# then modules without shebang
|
||||
printf '\n##############################\n# bashbot modules starts here ...\n'
|
||||
cat modules/*.sh | sed -e 's/^#\!\/bin\/bash.*//'
|
||||
# shellcheck disable=SC2016
|
||||
cat modules/*.sh | sed -e 's/^#\!\/bin\/bash.*//' -e '/^#.*\$\$VERSION\$\$/d'
|
||||
|
||||
# last tail of commands.sh
|
||||
printf '\n##############################\n# bashbot internal functions starts here ...\n\n'
|
||||
sed -n '/BASHBOT INTERNAL functions/,$ p' bashbot.sh
|
||||
# last remaining commands.sh
|
||||
printf '\n##############################\n'
|
||||
sed -n '/^# read commands file/,$ p' bashbot.sh
|
||||
|
||||
} >>$$bashbot.sh
|
||||
|
||||
@ -90,11 +91,11 @@ rm -rf modules
|
||||
|
||||
printf "Create minimized Version of bashbot.sh and commands.sh\n"
|
||||
# shellcheck disable=SC2016
|
||||
sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e 's/^[[:space:]]*//' -e '/^$/d' -e 'N;s/\\\n/ /;P;D' bashbot.sh |\
|
||||
sed 'N;s/\\\n/ /;P;D' > bashbot.sh.min
|
||||
sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e '/shellcheck/! s/\t+#.*//' -e 's/^[[:space:]]*//'\
|
||||
-e '/^$/d' bashbot.sh | sed 'N;s/\\\n/ /;P;D' | sed 'N;s/\\\n/ /;P;D' > bashbot.sh.min
|
||||
# shellcheck disable=SC2016
|
||||
sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e 's/^[[:space:]]*//' -e 's/\)[[:space:]]+#.*/)/' -e '/^$/d' commands.sh |\
|
||||
sed 'N;s/\\\n/ /;P;D' > commands.sh.min
|
||||
sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e '/shellcheck/! s/\t+#.*//' -e 's/^[[:space:]]*//'\
|
||||
-e '/^$/d' commands.sh | sed 'N;s/\\\n/ /;P;D' > commands.sh.min
|
||||
chmod +x bashbot.sh.min
|
||||
|
||||
# make html doc
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# joke hack to obfuscate bashbot.min.sh
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
# shellcheck disable=SC2028,SC2016,SC1117
|
||||
|
||||
infile="bashbot.sh"
|
||||
|
@ -1,4 +1,5 @@
|
||||
# list of additional files to check from shellcheck
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
bashbot.rc
|
||||
mycommands.conf
|
||||
mycommands.sh.clean
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
# shellcheck disable=SC2016
|
||||
#
|
||||
# Easy Versioning in git:
|
||||
@ -43,7 +43,8 @@ unset IFS
|
||||
VERSION="$(git describe --tags --long)"
|
||||
printf "Update to version %s ...\n" "${VERSION}"
|
||||
|
||||
FILES="$(find ./*)"
|
||||
# only regular files, ignore .dot files/dirs, e.g. .git .gitinore in BASEDIR
|
||||
FILES="$(find ./* -type f)"
|
||||
[ "$1" != "" ] && FILES="$*"
|
||||
|
||||
# autogenerate REMADME.html REMADE.txt
|
||||
@ -53,7 +54,7 @@ if [[ "${FILES}" == *"README.md"* ]]; then
|
||||
cat "doc/bashbot.ascii" >"README.txt"
|
||||
if [ -r "README.html" ] && type -f html2text >/dev/null; then
|
||||
# convert html links to text [link]
|
||||
sed -E 's/<a href="([^>]+)">([^<#]+)<\/a>/\2 [\1]/' <README.html |\
|
||||
sed -E 's/<a href="([^>]+)">([^<#]+)<\/a>/\2 [\1]/g' <README.html |\
|
||||
html2text -style pretty -width 90 - >>README.txt
|
||||
else
|
||||
type -f fold >/dev/null && fold -s -w 90 README.md >>README.txt
|
||||
@ -63,7 +64,8 @@ fi
|
||||
# change version string in given files
|
||||
for file in ${FILES}
|
||||
do
|
||||
[ ! -f "${file}" ] && continue
|
||||
# symlink is a file :-(
|
||||
[[ -L "${file}" || ! -f "${file}" ]] && continue
|
||||
#[ "${file}" == "version" ] && continue
|
||||
printf "%s" " ${file}" >&2
|
||||
sed -i 's/^#### $$VERSION$$.*/#### \$\$VERSION\$\$ '"${VERSION}"'/' "${file}"
|
||||
|
@ -132,5 +132,5 @@ You must update to [Version 1.20](https://github.com/topkecleon/telegram-bot-bas
|
||||
|
||||
#### [Next Create Bot](1_firstbot.md)
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
@ -65,5 +65,5 @@ group. This step is up to you actually.
|
||||
#### [Prev Installation](0_install.md)
|
||||
#### [Next Getting started](2_usage.md)
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
@ -33,14 +33,19 @@ Have FUN!
|
||||
├── JSON.sh # bashbots JSON parser, see https://github.com/dominictarr/JSON.sh
|
||||
│
|
||||
├── bin # ready to use scripts, use `scriptname --help` for help
|
||||
│ ├── bashbot_stats.sh # does what it says ...
|
||||
│ ├── send_broadcast.sh # send message to all known chats
|
||||
│ ├── send_message.sh # send message to given chat
|
||||
│ ├── edit_message.sh # replace given message id in given chat
|
||||
│ ├── delete_message.sh # delete given message id in given chat
|
||||
│ ├── send_broadcast.sh # send message to all known chats
|
||||
│ ├── send_file.sh # send file to given chat
|
||||
│ ├── bashbot_stats.sh # does what it says ...
|
||||
│ ├── delete_message.sh # delete given message id in given chat
|
||||
│ ├── send_buttons.sh # send message with attached button
|
||||
│ ├── edit_buttons.sh # attach/edit message buttons
|
||||
│ ├── kickban_user.sh # kick/unban user from given chat
|
||||
│ ├── promote_user.sh # promote/dente user rights in given chat
|
||||
│ │
|
||||
│ └── bashbot_env.inc.sh # bashbot location included from scripts, adapt if needed
|
||||
│ └── bashbot_env.inc.sh # sourced from scripts, adapt locations if needed
|
||||
│ └── bashbot_init.inc.sh # sourced from bashbot.sh init
|
||||
│
|
||||
├── scripts # place your bashbot interactive and background scripts here
|
||||
│ └── interactive.sh.clean # interactive script template for new scripts
|
||||
@ -91,6 +96,7 @@ Start or Stop your Bot use the following commands:
|
||||
```
|
||||
|
||||
### Scripts in bin/
|
||||
Use `script.sh -h` or `script --help` to get short/long help for script.
|
||||
|
||||
To count the total number of users and messages run the following command:
|
||||
|
||||
@ -244,8 +250,7 @@ e.g. if a new user joins a chat MESSAGE is set to "/_new_chat_user".
|
||||
|
||||
|
||||
### Inline query messages
|
||||
|
||||
Inline query messages are small, non regular messages used for interaction with the user,
|
||||
Inline query messages are special messages used for interaction with the user,
|
||||
they contain the following variables only:
|
||||
|
||||
* `${iQUERY}`: Current inline query
|
||||
@ -256,6 +261,22 @@ they contain the following variables only:
|
||||
* `${iQUERY[LAST_NAME]}`: User's last name
|
||||
|
||||
|
||||
### Callback button messages
|
||||
Callback button messages special messages swedn from callback buttons,
|
||||
they contain the following variables only:
|
||||
|
||||
* `$iBUTTON`: This array contains the ID, First name, last name, username and user id of the user clicked on the button
|
||||
* `${iBUTTON[ID]}`: Callback query ID
|
||||
* `${iBUTTON[DATA]`: Data attached to button, hopefully unique
|
||||
* `${iBUTTON[CHAT_ID]`: Chat where button was pressed
|
||||
* `${iBUTTON[MESSAGE_ID]`: Message to which button is attached
|
||||
* `${iBUTTON[MESSAGE]`: Text of message
|
||||
* `${iBUTTON[USER_ID]}`: User's id
|
||||
* `${iBUTTON[FIRST_NAME]}`: User's first name
|
||||
* `${iBUTTON[LAST_NAME]}`: User's last name
|
||||
* `${iBUTTON[USERNAME]}`: User's @username
|
||||
|
||||
|
||||
## Send data / get response
|
||||
|
||||
After every `send_xxx` `get_xxx` call the array BOTSENT contains the most important values from Telegram response.
|
||||
@ -274,7 +295,7 @@ In case you need other response values , the array `UPD` contains complete Teleg
|
||||
## Usage of bashbot functions
|
||||
|
||||
#### sending messages
|
||||
To send messages use the `send_xxx_message`functions.
|
||||
To send messages use the `send_xxx_message` functions.
|
||||
To insert line brakes in a message place `\n` in the text.
|
||||
|
||||
To send regular text without any markdown use:
|
||||
@ -290,7 +311,7 @@ To send text with html:
|
||||
send_html_message "${CHAT[ID]}" "lol <b>bold</b>"
|
||||
```
|
||||
|
||||
To forward messages use the `forward`function:
|
||||
To forward messages use the `forward` function:
|
||||
```bash
|
||||
forward "${CHAT[ID]}" "from_chat_id" "message_id"
|
||||
```
|
||||
@ -328,20 +349,20 @@ To send local files or URL's (photo, video, voice, sticker, documents) use the `
|
||||
send_file "${CHAT[ID]}" "/home/user/dog.jpg" "Lool" "photo"
|
||||
send_file "${CHAT[ID]}" "https://images-na.ssl-images-amazon.com/images/I/81DQ0FpoSNL._AC_SL1500_.jpg"
|
||||
```
|
||||
To send custom keyboards use the `send_keyboard`function:
|
||||
To send custom keyboards use the `send_keyboard` function:
|
||||
```bash
|
||||
send_keyboard "${CHAT[ID]}" "Text that will appear in chat?" '[ "Yep" , "No" ]' # note the single quotes!
|
||||
send_keyboard "${CHAT[ID]}" "Text that will appear in chat?" "[ \\"Yep\\" , \\"No\\" ]" # within double quotes you must escape the inside double quots
|
||||
```
|
||||
To send locations use the `send_location`function:
|
||||
To send locations use the `send_location` function:
|
||||
```bash
|
||||
send_location "${CHAT[ID]}" "Latitude" "Longitude"
|
||||
```
|
||||
To send venues use the `send_venue`function:
|
||||
To send venues use the `send_venue` function:
|
||||
```bash
|
||||
send_venue "${CHAT[ID]}" "Latitude" "Longitude" "Title" "Address" "optional foursquare id"
|
||||
```
|
||||
To send a chat action use the `send_action`function.
|
||||
To send a chat action use the `send_action` function.
|
||||
Allowed values: typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_audio or upload_audio for audio files, upload_document for general files, find_location for locations.
|
||||
```bash
|
||||
send_action "${CHAT[ID]}" "action"
|
||||
@ -351,5 +372,5 @@ send_action "${CHAT[ID]}" "action"
|
||||
#### [Prev Create Bot](1_firstbot.md)
|
||||
#### [Next Advanced Usage](3_advanced.md)
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
@ -144,7 +144,7 @@ echo "Text that will appear in one message \nwith this text on a new line"
|
||||
```
|
||||
|
||||
In case you want extend a message already containing a location, a file, a keyboard etc.,
|
||||
with an additionial text simply add ` mytextstartshere additional text`at the end of the string:
|
||||
with an additionial text simply add ` mytextstartshere additional text` at the end of the string:
|
||||
```bash
|
||||
out="Text that will appear mylatstartshere 45 mylongstartshere 45"
|
||||
[[ "$out" != *'in chat'* ]] && out="$out mytextstartshere in chat."
|
||||
@ -190,7 +190,7 @@ Note: Background jobs run independent from main bot and continue running until y
|
||||
|
||||
In order to enable **inline mode**, send `/setinline` command to [@BotFather](https://telegram.me/botfather) and provide the placeholder text that the user will see in the input field after typing your bot’s name.
|
||||
|
||||
The following commands allows you to send ansers to *inline queries*. To enable bashbot to process inline queries set `INLINE="1"`in 'mycommands.sh'.
|
||||
The following commands allows you to send ansers to *inline queries*. To enable bashbot to process inline queries set `INLINE="1"` in `mycommands.sh`.
|
||||
|
||||
To send messages or links through an *inline query*:
|
||||
```bash
|
||||
@ -258,7 +258,7 @@ By default you don't have to care about retry, as bashbot resend the message aft
|
||||
Only if the retry fails also an error is returned. The downside is that send_message functions will wait until resend is done.
|
||||
|
||||
If you want to disable automatic error processing and handle all errors manually (or don't care)
|
||||
set `BASHBOT_RETRY`to any no zero value.
|
||||
set `BASHBOT_RETRY` to any no zero value.
|
||||
|
||||
[Telegram Bot API error codes](https://github.com/TelegramBotAPI/errors)
|
||||
|
||||
@ -266,9 +266,9 @@ set `BASHBOT_RETRY`to any no zero value.
|
||||
#### Detect bot blocked
|
||||
|
||||
If the we can't connect to telegram, e.g. blocked from telegram server but also any other reason,
|
||||
bashbot set `BOTSENT[ERROR]`to `999`.
|
||||
bashbot set `BOTSENT[ERROR]` to `999`.
|
||||
|
||||
To get a notification on every connection problem create a function named `bashbotBlockRecover`and handle blocks there.
|
||||
To get a notification on every connection problem create a function named `bashbotBlockRecover` and handle blocks there.
|
||||
If the function returns true (0 or no value) bashbot will retry once and then return to the calling function.
|
||||
In case you return any non 0 value bashbot will return to the calling function without retry.
|
||||
|
||||
@ -302,5 +302,5 @@ Note: If you disable automatic retry, se above, you disable also connection prob
|
||||
#### [Prev Getting started](2_usage.md)
|
||||
#### [Next Expert Use](4_expert.md)
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
@ -434,5 +434,5 @@ for every poll until the maximum of BASHBOT_SLEEP ms.
|
||||
#### [Prev Advanced Use](3_advanced.md)
|
||||
#### [Next Best Practice](5_practice.md)
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
@ -12,7 +12,7 @@ If you don't have a github account, it may time to [setup a free account now](ht
|
||||
### Add commands to mycommands.sh only
|
||||
Do not change `bashbot.sh` and `commands.sh`, instead place your commands in to `mycommands.sh`.
|
||||
To start with a clean/minimal bot copy `mycommands.sh.clean` to `mycommands.sh` and start editing
|
||||
the message strings and place commands in the`case ... esac` block of the function mycommands():
|
||||
the message strings and place commands in the` case ... esac` block of the function mycommands():
|
||||
```bash
|
||||
# file: mycommands.sh
|
||||
# your additional bashbot commands
|
||||
@ -160,5 +160,5 @@ The second warning is about an unused variable, this is true because in our exam
|
||||
#### [Prev Best Practice](5_practice.md)
|
||||
#### [Next Functions Reference](6_reference.md)
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
@ -8,7 +8,7 @@ To insert line brakes in a message or caption you can place `\n` in the text.
|
||||
##### send_action
|
||||
`send_action` shows users what your bot is currently doing.
|
||||
|
||||
*usage:* send_action "${CHAT[ID]}" "action"
|
||||
*usage:* send_action "CHAT[ID]" "action"
|
||||
|
||||
*"action":* `typing`, `upload_photo`, `record_video`, `upload_video`, `record_audio`, `upload_audio`, `upload_document`, `find_location`.
|
||||
|
||||
@ -23,7 +23,7 @@ send_action "${CHAT[ID]}" "record_audio"
|
||||
##### send_normal_message
|
||||
`send_normal_message` sends text only messages to the given chat.
|
||||
|
||||
*usage:* send_normal_message "${CHAT[ID]}" "message"
|
||||
*usage:* send_normal_message "CHAT[ID]" "message"
|
||||
|
||||
*alias:* _normal_message "message"
|
||||
|
||||
@ -41,7 +41,7 @@ has more formatting codes and is more robust, but incompatible with old telegram
|
||||
To send characters reserved for markdown v2 formatting, you must prefix them with `\` ( e.g. `\| \= \_ \*`).\
|
||||
*Hint*: If a message is not sent, have a look in `logs/ERROR.log`
|
||||
|
||||
*usage:* send_markdownv2_message "${CHAT[ID]}" "markdown message"
|
||||
*usage:* send_markdownv2_message "CHAT[ID]" "markdown message"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
@ -55,7 +55,7 @@ send_markdownv2_message "${CHAT[ID]}" "*bold* __underlined__ [text](link)"
|
||||
This is the old, legacy Telegram markdown style, retained for backward compatibility.
|
||||
It supports a [reduced set of Markdown](https://core.telegram.org/bots/api#markdown-style) only
|
||||
|
||||
*usage:* send_markdown_message "${CHAT[ID]}" "markdown message"
|
||||
*usage:* send_markdown_message "CHAT[ID]" "markdown message"
|
||||
|
||||
*alias:* _markdown "message"
|
||||
|
||||
@ -70,7 +70,7 @@ send_markdown_message "${CHAT[ID]}" "*bold* _italic_ [text](link)"
|
||||
`send_html_message` sends HTML style messages to the given chat.
|
||||
Telegram supports a [reduced set of HTML](https://core.telegram.org/bots/api#html-style) only
|
||||
|
||||
*usage:* send_html_message "${CHAT[ID]}" "html message"
|
||||
*usage:* send_html_message "CHAT[ID]" "html message"
|
||||
|
||||
*alias:* _html_message "message"
|
||||
|
||||
@ -96,7 +96,7 @@ See also [Text formatting options](https://core.telegram.org/bots/api#formatting
|
||||
##### delete_message
|
||||
A bot can only delete messages if he is admin of a Chat, if not he can delete his own messages only.
|
||||
|
||||
*usage:* delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
*usage:* delete_message "CHAT[ID]" "${MESSAGE[ID]}"
|
||||
|
||||
See also [deleteMessage limitations](https://core.telegram.org/bots/api#deletemessage)
|
||||
|
||||
@ -107,7 +107,7 @@ See also [deleteMessage limitations](https://core.telegram.org/bots/api#deleteme
|
||||
|
||||
The main use case for send_message is to process the output of interactive chats and background jobs. **For regular Bot commands I recommend using of the dedicated send_xxx_message() functions from above.**
|
||||
|
||||
*usage:* send_message "${CHAT[ID]}" "message"
|
||||
*usage:* send_message "CHAT[ID]" "message"
|
||||
|
||||
*example:* - see [Usage](2_usage.md#send_message) and [Advanced Usage](3_advanced.md#Interactive-Chats)
|
||||
|
||||
@ -118,7 +118,7 @@ The main use case for send_message is to process the output of interactive chats
|
||||
##### send_file
|
||||
send_file can send local files, URL's or file_id's as different filex types (_e.g. photo video sticker_)
|
||||
|
||||
*usage:* send_file "${CHAT[ID]}" "file/URL/file_id" "caption" ["type"]
|
||||
*usage:* send_file "CHAT[ID]" "file/URL/file_id" "caption" ["type"]
|
||||
|
||||
URL's must start with `http://` or `https://` and remote server must send an appropriate media type.
|
||||
A file_id must start with `file_id://`, all other file names are threated as local files.
|
||||
@ -158,7 +158,7 @@ send_file "${CHAT[ID]}" "dog.jpg" "My Dog"
|
||||
|
||||
##### send_album
|
||||
|
||||
*usage:* send_album "${CHAT[ID]}" "URL1" "URL2" ... "URLn"
|
||||
*usage:* send_album "CHAT[ID]" "URL1" "URL2" ... "URLn"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
@ -166,25 +166,27 @@ send_album "$(getConfigKey "botadmin")" "http://www.rrr.de/slider/main-image1.jp
|
||||
```
|
||||
|
||||
##### send_location
|
||||
*usage:* send_location "${CHAT[ID]}" "Latitude" "Longitude"
|
||||
*usage:* send_location "CHAT[ID]" "Latitude" "Longitude"
|
||||
|
||||
|
||||
##### send_venue
|
||||
*usage:* send_venue "${CHAT[ID]}" "Latitude" "Longitude" "Title" "Address" "foursquare id (optional)"
|
||||
*usage:* send_venue "CHAT[ID]" "Latitude" "Longitude" "Title" "Address" "foursquare id (optional)"
|
||||
|
||||
|
||||
##### send_sticker
|
||||
`send_sticker` sends a sticker using a `file_id` to send a sticker that exists on the Telegram servers.
|
||||
|
||||
*usage:* send_sticker "$CHAT[ID]" "file_id"
|
||||
|
||||
|
||||
----
|
||||
|
||||
##### send_keyboard
|
||||
Note: Since version 0.6 send_keyboard was changed to use native "JSON Array" notation as used from Telegram.
|
||||
Detection and emulation for old format will be removed after 1.0 release!
|
||||
`send_keyboard` sends a custom keyboard, Telegram clients will show it instead of the regular keyboard.
|
||||
If the user press a button on the custom keyboard, the text shown on the button is send to the chat.
|
||||
|
||||
Example Keyboard Array definitions:
|
||||
|
||||
- yes no in two rows:
|
||||
- OLD format: 'yes' 'no' (two strings)
|
||||
- NEW format: '[ "yes" ] , [ "no" ]' (two arrays with a string)
|
||||
- new layouts made easy with NEW format:
|
||||
- Yes No in one row: '[ "yes" , "no" ]'
|
||||
- Yes No plus Maybe in 2.row: '[ "yes" , "no" ] , [ "maybe" ]'
|
||||
- number pad style keyboard: '[ "1" , "2" , "3" ] , [ "4" , "5" , "6" ] , [ "7" , "8" , "9" ] , [ "0" ]'
|
||||
@ -205,56 +207,263 @@ _keyboard_numpad
|
||||
```
|
||||
|
||||
##### remove_keyboard
|
||||
`remove_keyboard` deletes the last custom keyboard. Depending on used Telegram client this will hide or delete the custom keyboard.
|
||||
|
||||
*usage:* remove_keybord "$CHAT[ID]" "message"
|
||||
|
||||
*alias:* _del_keyboard "message"
|
||||
|
||||
*See also: [Keyboard Markup](https://core.telegram.org/bots/api/#replykeyboardmarkup)*
|
||||
|
||||
|
||||
----
|
||||
|
||||
##### send_button
|
||||
`send_button` sends a text message with a single button to open an URL attached.
|
||||
|
||||
*usage:* send_button "$CHAT[ID]" "message" "text" "URL"
|
||||
|
||||
*alias:* _button "text" "URL"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
send_button "${CHAT[ID]}" "MAKE MONEY FAST!!!" "Visit my Shop" "https://dealz.rrr.de"
|
||||
send_button "${CHAT[ID]}" "Awesome Deals!" "Visit my Shop" "https://dealz.rrr.de"
|
||||
```
|
||||
|
||||
##### send_sticker
|
||||
`send_sticker` sends a sticker using a `file_id` to send a sticker that exists on the Telegram servers.
|
||||
### Inline buttons
|
||||
Functions to send/edit messages with with some buttons attached.
|
||||
|
||||
*usage:* send_sticker "$CHAT[ID]" "file_id"
|
||||
##### send_inline_buttons
|
||||
`senbd_inline_buttons` sends a message with multiple buttons attached. Buttons can be an URL or a CALLBACK button.
|
||||
By default all buttons are displayed on one row, an empty string `""` starts a new row.
|
||||
|
||||
*usage:* send_inline_buttons "CHAT[ID]" "text|url" "text|url" "" "url" "" "text|url" ...
|
||||
|
||||
##### send_inline_keyboard
|
||||
Even its called keyboard, this function is different from send_keyboard. The main difference is that it's only possible to
|
||||
specify URL buttons, no Text Buttons and the Buttons must be an Array of Buttons as specified for
|
||||
[Telegram InlineMarkup](https://core.telegram.org/bots/api#inlinekeyboardmarkup).
|
||||
URL buttons are specified as a `"text|url"` pair separated by `|`, `text` is shown on the button and `url` is opened on button click.
|
||||
If `"url"` without text is given, `url` is shown on the button and opened on button click.
|
||||
|
||||
The inline buttons must be specified as a JSON string in the following format:
|
||||
*Important* An `url` not startung with http(s):// or tg:// will create a
|
||||
[CALLBACK Button](https://core.telegram.org/bots/2-0-intro#callback-buttons).
|
||||
|
||||
`[ {"text":"text1", "url":"url1"}, ... {"text":"textN", "url":"urlN"} ]```
|
||||
|
||||
Each button consists of a pair of text and URL values, sourrounded by '{ }', multiple buttons are separated by '**,**' and everything is wrapped in '[ ]'.
|
||||
|
||||
*usage:* send_inline_keyboard "chat-id" "message" "[ {"text":"text", "url":"url"} ...]"
|
||||
|
||||
*alias:* _inline_keyboard "[{"text":"text", "url":"url"} ...]"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
send_inline_keyboard "${CHAT[ID]}" "MAKE MONEY FAST!!!" '[{"text":"Visit my Shop", url"":"https://dealz.rrr.de"}]'
|
||||
send_inline_keyboard "${CHAT[ID]}" "" '[{"text":"button 1", url"":"url 1"}, {"text":"button 2", url"":"url 2"} ]'
|
||||
send_inline_keyboard "${CHAT[ID]}" "" '[{"text":"b 1", url"":"u 1"}, {"text":"b 2", url"":"u 2"}, {"text":"b 2", url"":"u 2"} ]'
|
||||
# one button, same as send_button
|
||||
send_inline_buttons "${CHAT[ID]}" "Best Dealz!" "Visit my Shop|https://dealz.rrr.de"
|
||||
|
||||
# result
|
||||
Best Dealz!
|
||||
+----------------------------+
|
||||
| Visit my Shop |
|
||||
+----------------------------+
|
||||
|
||||
# one button row
|
||||
send_inline_buttons "${CHAT[ID]}" "message" "Button 1|http://rrr.de" "Button 2|http://rrr.de"
|
||||
|
||||
# result
|
||||
message ...
|
||||
+----------------------------+
|
||||
| Button 1 | Button 2 |
|
||||
+----------------------------+
|
||||
|
||||
# multiple button rows
|
||||
send_inline_buttons "${CHAT[ID]}" "message" "Button 1|http://rrr.de" "Button 2|http://rrr.de" "" "Button on second row|http://rrr.de"
|
||||
|
||||
# result
|
||||
message ...
|
||||
+----------------------------+
|
||||
| Button 1 | Button 2 |
|
||||
|----------------------------|
|
||||
| Button on second row |
|
||||
+----------------------------+
|
||||
|
||||
```
|
||||
|
||||
##### edit_inline_buttons
|
||||
`edit_inline_buttons` add inline buttons to existing messages, existing inline buttons will be replaced.
|
||||
Only the attached buttons will be changed, not the message.
|
||||
|
||||
*usage:* edit_inline_buttons "CHAT[ID]" "MESSAGE[ID]" "text|url" "text|url" ...
|
||||
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
# message without button
|
||||
send_markdownv2_message "${CHAT[ID]}" "*HI* this is a _markdown_ message ..."
|
||||
echo ${BOTSEND[ID]}
|
||||
567
|
||||
|
||||
# add one button row
|
||||
edit_inline_keyboard "${CHAT[ID]}" "567" "button 1|http://rrr.de" "button 2|http://rrr.de"
|
||||
|
||||
# change buttons
|
||||
edit_inline_keyboard "${CHAT[ID]}" "567" "Success edit_inline_keyboard|http://rrr.de"
|
||||
|
||||
# delete button by replace whole message
|
||||
edit_markdownv2_message "${CHAT[ID]}" "*HI* this is a _markdown_ message inline *removed*..."
|
||||
|
||||
```
|
||||
|
||||
##### answer_callback_query
|
||||
Each request send from a CALLBACK button must be answered by a call to `answer_callback_query`.
|
||||
If alert is given an alert will be shown by the Telegram client instead of a notification.
|
||||
|
||||
*usage:* answer_callback_query "iBUTTON[ID]" "text notification ..." ["alert"]
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
answer_callback_query "${iBUTTON[ID]}" "Button data is: ${iBUTTON[DATA]}"
|
||||
|
||||
answer_callback_query "${iBUTTON[ID]}" "Alert: Button pressed!" "alert"
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
# CALLBACK button example
|
||||
send_inline_buttons "${CHAT[ID]}" "Press Button ..." " Button |RANDOM-BUTTON"
|
||||
|
||||
# result
|
||||
Press Button ...
|
||||
+----------------------------+
|
||||
| Button |
|
||||
+----------------------------+
|
||||
|
||||
# react on button press from mycommands
|
||||
CALLBACK="1" # enable callbacks
|
||||
...
|
||||
mycallbacks() {
|
||||
local answer
|
||||
#######################
|
||||
# callbacks from buttons attached to messages will be processed here
|
||||
if [ "${iBUTTON[DATA]}" = "RANDOM-BUTTON" ]; then
|
||||
answer="Button pressed"
|
||||
edit_inline_buttons "${iBUTTON[CHAT_ID]}" "${iBUTTON[MESSAGE_ID]}" " Button ${RANDOM}|RANDOM-BUTTON"
|
||||
fi
|
||||
|
||||
# Telegram needs an ack each callback query, default empty
|
||||
answer_callback_query "${iBUTTON[ID]}" "${answer}"
|
||||
;;
|
||||
}
|
||||
|
||||
# result, XXXXX: random number changed on each press
|
||||
Press Button ...
|
||||
+----------------------------+
|
||||
| Button XXXXXX |
|
||||
+----------------------------+
|
||||
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
#### Inline keyboards
|
||||
Functions to send/edit more complex button layouts (keyboards), I suggest to start with the simpler inline buttons above.
|
||||
|
||||
##### _button_row
|
||||
`_button_row` is a helper function to specify a keyboard row in the form "text|url" pairs.
|
||||
Internally used by inline buttons also.
|
||||
|
||||
*usage:* _button_row "text|url" "text|url" "url" "text|url" ...
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
# similar to send_button
|
||||
send_inline_keyboard "${CHAT[ID]}" "Best Dealz!" "$(_button_row "Visit my Shop|https://dealz.rrr.de")"
|
||||
|
||||
# similar to send_inline_button
|
||||
send_inline_keyboard "${CHAT[ID]}" "message" "$(_button_row "button 1|http://rrr.de" "button 2|http://rrr.de")"
|
||||
|
||||
# multiple button rows
|
||||
send_inline_keyboard "${CHAT[ID]}" "message" "$(_button_row "b1|http://rrr.de" "b2|http://rrr.de" "" "b3|http://rrr.de" "b4|http://rrr.de")"
|
||||
```
|
||||
|
||||
##### send_inline_keyboard
|
||||
`send_inline_keyboard` sends a message with keyboards attached, keyboards must be specified in JSON format.
|
||||
|
||||
*usage:* send_inline_keyboard "CHAT[ID]" "message" "[JSON button array]"
|
||||
|
||||
I suggest to use `_button_row` to create the used JSON. For hand crafted JSON the following format must be used,
|
||||
see [Inline Keyboard Markup](https://core.telegram.org/bots/api#inlinekeyboardmarkup)
|
||||
|
||||
URL `[ {"text":"text1", "url":"url1"}, ... {"text":"textN", "url":"urlN"} ],[...]`\
|
||||
CALLBACK `[ {"text":"text1", "callback_data":"abc"}, ... {"text":"textN", "callback_data":"defg"} ],[...]`\
|
||||
An URL Button opens the given URL, a CALLBACK button sends an update the bot must react on.
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
# send_button
|
||||
send_inline_keyboard "${CHAT[ID]}" "Best Dealz!" '[{"text":"Visit my Shop", "url":"https://dealz.rrr.de"}]'
|
||||
|
||||
# send_inline_button
|
||||
send_inline_keyboard "${CHAT[ID]}" "message" '[{"text":"button 1", url"":"http://rrr.de"}, {"text":"button 2", "url":"http://rrr.de"} ]'
|
||||
|
||||
# multiple button rows
|
||||
send_inline_keyboard "${CHAT[ID]}" "message" '[{"text":"b1", "url":"http://rrr.de"}, {"text":"b2", "url":"http://rrr.de"}], [{"text":"b3", "url":"http://rrr.de"}, "text":"b4", "url":"http://rrr.de"}]'
|
||||
|
||||
# more complex keyboard, note the ,
|
||||
keyboard_text="Deal-O-Mat public groups ..."
|
||||
keyboard_json="$(_button_row "🤖 #Home of Deal-O-Mat Bot 🤖|https://dealz.rrr.de/dealzbot.html")
|
||||
, $(_button_row "Amazon DE|https://t.me/joinchat/IvvRtlxxxxx" "Home & Family|https://t.me/joinchat/VPh_wexxxxx")
|
||||
, $(_button_row "Amz International |https://t.me/joinchat/IvvRtkxxxxx" "Amazon WHD|https://t.me/joinchat/IvvRxxxxx")
|
||||
, $(_button_row "Smartphones|https://t.me/joinchat/IvvRthtqxxxxx" "Gaming|https://t.me/joinchat/IvvRthRyrsmxxxxx")
|
||||
, $(_button_row "Accessoires|https://t.me/joinchat/IvvRthlJxxxxx" "eBay|https://t.me/joinchat/IvvRthxxxxx")
|
||||
, $(_button_row "!! Offtopic Discussions !!|https://t.me/joinchat/IvvRthRhxxxxx-pZrWw")
|
||||
, $(_button_row "Deals >100|https://t.me/joinchat/IvvRtxxxxx" "Leasing|https://t.me/joinchat/IvvRthRbxxxxx")
|
||||
, $(_button_row "Deals >1000|https://t.me/joinchat/IvvRtlxxxxx" "Deals >500|https://t.me/joinchat/IvvRthvbHxxxxx")
|
||||
|
||||
send_inline_keyboard "CHAT[ID]" "${keyboard_text}" "${keyboard_json}"
|
||||
|
||||
# result
|
||||
+---------------------------------+
|
||||
| 🤖 #Home of Deal-O-Mat Bot 🤖 |
|
||||
|---------------------------------|
|
||||
| Amazon DE | Home & Family |
|
||||
|----------------|----------------|
|
||||
| Amz Internat | Amazon WHD |
|
||||
|----------------|----------------|
|
||||
| Smartphones | Gaming |
|
||||
|----------------|----------------|
|
||||
| Accessoires | eBay |
|
||||
|---------------------------------|
|
||||
| !! Offtopic Discussions !! |
|
||||
|---------------------------------|
|
||||
| Deals >100 | Leasing |
|
||||
|----------------|----------------|
|
||||
| Deals >1000 | Deals >500 |
|
||||
+---------------------------------+
|
||||
|
||||
```
|
||||
|
||||
*See also [Inline keyboard markup](https://core.telegram.org/bots/api/#inlinekeyboardmarkup)*
|
||||
|
||||
##### edit_inline_keyboard
|
||||
`edit_inline_keyboard` add inline keyboards to existing messages and replace existing inline keyboards.
|
||||
Only the attached keyboard will be changed, not the message.
|
||||
|
||||
*usage:* edit_inline_keyboard "CHAT[ID]" "MESSAGE[ID]" "[JSON button array]"
|
||||
|
||||
To create a JSON button array I suggest to use `_button_row`.
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
# message without button
|
||||
send_markdownv2_message "${CHAT[ID]}" "*HI* this is a _markdown_ message ..."
|
||||
echo ${BOTSEND[ID]}
|
||||
567
|
||||
|
||||
# add one button row with help of _button_row
|
||||
edit_inline_keyboard "${CHAT[ID]}" "567" "$(_button_row "button 1|http://rrr.de" "button 2|http://rrr.de")"
|
||||
|
||||
# change buttons with help of _button_row
|
||||
edit_inline_keyboard "${CHAT[ID]}" "567" "$(_button_row "Success edit_inline_keyboard|http://rrr.de")"
|
||||
|
||||
# delete button by replace whole message
|
||||
edit_markdownv2_message "${CHAT[ID]}" "*HI* this is a _markdown_ message inline *removed*..."
|
||||
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
|
||||
### Edit / Replace Messages
|
||||
|
||||
Edit a message means replace the content of the message in place. The message stay on the same position in the chat and keep the same
|
||||
@ -270,7 +479,7 @@ To replace a message you must know the message id of the the original message. T
|
||||
##### edit_normal_message
|
||||
`edit_normal_message` replace a message with a text message in the given chat.
|
||||
|
||||
*usage:* edit_normal_message "${CHAT[ID]}" "MESSAGE-ID" "message"
|
||||
*usage:* edit_normal_message "CHAT[ID]" "MESSAGE-ID" "message"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
@ -283,7 +492,7 @@ edit_normal_message "${CHAT[ID]}" "${saved-id}" "this is another text"
|
||||
##### edit_markdownv2_message
|
||||
`edit_markdownv2_message` replace a message with a markdown v2 message in the given chat.
|
||||
|
||||
*usage:* edit_markdownv2_message "${CHAT[ID]}" "MESSAGE-ID" "message"
|
||||
*usage:* edit_markdownv2_message "CHAT[ID]" "MESSAGE-ID" "message"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
@ -296,7 +505,7 @@ edit_markdownv2_message "${CHAT[ID]}" "${saved-id}" "this is __markdown__ *V2* t
|
||||
##### edit_markdown_message
|
||||
`edit_markdown_message` replace a message with a markdown message in the given chat.
|
||||
|
||||
*usage:* edit_markdown_message "${CHAT[ID]}" "MESSAGE-ID" "message"
|
||||
*usage:* edit_markdown_message "CHAT[ID]" "MESSAGE-ID" "message"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
@ -309,7 +518,7 @@ edit_markdown_message "${CHAT[ID]}" "${saved-id}" "this is *markdown* text"
|
||||
##### edit_html_message
|
||||
`edit_html_message` replace a message with a html message in the given chat.
|
||||
|
||||
*usage:* edit_html_message "${CHAT[ID]}" "MESSAGE-ID" "message"
|
||||
*usage:* edit_html_message "CHAT[ID]" "MESSAGE-ID" "message"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
@ -322,7 +531,7 @@ edit_html_message "${CHAT[ID]}" "${saved-id}" "this is <b>html</b> text"
|
||||
##### edit_message_caption
|
||||
`edit_message_caption` changes the caption of a message (photo, audio, video, document) in the given chat.
|
||||
|
||||
*usage:* edit_message_caption "${CHAT[ID]}" "MESSAGE-ID" "caption"
|
||||
*usage:* edit_message_caption "CHAT[ID]" "MESSAGE-ID" "caption"
|
||||
|
||||
|
||||
---
|
||||
@ -330,55 +539,60 @@ edit_html_message "${CHAT[ID]}" "${saved-id}" "this is <b>html</b> text"
|
||||
### Manage Group
|
||||
To use the following functions the bot must have administrator status in the chat / group
|
||||
|
||||
##### chat_member_count
|
||||
`chat_member_count` returns (putput) number of chat members.
|
||||
|
||||
*usage:* num_members="$(chat_member_count "CHAT[ID]")"
|
||||
|
||||
##### set_chat_title
|
||||
`set_chat_title` sets a new chat title. If new title is the same than current title Telegram return error 400
|
||||
with description "Bad Request: chat title is not modified"
|
||||
|
||||
*usage:* set_chat_title "${CHAT[ID]}" "new chat title"
|
||||
*usage:* set_chat_title "CHAT[ID]" "new chat title"
|
||||
|
||||
|
||||
##### set_chat_description
|
||||
`set_chat_description` sets a new description title. If new description is the same than current description Telegram return error 400
|
||||
with description "Bad Request: chat description is not modified"
|
||||
|
||||
*usage:* set_chat_description "${CHAT[ID]}" "new chat description"
|
||||
*usage:* set_chat_description "CHAT[ID]" "new chat description"
|
||||
|
||||
|
||||
##### new_chat_invite
|
||||
`new_chat_invite` generate a new invite link for a chat; any previously generated link is revoked.
|
||||
Returns the new invite link as String on success.
|
||||
|
||||
*usage:* new_chat_invite "${CHAT[ID]}"
|
||||
*usage:* new_chat_invite "CHAT[ID]"
|
||||
|
||||
|
||||
##### delete_chat_photo
|
||||
|
||||
*usage:* delete_chat_photo "${CHAT[ID]}"
|
||||
*usage:* delete_chat_photo "CHAT[ID]"
|
||||
|
||||
|
||||
##### pin_chat_message
|
||||
# $1 chat, $2 message_id
|
||||
`pin_chat_message` add a message to the list of pinned messages in a chat.
|
||||
|
||||
*usage:* pin_chat_message "${CHAT[ID]}" "message_id"
|
||||
*usage:* pin_chat_message "CHAT[ID]" "message_id"
|
||||
|
||||
|
||||
##### unpin_chat_message
|
||||
`unpin_chat_message` remove a message from the list of pinned messages in a chat.
|
||||
|
||||
*usage:* unpin_chat_message "${CHAT[ID]}" "message_id"
|
||||
*usage:* unpin_chat_message "CHAT[ID]" "message_id"
|
||||
|
||||
|
||||
##### unpinall_chat_message
|
||||
`unpinall_chat_message` clear the list of pinned messages in a chat.
|
||||
|
||||
*usage:* unpinall_chat_message "${CHAT[ID]}"
|
||||
*usage:* unpinall_chat_message "CHAT[ID]"
|
||||
|
||||
|
||||
##### delete_chat_stickers
|
||||
`delete_chat_stickers` deletes a group sticker set from a supergroup.
|
||||
|
||||
*usage:* delete_chat_stickers "${CHAT[ID]}"
|
||||
*usage:* delete_chat_stickers "CHAT[ID]"
|
||||
|
||||
|
||||
----
|
||||
@ -390,21 +604,21 @@ More advanced API functions are currently not implemented in bashbot.
|
||||
##### kick_chat_member
|
||||
If your Bot is a chat admin he can kick and ban a user.
|
||||
|
||||
*usage:* kick_chat_member "${CHAT[ID]}" "${USER[ID]}"
|
||||
*usage:* kick_chat_member "CHAT[ID]" "USER[ID]"
|
||||
|
||||
*alias:* _kick_user "${USER[ID]}"
|
||||
*alias:* _kick_user "USER[ID]"
|
||||
|
||||
##### unban_chat_member
|
||||
If your Bot is a chat admin can unban a kicked user.
|
||||
|
||||
*usage:* unban_chat_member "${CHAT[ID]}" "${USER[ID]}"
|
||||
*usage:* unban_chat_member "CHAT[ID]" "USER[ID]"
|
||||
|
||||
*alias:* _unban "${USER[ID]}"
|
||||
*alias:* _unban "USER[ID]"
|
||||
|
||||
##### leave_chat
|
||||
Your Bot will leave the chat.
|
||||
|
||||
*usage:* leave_chat "${CHAT[ID]}"
|
||||
*usage:* leave_chat "CHAT[ID]"
|
||||
|
||||
*alias:* _leave
|
||||
|
||||
@ -417,6 +631,25 @@ fi
|
||||
|
||||
See also [kick Chat Member](https://core.telegram.org/bots/api/#kickchatmember)*
|
||||
|
||||
|
||||
##### promote_chat_member
|
||||
`promote_chat_member` promote or denote user rights in a chat. Bot must be admin and can only promote/denote rights he owns.
|
||||
|
||||
Right are specified as "right:bool" pairs, where right is one of `long` or `short` listed below, followed
|
||||
by `:true` or `:false`. Anything but `:true` (e.g. nothing or :xyz) is `:false`.
|
||||
|
||||
long: `is_anonymous can_change_info can_post_messages can_edit_messages can_delete_messages can_invite_users can_restrict_members can_pin_messages can_promote_member`
|
||||
short: `anon change post edit delete invite restrict pin promote`
|
||||
|
||||
*usage:* promote_chat_member "CHAT[ID]" "USER[ID]" "right[:true|false]" ... "right[:true|false]"
|
||||
|
||||
See also [promote Chat Member](https://core.telegram.org/bots/api#promotechatmember)*
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
# USER can post, can't edit, can't delete, can't pin message, can invite users
|
||||
promote_chat_member "CHAT[ID}" "USER[ID]" "post:true" "can_edit_message" "delete:false" "pin:xxx" "invite:true"
|
||||
```
|
||||
----
|
||||
|
||||
The following functions are bashbot only and not part of the Telegram API.
|
||||
@ -424,7 +657,7 @@ The following functions are bashbot only and not part of the Telegram API.
|
||||
##### bot_is_admin
|
||||
Return true (0) if bot is admin or creator of given chat.
|
||||
|
||||
*usage:* bot_is_admin "${CHAT[ID]}"
|
||||
*usage:* bot_is_admin "CHAT[ID]"
|
||||
|
||||
|
||||
*example:*
|
||||
@ -437,7 +670,7 @@ fi
|
||||
##### user_is_botadmin
|
||||
Return true (0) if user is admin of bot, user id if botadmin is read from file './botadmin'.
|
||||
|
||||
*usage:* user_is_botadmin "${USER[ID]}"
|
||||
*usage:* user_is_botadmin "USER[ID]"
|
||||
|
||||
*alias:* _is_botadmin
|
||||
|
||||
@ -449,14 +682,14 @@ user_is_botadmin "${CHAT[ID]}" && send_markdown_message "${CHAT[ID]}" "You are *
|
||||
##### user_is_creator
|
||||
Return true (0) if user is creator of given chat or chat is a private chat.
|
||||
|
||||
*usage:* user_is_creator "${CHAT[ID]}" "${USER[ID]}"
|
||||
*usage:* user_is_creator "CHAT[ID]" "USER[ID]"
|
||||
|
||||
*alias:* _is_creator
|
||||
|
||||
##### user_is_admin
|
||||
Return true (0) if user is admin or creator of given chat.
|
||||
|
||||
*usage:* user_is_admin "${CHAT[ID]}" "${USER[ID]}"
|
||||
*usage:* user_is_admin "CHAT[ID]" "USER[ID]"
|
||||
|
||||
*alias:* _is_admin
|
||||
|
||||
@ -474,7 +707,7 @@ fi
|
||||
`uers_is_allowed` checks if: user id botadmin, user is group admin or user is allowed to execute action..
|
||||
Allowed actions are configured as User Access Control rules, see [Advanced Usage](3_advanced.md)
|
||||
|
||||
*usage:* user_is_allowed "${USER[ID]}" "action" "${CHAT[ID]}"
|
||||
*usage:* user_is_allowed "USER[ID]" "action" "CHAT[ID]"
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
@ -562,7 +795,7 @@ chats and send messages based on time or other external events.
|
||||
##### start_proc
|
||||
`startproc` starts a script, the output of the script is sent to the user or chat, user input will be sent back to the script. see [Advanced Usage](3_advanced.md#Interactive-Chats)
|
||||
|
||||
*usage:* start_proc "${CHAT[ID]}" "script"
|
||||
*usage:* start_proc "CHAT[ID]" "script"
|
||||
|
||||
*alias:* startproc "script"
|
||||
|
||||
@ -575,7 +808,7 @@ startproc 'examples/calc.sh'
|
||||
##### check_proc
|
||||
Return true (0) if an interactive script is running in the chat.
|
||||
|
||||
*usage:* check_prog "${CHAT[ID]}"
|
||||
*usage:* check_prog "CHAT[ID]"
|
||||
|
||||
*alias:* checkprog
|
||||
|
||||
@ -591,7 +824,7 @@ fi
|
||||
##### kill_proc
|
||||
Kill the interactive script running in the chat
|
||||
|
||||
*usage:* kill_proc "${CHAT[ID]}"
|
||||
*usage:* kill_proc "CHAT[ID]"
|
||||
|
||||
*alias:* killproc
|
||||
|
||||
@ -611,7 +844,7 @@ Starts a script as a background job and attaches a job name to it. All output fr
|
||||
|
||||
In contrast to interactive chats, background jobs do not receive user input and can run forever. In addition you can suspend and restart running jobs, e.g. after reboot.
|
||||
|
||||
*usage:* start_back "${CHAT[ID]}" "script" "jobname"
|
||||
*usage:* start_back "CHAT[ID]" "script" "jobname"
|
||||
|
||||
*alias:* background "script" "jobname"
|
||||
|
||||
@ -623,7 +856,7 @@ background "examples/notify.sh" "notify"
|
||||
##### check_back
|
||||
Return true (0) if an background job is active in the given chat.
|
||||
|
||||
*usage:* check_back "${CHAT[ID]}" "jobname"
|
||||
*usage:* check_back "CHAT[ID]" "jobname"
|
||||
|
||||
*alias:* checkback "jobname"
|
||||
|
||||
@ -639,7 +872,7 @@ fi
|
||||
|
||||
##### kill_back
|
||||
|
||||
*usage:* kill_back "${CHAT[ID]}" "jobname"
|
||||
*usage:* kill_back "CHAT[ID]" "jobname"
|
||||
|
||||
*alias:* killback "jobname"
|
||||
|
||||
@ -660,7 +893,7 @@ fi
|
||||
`send_interactive` is used to forward messages to interactive jobs.
|
||||
Usually a message is automatically forwarded from within `commands.sh`, but you can send messages yourself.
|
||||
|
||||
*usage:* send_interactive "${CHAT[ID]}" "message"
|
||||
*usage:* send_interactive "CHAT[ID]" "message"
|
||||
|
||||
----
|
||||
|
||||
@ -989,6 +1222,91 @@ https://linuxhint.com/associative_array_bash/
|
||||
https://linuxconfig.org/how-to-use-arrays-in-bash-script
|
||||
|
||||
|
||||
----
|
||||
|
||||
### Manage webhook
|
||||
Bashbot default mode is to poll Telegram server for updates but Telegram offers also webhook as a more efficient method to deliver updates.
|
||||
|
||||
*Important*: Before enable webhook you must setup your server to [receive and process webhook updates from Telegram](../examples/webhook)
|
||||
I recommend to use webhook with a test bot first.
|
||||
|
||||
##### get_webhook_info
|
||||
`get_webhook_info` get current status of webhook for your bot, e.g. url, waiting updates, last error.
|
||||
|
||||
*usage:* get_webhook_info
|
||||
|
||||
*example:*
|
||||
```bash
|
||||
bin/any_command.sh get_webhook_info
|
||||
|
||||
["URL"] ""
|
||||
["OK"] "true"
|
||||
["LASTERR"] ""
|
||||
["COUNT"] "0"
|
||||
["CERT"] "false"
|
||||
["result","pending_update_count"] "0"
|
||||
["ok"] "true"
|
||||
["result","has_custom_certificate"] "false"
|
||||
```
|
||||
|
||||
|
||||
##### delete_webhook
|
||||
`delete_webhook` deletes your bots current webhook, deletes outstanding updates also if second arg is `true`
|
||||
|
||||
*usage:* delete_webhook [true|false]
|
||||
|
||||
*example:*
|
||||
|
||||
```bash
|
||||
bin/any_command.sh delete_webhook false
|
||||
|
||||
["RESULT"] "true"
|
||||
["OK"] "true"
|
||||
["result"] "true"
|
||||
["ok"] "true"
|
||||
["description"] "Webhook was deleted"
|
||||
```
|
||||
|
||||
|
||||
##### set_webhook
|
||||
`set_webhook` instructs Telegram to use your bots webhook for delivering updates. If webhook is set
|
||||
it's no more possible to pull updates from `bashbot start`, you must delete webhook first.
|
||||
|
||||
*Important*: Before using webhook you must setup your server to receive and process updates from Telegram!
|
||||
|
||||
*usage:* set_webhook "https://host.dom[:port][/path]" [max_conn]
|
||||
|
||||
First arg is webhook URL used to send updates to your bot, `:port` and `/path` are optional.
|
||||
If `:port` is given it must be one of `:443`, `:80`, `:88` or `:8443`, default is`:80`.
|
||||
For security reasons `BOTTOKEN` will be added to URL (_e.g. `https://myhost.com` -> `https://myhost.com/12345678:azndfhbgdfbbbdsfg/`_).
|
||||
|
||||
Second arg is max connection rate in the range 1-100, bashbot default is 1.
|
||||
|
||||
*example:*
|
||||
|
||||
```bash
|
||||
bin/any_command.sh set_webhook "https://myhost.com/telegram" "2"
|
||||
|
||||
["OK"] "true"
|
||||
["RESULT"] "true"
|
||||
["ok"] "true"
|
||||
["result"] "true"
|
||||
["description"] "Webhook is set"
|
||||
|
||||
bin/any_command.sh get_webhook_info
|
||||
|
||||
["OK"] "true"
|
||||
["URL"] "https://myhost.com/telegram/12345678:AABBCCDDEE...aabbccee124567890/"
|
||||
["COUNT"] "0"
|
||||
["CERT"] "false"
|
||||
["ok"] "true"
|
||||
["result","ip_address"] "1.2.3.4"
|
||||
["result","url"] "https://myhost.com/telegram/12345678:AABBCCDDEE...aabbccee124567890/"
|
||||
["result","pending_update_count"] "0"
|
||||
["result","max_connections"] "2"
|
||||
["result","has_custom_certificate"] "false"
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### Aliases - shortcuts for often used functions
|
||||
@ -1017,13 +1335,13 @@ Do not use them in other files e.g. `bashbot.sh`, modules, addons etc.
|
||||
|
||||
##### _kick_user
|
||||
|
||||
*usage:* _kick_user "${USER[ID]}"
|
||||
*usage:* _kick_user "USER[ID]"
|
||||
|
||||
*alias for:* kick_chat_member "${CHAT[ID]}" "${USER[ID]}"
|
||||
|
||||
##### _unban
|
||||
|
||||
*usage:* _unban "${USER[ID]}"
|
||||
*usage:* _unban "USER[ID]"
|
||||
|
||||
*alias for:* unban_chat_member "${CHAT[ID]}" "${USER[ID]}"
|
||||
|
||||
@ -1061,16 +1379,6 @@ Do not use them in other files e.g. `bashbot.sh`, modules, addons etc.
|
||||
|
||||
----
|
||||
|
||||
#### _inline_button
|
||||
*usage:* _inline_button "${1}" "${2}"
|
||||
|
||||
*alias for:* send_inline_button "${CHAT[ID]}" "" "${1}" "${2}"
|
||||
|
||||
#### _inline_keyboard
|
||||
*usage:* _inline_keyboard "${1}"
|
||||
|
||||
*alias for:* _inline_keyboard "${CHAT[ID]}" "" "${1}"
|
||||
|
||||
#### _keyboard_numpad
|
||||
*usage:* _keyboard_numpad
|
||||
|
||||
@ -1199,7 +1507,7 @@ killallproc
|
||||
----
|
||||
|
||||
##### get_file
|
||||
*usage:* url="$(get_file "${CHAT[ID]}" "message")"
|
||||
*usage:* url="$(get_file "CHAT[ID]" "message")"
|
||||
|
||||
----
|
||||
|
||||
@ -1233,7 +1541,7 @@ Output ARRAY as JSON.sh style data to STDOUT
|
||||
----
|
||||
|
||||
##### get_chat_member_status
|
||||
*usage:* get_chat_member_status "${CHAT[ID]}" "${USER[ID]}"
|
||||
*usage:* get_chat_member_status "CHAT[ID]" "USER[ID]"
|
||||
|
||||
|
||||
----
|
||||
@ -1266,8 +1574,9 @@ The name of your bot is available as bash variable "$ME", there is no need to ca
|
||||
|
||||
*usage:* ME="$(getBotName)"
|
||||
|
||||
|
||||
#### [Prev Best Practice](5_practice.md)
|
||||
#### [Next Notes for Developers](7_develop.md)
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
@ -284,8 +284,9 @@ bar="${_/__x/_c}" # a_b_c
|
||||
: ${SOMEVAR} # "String in var" $_ -> "var"
|
||||
: $(<"file") # "Content of\n file" $_ -> "file"
|
||||
|
||||
# pitfall test command
|
||||
[ -n "$MYVAR" ] && echo "$_" # outputs "]"
|
||||
# pitfall [ vs. test command
|
||||
[ -n "xxx" ] && echo "$_" # $_ -> "]"
|
||||
test -n "xxx" && echo "$_" # $_ -> "xxx"
|
||||
|
||||
# pitfall command substitution: globbing and IFS is applied!
|
||||
: "$(echo "a* is born")"# $_ -> a* is globbed even quoted!
|
||||
@ -386,5 +387,5 @@ fi
|
||||
|
||||
#### [Prev Function Reference](6_reference.md)
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
@ -56,6 +56,10 @@ convert existing bots.
|
||||
**jsonDB-keybords** contains a stripped down real world example from my bot showing the usage of jsonDB to store and retrieve values
|
||||
plus use of keyboards in private chats. It's an extended version of mycommands.sh.dist. Messages and help are in german.
|
||||
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
### Webhook
|
||||
|
||||
**Webhook** contains instructions on how use webhook API to get updates from telegram instead polling Telegram server.
|
||||
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
@ -2,7 +2,7 @@
|
||||
# file: run_filename
|
||||
# background job to display content of all new files in WATCHDIR
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
@ -2,7 +2,7 @@
|
||||
# file: run_filename
|
||||
# background job to display all new files in WATCHDIR
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
@ -6,7 +6,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
# shellcheck disable=SC1117
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
@ -2,7 +2,7 @@
|
||||
# file. multibot.sh
|
||||
# description: run multiple telegram bots from one installation
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
if [ "$2" = "" ] || [ "$2" = "-h" ]; then
|
||||
echo "Usage: $0 botname command"
|
||||
|
@ -7,7 +7,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
|
||||
SHELL=/bin/sh
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
########################################################################
|
||||
|
||||
######
|
||||
|
@ -10,7 +10,7 @@
|
||||
# AUTHOR: KayM (), kay@rrr.de
|
||||
# DATE: 19.12.2020 19:03
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2154
|
||||
# shellcheck disable=SC2034
|
||||
|
@ -13,7 +13,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
########################################################################
|
||||
|
||||
######
|
||||
|
@ -10,7 +10,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
########################################################################
|
||||
|
||||
######
|
||||
|
@ -1,7 +1,7 @@
|
||||
# file: botacl
|
||||
# a user not listed here, will return false from 'user_is_allowed'
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
# Format:
|
||||
# user:resource:chat
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
# to show how you can customize bashbot by only editing mycommands.sh
|
||||
# NOTE: this is not tested, simply copied from original source and reworked!
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#
|
||||
# shellcheck disable=SC2154
|
||||
# shellcheck disable=SC2034
|
||||
|
3
examples/webhook/BASHBOT_HOME
Normal file
3
examples/webhook/BASHBOT_HOME
Normal file
@ -0,0 +1,3 @@
|
||||
/usr/local/github/telegram-bot-bash-develop/DIST/telegram-bot-bash
|
||||
/usr/local/github/telegram-bot-bash-develop/STANDALONE
|
||||
/usr/local/telegram-bot-bash
|
80
examples/webhook/README.md
Normal file
80
examples/webhook/README.md
Normal file
@ -0,0 +1,80 @@
|
||||
#### [Examples](../README.md)
|
||||
|
||||
## Bashtbot webhook example
|
||||
|
||||
### Webhooks
|
||||
|
||||
Bashbot default mode is to poll Telegram server for updates but Telegram offers also webhook
|
||||
as a more efficient method to deliver updates.
|
||||
If your server is reachable from the Internet you can use the webhook method described here.
|
||||
|
||||
|
||||
#### Setup Apache webhook
|
||||
|
||||
Prerequisite: An Apache webserver with a valid SLL certificate chain and php enabled.
|
||||
|
||||
Prepare Apache to forward webhook to Bashbot:
|
||||
|
||||
- install bashbot as described in [Bashbot Installation](../../doc/0_install.md)
|
||||
- create file `data-bot-bash/webhook-fifo`
|
||||
- run `bashbot.sh init` to setup bashbot to run as same user as Apache (_e.g. www_)
|
||||
- go to apache web root and create directory `telegram/<your_bot_token>`
|
||||
- copy all files from `examples/webhook` to new directory and change to it
|
||||
- write bashbot installation directory as first line to file `BASHBOT_HOME`
|
||||
- execute `php index.php`
|
||||
|
||||
Every call to webhook `https://<yourservername>/telegram/<your_bot_token>/` will execute
|
||||
`index.php` and write received JSON to file `data-bot-bash/webhook-fifo`.
|
||||
E.g. the URL `https://<yourservername>/telegram/<your_bot_token>/?json={"test":"me"}`
|
||||
will append `{"test":"me"}` to the file `data-bot-bash/webhook-fifo`.
|
||||
|
||||
Now your Apache is ready to forward data to Bashbot.
|
||||
|
||||
|
||||
#### Simple update processing
|
||||
|
||||
To configure `Simple update processing` delete the file `data-bot-bash/webhook-fifo` after your webhook is working.
|
||||
All webhook calls are now forwarded to `bin/process_update.sh` for processing.
|
||||
|
||||
To start `Simple processing ` enable webhook on Telegram (_see below_).
|
||||
|
||||
Every incoming Telegram update load Bashbot once for processing one command. Even it seems overkill to load
|
||||
Bashbot on every incoming update, it's more responsive and create less server load for low traffic bots.
|
||||
|
||||
If your bot uses `addons` or `BASHBOT_EVENTs` you can't use `Simple processing`.
|
||||
|
||||
*Note:* `Simple processing` works without running `bashbot.sh start`.
|
||||
|
||||
|
||||
#### High traffic processing
|
||||
|
||||
#### CURRENTLY NOT IMPLEMENTED
|
||||
|
||||
High traffic processing writes Telegram updates to the named pipe `data-bot-bash/webhook-fifo`
|
||||
and Bashbot poll them, this is much more efficient than polling Telegram server.
|
||||
|
||||
To switch from `Simple processing` to `High traffic processing` start bashbot as `bashbot.sh start-webhook`.
|
||||
Stop bashbot with `bashbot.sh stop` to switch back to `Simple processing`
|
||||
|
||||
|
||||
#### Enable webhook on Telegram
|
||||
|
||||
To get updates via webhook your server must be reachable from the internet and you must
|
||||
instruct Telegram where to deliver updates, this is done by calling bashbot function `set_webhook`.
|
||||
|
||||
*Example:*
|
||||
|
||||
```bash
|
||||
bin/any_command.sh set_webhook "https://myserver.com/telegram"
|
||||
```
|
||||
|
||||
instruct Telegram to use the URL `https://myserver.com/telegram/<your_bot_token>/` to deliver updates.
|
||||
After you enable webhook to deliver Telegram updates it's no more possible to poll updates with `bashbot.sh start`.
|
||||
|
||||
To stop delivering of Telegram updates via webhook run `bin/any_command.sh delete_webhook`.
|
||||
|
||||
**Important**: Only https connections with a valid certificate chain are allowed as endpoint for webhook.
|
||||
|
||||
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
96
examples/webhook/index.php
Normal file
96
examples/webhook/index.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/************************************************************
|
||||
* @file examples/webhook/index.php
|
||||
* @description example webhook implementation for apache
|
||||
* write to fifo/file if writeable, else pipe to command
|
||||
*
|
||||
* first line of BASHBOT_HOME is used as bot home (optional)
|
||||
* must start with /, not contain /. and min 20 characters long
|
||||
*
|
||||
* @author KayM (gnadelwartz), kay@rrr.de
|
||||
* @license http://www.wtfpl.net/txt/copying/ WTFPLv2
|
||||
* @since 30.01.2021 20:24
|
||||
*
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
***********************************************************/
|
||||
|
||||
// bashbot home dir
|
||||
$CONFIG_HOME='BASHBOT_HOME';
|
||||
$BASHBOT_HOME='/usr/local/telegram-bot-bash';
|
||||
// read from config file
|
||||
if (file_exists($CONFIG_HOME)) {
|
||||
$tmp = trim(fgets(fopen($CONFIG_HOME, 'r')));
|
||||
// start with '/', not '/.', min 20 chars
|
||||
if (substr($tmp,0,1) == '/' && strlen($tmp) >= 20 && strpos($tmp, '/.') === false) {
|
||||
$BASHBOT_HOME=$tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// script endpoint
|
||||
$cmd=$BASHBOT_HOME.'/bin/process_update.sh';
|
||||
// fifo endpoint
|
||||
$fifo=$BASHBOT_HOME.'/data-bot-bash/webhook-fifo';
|
||||
|
||||
// prepeare read, e.g. run from CLI
|
||||
$data='';
|
||||
$input="php://input";
|
||||
$json_file="json.txt";
|
||||
if (php_sapi_name() == "cli") {
|
||||
if(is_readable($json_file)) {
|
||||
$input=$json_file;
|
||||
} else {
|
||||
$input="php://stdin";
|
||||
}
|
||||
}
|
||||
// read request data
|
||||
if($json = file_get_contents($input)) {
|
||||
$data = $json;
|
||||
} else {
|
||||
$data = implode(" ",$_POST);
|
||||
if ($data == '') { $data = implode(" ",$_GET); }
|
||||
}
|
||||
// uncomment to save last received JSON
|
||||
// file_put_contents($json_file, $data);
|
||||
|
||||
// prepare for writing
|
||||
if ($data == '') {
|
||||
error_response(400, "No data received");
|
||||
}
|
||||
if (! chdir($BASHBOT_HOME)) {
|
||||
error_response(403, "No route to bot home");
|
||||
}
|
||||
|
||||
// fifo or command?
|
||||
if (! is_writeable($fifo)) {
|
||||
// pipe to command
|
||||
if (! file_exists($cmd)) {
|
||||
error_response(502, "Webhook endpoint not found");
|
||||
}
|
||||
if (! $handle = popen( $cmd.' debug', 'w' )) {
|
||||
error_response(503, "Can't open webhook command endpoint");
|
||||
}
|
||||
} else {
|
||||
// write to fifo
|
||||
if (! $handle = fopen( $fifo, 'a' )) {
|
||||
error_response(503, "Can't open webhook file endpoint");
|
||||
}
|
||||
flock($handle, LOCK_EX);
|
||||
}
|
||||
if (fwrite( $handle, str_replace(array("\n", "\r"), '',$data). PHP_EOL) === false) {
|
||||
error_response(504, "Write to webhook failed");
|
||||
}
|
||||
flock($handle, LOCK_UN);
|
||||
pclose($handle);
|
||||
/**/
|
||||
|
||||
function error_response($code, $msg) {
|
||||
$api = substr(php_sapi_name(), 0, 3);
|
||||
if ($api == 'cgi' || $api == 'fpm') {
|
||||
header('Status: '.$code.' '.$msg);
|
||||
} else {
|
||||
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
|
||||
header($protocol.' '.$code.' '.$msg);
|
||||
}
|
||||
exit('Error '.$code.': '.$msg. PHP_EOL);
|
||||
}
|
||||
?>
|
2
examples/webhook/json.txt
Normal file
2
examples/webhook/json.txt
Normal file
@ -0,0 +1,2 @@
|
||||
{"update_id":665220889,
|
||||
"message":{"message_id":760,"from":{"id":586928566,"is_bot":false,"first_name":"Kay","last_name":"M","username":"KayM","language_code":"de"},"chat":{"id":589682731,"first_name":"Kay","last_name":"M","username":"KayM","type":"private"},"date":1612029749,"text":"/info","entities":[{"offset":0,"length":5,"type":"bot_command"}]}}
|
@ -1,11 +1,11 @@
|
||||
#!/bin/bash
|
||||
# file: modules/alaises.sh
|
||||
# file: modules/aliases.sh
|
||||
# do not edit, this file will be overwritten on update
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
@ -31,70 +31,70 @@ inline_query_compose(){
|
||||
# title2Json title caption description markup inlinekeyboard
|
||||
case "$2" in
|
||||
# user provided media
|
||||
"article"|"message") # article ID title message (markup description)
|
||||
"article"|"message") # article ID title message (markup description)
|
||||
JSON='{"type":"article","id":"'${ID}'","input_message_content": {"message_text":"'$4'"} '$(title2Json "$3" "" "$5" "$6" "$7")'}'
|
||||
;;
|
||||
"photo") # photo ID photoURL (thumbURL title description caption)
|
||||
"photo") # photo ID photoURL (thumbURL title description caption)
|
||||
[ -z "$4" ] && tumb="$3"
|
||||
JSON='{"type":"photo","id":"'${ID}'","photo_url":"'$3'","thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$7" "$6" "$7" "$8")'}'
|
||||
;;
|
||||
"gif") # gif ID photoURL (thumbURL title caption)
|
||||
"gif") # gif ID photoURL (thumbURL title caption)
|
||||
[ -z "$4" ] && tumb="$3"
|
||||
JSON='{"type":"gif","id":"'${ID}'","gif_url":"'$3'", "thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$6" "$7" "$8" "$9")'}'
|
||||
;;
|
||||
"mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption)
|
||||
"mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption)
|
||||
[ -n "$4" ] && tumb='","thumb_url":"'$4'"'
|
||||
JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_url":"'$3'"'${tumb}$(title2Json "$5" "$6" "" "$7" "$8")'}'
|
||||
;;
|
||||
"video") # video ID videoURL mime thumbURL title (caption)
|
||||
"video") # video ID videoURL mime thumbURL title (caption)
|
||||
JSON='{"type":"video","id":"'${ID}'","video_url":"'$3'","mime_type":"'$4'","thumb_url":"'$5'"'$(title2Json "$6" "$7" "$8" "$9" "${10}")'}'
|
||||
;;
|
||||
"audio") # audio ID audioURL title (caption)
|
||||
"audio") # audio ID audioURL title (caption)
|
||||
JSON='{"type":"audio","id":"'${ID}'","audio_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
"voice") # voice ID voiceURL title (caption)
|
||||
"voice") # voice ID voiceURL title (caption)
|
||||
JSON='{"type":"voice","id":"'${ID}'","voice_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
"document") # document ID title documentURL mimetype (caption description)
|
||||
"document") # document ID title documentURL mimetype (caption description)
|
||||
JSON='{"type":"document","id":"'${ID}'","document_url":"'$4'","mime_type":"'$5'"'$(title2Json "$3" "$6" "$7" "$8" "$9")'}'
|
||||
;;
|
||||
"location") # location ID lat long title
|
||||
"location") # location ID lat long title
|
||||
JSON='{"type":"location","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'"}'
|
||||
;;
|
||||
"venue") # venue ID lat long title (address forsquare)
|
||||
"venue") # venue ID lat long title (address forsquare)
|
||||
[ -z "$6" ] && addr="$5"
|
||||
[ -n "$7" ] && fours=',"foursquare_id":"'$7'"'
|
||||
JSON='{"type":"venue","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'","address":"'$6${addr}'"'${fours}'}'
|
||||
;;
|
||||
"contact") # contact ID phone first (last thumb)
|
||||
"contact") # contact ID phone first (last thumb)
|
||||
[ -n "$5" ] && last=',"last_name":"'$5'"'
|
||||
[ -n "$6" ] && tumb='","thumb_url":"'$6'"'
|
||||
JSON='{"type":"contact","id":"'${ID}'","phone_number":"'$3'","first_name":"'$4'"'${last}'"}'
|
||||
;;
|
||||
# title2Json title caption description markup inlinekeyboard
|
||||
# Cached media stored in Telegram server
|
||||
"cached_photo") # photo ID file (title description caption)
|
||||
"cached_photo") # photo ID file (title description caption)
|
||||
JSON='{"type":"photo","id":"'${ID}'","photo_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}'
|
||||
;;
|
||||
"cached_gif") # gif ID file (title caption)
|
||||
"cached_gif") # gif ID file (title caption)
|
||||
JSON='{"type":"gif","id":"'${ID}'","gif_file_id":"'$3'"'$(title2Json "$4" "$5" "$6" "$7" "$8" )'}'
|
||||
;;
|
||||
"cached_mpeg4_gif") # mpeg ID file (title caption)
|
||||
"cached_mpeg4_gif") # mpeg ID file (title caption)
|
||||
JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_file_id":"'$3'"'$(title2Json "$4" "$5" "" "$6" "$7")'}'
|
||||
;;
|
||||
"cached_sticker") # sticker ID file
|
||||
"cached_sticker") # sticker ID file
|
||||
JSON='{"type":"sticker","id":"'${ID}'","sticker_file_id":"'$3'"}'
|
||||
;;
|
||||
"cached_document") # document ID title file (description caption)
|
||||
"cached_document") # document ID title file (description caption)
|
||||
JSON='{"type":"document","id":"'${ID}'","document_file_id":"'$4'"'$(title2Json "$3" "$6" "$5" "$6" "$7")'}'
|
||||
;;
|
||||
"cached_video") # video ID file title (description caption)
|
||||
"cached_video") # video ID file title (description caption)
|
||||
JSON='{"type":"video","id":"'${ID}'","video_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}'
|
||||
;;
|
||||
"cached_voice") # voice ID file title (caption)
|
||||
"cached_voice") # voice ID file title (caption)
|
||||
JSON='{"type":"voice","id":"'${ID}'","voice_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
"cached_audio") # audio ID file title (caption)
|
||||
"cached_audio") # audio ID file title (caption)
|
||||
JSON='{"type":"audio","id":"'${ID}'","audio_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
esac
|
||||
|
@ -6,7 +6,7 @@
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
# shellcheck disable=SC1117,SC2059
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
@ -48,10 +48,10 @@ start_back() {
|
||||
}
|
||||
restart_back() {
|
||||
local fifo; fifo="${DATADIR:-.}/$(procname "$1" "back-$3-")"
|
||||
log_message "Start background job CHAT=$1 JOB=${fifo##*/} CMD=${2##*/} $4 $5"
|
||||
log_update "Start background job CHAT=$1 JOB=${fifo##*/} CMD=${2##*/} $4 $5"
|
||||
check_back "$1" "$3" && kill_proc "$1" "back-$3-"
|
||||
nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"$1\" \"${fifo}\"; }" &>>"${fifo}.log" &
|
||||
sleep 0.5 # give bg job some time to init
|
||||
sleep 0.5 # give bg job some time to init
|
||||
}
|
||||
|
||||
|
||||
@ -62,7 +62,7 @@ start_proc() {
|
||||
[ -z "$2" ] && return
|
||||
[ -x "${2%% *}" ] || return 1
|
||||
local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
|
||||
log_message "Start interactive script CHAT=$1 JOB=${fifo##*/} CMD=$2 $3 $4"
|
||||
log_update "Start interactive script CHAT=$1 JOB=${fifo##*/} CMD=$2 $3 $4"
|
||||
check_proc "$1" && kill_proc "$1"
|
||||
mkfifo "${fifo}"
|
||||
nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"$1\" \"${fifo}\"
|
||||
@ -99,7 +99,7 @@ kill_proc() {
|
||||
fifo="$(procname "$1" "$2")"
|
||||
prid="$(proclist "${fifo}")"
|
||||
fifo="${DATADIR:-.}/${fifo}"
|
||||
log_message "Stop interactive / background CHAT=$1 JOB=${fifo##*/}"
|
||||
log_update "Stop interactive / background CHAT=$1 JOB=${fifo##*/}"
|
||||
# shellcheck disable=SC2086
|
||||
[ -n "${prid}" ] && kill ${prid}
|
||||
[ -s "${fifo}.log" ] || rm -f "${fifo}.log"
|
||||
@ -110,7 +110,7 @@ kill_proc() {
|
||||
# $2 message
|
||||
send_interactive() {
|
||||
local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
|
||||
[ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking!
|
||||
[ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking!
|
||||
}
|
||||
|
||||
# old style but may not work because of local checks
|
||||
@ -154,7 +154,7 @@ job_control() {
|
||||
"killb"*)
|
||||
printf "Kill Job: %s %s\n" "${proc}" " ${fifo##*/}"
|
||||
kill_proc "${CHAT}" "${job}"
|
||||
rm -f "${FILE}" # remove job
|
||||
rm -f "${FILE}" # remove job
|
||||
# inform botadmin about stop
|
||||
[ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} kill background jobs ..." &
|
||||
killall="y"
|
||||
|
@ -5,7 +5,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
@ -56,6 +56,12 @@ delete_chat_stickers() {
|
||||
}
|
||||
|
||||
# manage chat member functions -------
|
||||
# $1 chat
|
||||
chat_member_count() {
|
||||
sendJson "$1" "" "${URL}/getChatMembersCount"
|
||||
[ "${BOTSENT[OK]}" = "true" ] && printf "%s\n" "${BOTSENT[RESULT]}"
|
||||
}
|
||||
|
||||
kick_chat_member() {
|
||||
sendJson "$1" 'user_id: '"$2"'' "${URL}/kickChatMember"
|
||||
}
|
||||
@ -68,6 +74,34 @@ leave_chat() {
|
||||
sendJson "$1" "" "${URL}/leaveChat"
|
||||
}
|
||||
|
||||
# $1 chat, $2 userid, $3 ... "right[:true]" default false
|
||||
# right: is_anonymous change_info post_messages edit_messages delete_messages invite_users restrict_members pin_messages promote_member
|
||||
promote_chat_member() {
|
||||
local arg bool json chat="$1" user="$2; shift 2"
|
||||
for arg in "$@"
|
||||
do
|
||||
# default false
|
||||
bool=false; [ "${arg##*:}" = "true" ] && bool="true"
|
||||
# expand args
|
||||
case "${arg}" in
|
||||
*"anon"*) arg="is_anonymous";;
|
||||
*"change"*) arg="can_change_info";;
|
||||
*"post"*) arg="can_post_messages";;
|
||||
*"edit"*) arg="can_edit_messages";;
|
||||
*"delete"*) arg="can_delete_messages";;
|
||||
*"pin"*) arg="can_pin_messages";;
|
||||
*"invite"*) arg="can_invite_users";;
|
||||
*"restrict"*) arg="can_restrict_members";;
|
||||
*"promote"*) arg="can_promote_members";;
|
||||
*) [ -n "${BASHBOTDEBUG}" ] && debug_log "${FUNCNAME[0]}: unknown promotion ${arg}"
|
||||
continue;;
|
||||
esac
|
||||
# compose json
|
||||
[ -n "${json}" ] && json+=","
|
||||
json+='"'"${arg}"'": "'"${bool}"'"'
|
||||
done
|
||||
sendJson "${chat}" '"user_id":'"${user}"','"${json}"'' "${URL}/promoteChatMember"
|
||||
}
|
||||
|
||||
# bashbot specific functions ---------
|
||||
|
||||
@ -76,7 +110,7 @@ leave_chat() {
|
||||
get_chat_member_status() {
|
||||
sendJson "$1" '"user_id":'"$2"'' "${URL}/getChatMember"
|
||||
# shellcheck disable=SC2154
|
||||
JsonGetString '"result","status"' <<< "${res}"
|
||||
printf "%s\n" "${UPD["result,status"]}"
|
||||
}
|
||||
|
||||
user_is_creator() {
|
||||
|
@ -5,7 +5,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#
|
||||
# source from commands.sh to use jsonDB functions
|
||||
#
|
||||
@ -42,7 +42,7 @@ JSSH_KEYOK="[-${azAZo9},._]"
|
||||
# $1 - invalid charcaters are replaced with first character
|
||||
# or deleted if $1 is empty
|
||||
jssh_stripKey() { # tr: we must escape first - in [-a-z...]
|
||||
if [[ "$1" =~ ^${JSSH_KEYOK} ]]; then # tr needs [\-...
|
||||
if [[ "$1" =~ ^${JSSH_KEYOK} ]]; then # tr needs [\-...
|
||||
tr -c "${JSSH_KEYOK/\[-/[\\-}\r\n" "${1:0:1}"
|
||||
else
|
||||
tr -dc "${JSSH_KEYOK/\[-/[\\-}\r\n"
|
||||
@ -86,7 +86,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
||||
jssh_updateDB() {
|
||||
# for atomic update we can't use read/writeDB
|
||||
[ -z "$2" ] && return 1
|
||||
local DB="$2.jssh" # check in async
|
||||
local DB="$2.jssh" # check in async
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
{ flock -e -w 10 200; jssh_updateDB_async "$@"; } 200>"${DB}${JSSH_LOCKNAME}"
|
||||
}
|
||||
@ -95,7 +95,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
||||
# $1 key name, can only contain -a-zA-Z0-9,._
|
||||
# $2 key value
|
||||
# $3 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
alias jssh_insertDB=jssh_insertKeyDB # backward compatibility
|
||||
alias jssh_insertDB=jssh_insertKeyDB # backward compatibility
|
||||
# renamed to be more consistent
|
||||
jssh_insertKeyDB() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
@ -179,7 +179,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
||||
# medium complex, wrapper async
|
||||
jssh_updateArray() {
|
||||
[ -z "$2" ] && return 1
|
||||
local DB="$2.jssh" # name check in async
|
||||
local DB="$2.jssh" # name check in async
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
declare -n ARRAY="$1"
|
||||
[[ -z "${ARRAY[*]}" || "${DB}" -nt "${DB}.last$3" ]] && touch "${DB}.last$3" && jssh_readDB "$1" "$2"
|
||||
@ -216,7 +216,7 @@ jssh_newDB_async() { jssh_newDB "$@"; }
|
||||
jssh_newDB() {
|
||||
local DB; DB="$(jssh_checkDB "$1")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ -f "${DB}" ] && return 2 # already exist
|
||||
[ -f "${DB}" ] && return 2 # already exist
|
||||
touch "${DB}"
|
||||
}
|
||||
|
||||
|
496
modules/processUpdates.sh
Normal file
496
modules/processUpdates.sh
Normal file
@ -0,0 +1,496 @@
|
||||
#!/bin/bash
|
||||
##################################################################
|
||||
#
|
||||
# File: processUpdates.sh
|
||||
# Note: DO NOT EDIT! this file will be overwritten on update
|
||||
#
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
##################################################################
|
||||
|
||||
##############
|
||||
# manage webhooks
|
||||
|
||||
# $1 URL to sed updates to: https://host.dom[:port][/path], port and path are optional
|
||||
# port must be 443, 80, 88 8443, TOKEN will be added to URL for security
|
||||
# e.g. https://myhost.com -> https://myhost.com/12345678:azndfhbgdfbbbdsfg
|
||||
# $2 max connections 1-100 default 1 (because of bash ;-)
|
||||
set_webhook() {
|
||||
local url='"url": "'"$1/${BOTTOKEN}/"'"'
|
||||
local max=',"max_connections": 1'
|
||||
[[ "$2" =~ ^[0-9]+$ ]] && max=',"max_connections": '"$2"''
|
||||
# shellcheck disable=SC2153
|
||||
sendJson "" "${url}${max}" "${URL}/setWebhook"
|
||||
unset "BOTSENT[ID]" "BOTSENT[CHAT]"
|
||||
|
||||
}
|
||||
|
||||
get_webhook_info() {
|
||||
sendJson "" "" "${URL}/getWebhookInfo"
|
||||
if [ "${BOTSENT[OK]}" = "true" ]; then
|
||||
BOTSENT[URL]="${UPD[result,url]}"
|
||||
BOTSENT[COUNT]="${UPD[result,pending_update_count]}"
|
||||
BOTSENT[CERT]="${UPD[result,has_custom_certificate]}"
|
||||
BOTSENT[LASTERR]="${UPD[result,last_error_message]}"
|
||||
unset "BOTSENT[ID]" "BOTSENT[CHAT]"
|
||||
fi
|
||||
}
|
||||
|
||||
# $1 drop pending updates true/false, default false
|
||||
delete_webhook() {
|
||||
local drop; [ "$1" = "true" ] && drop='"drop_pending_updates": true'
|
||||
sendJson "" "${drop}" "${URL}/deleteWebhook"
|
||||
unset "BOTSENT[ID]" "BOTSENT[CHAT]"
|
||||
}
|
||||
|
||||
################
|
||||
# processing of updates starts here
|
||||
process_multi_updates() {
|
||||
local max num debug="$1"
|
||||
max="$(grep -F ',"update_id"]' <<< "${UPDATE}" | tail -1 | cut -d , -f 2 )"
|
||||
Json2Array 'UPD' <<<"${UPDATE}"
|
||||
for ((num=0; num<=max; num++)); do
|
||||
process_update "${num}" "${debug}"
|
||||
done
|
||||
}
|
||||
|
||||
process_update() {
|
||||
local num="$1" debug="$2"
|
||||
pre_process_message "${num}"
|
||||
# log message on debug
|
||||
[[ -n "${debug}" ]] && log_message "New Message ==========\n$(grep -F '["result",'"${num}" <<<"${UPDATE}")"
|
||||
|
||||
# check for users / groups to ignore
|
||||
jssh_updateArray_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
||||
[ -n "${USER[ID]}" ] && [[ -n "${BASHBOTBLOCKED[${USER[ID]}]}" || -n "${BASHBOTBLOCKED[${CHAT[ID]}]}" ]] && return
|
||||
|
||||
# process per message type
|
||||
if [ -n "${iQUERY[ID]}" ]; then
|
||||
process_inline_query "${num}" "${debug}"
|
||||
printf "%(%c)T: Inline Query update received FROM=%s iQUERY=%s\n" -1\
|
||||
"${iQUERY[USERNAME]:0:20} (${iQUERY[USER_ID]})" "${iQUERY[0]}" >>"${UPDATELOG}"
|
||||
elif [ -n "${iBUTTON[ID]}" ]; then
|
||||
process_inline_button "${num}" "${debug}"
|
||||
printf "%(%c)T: Inline Button update received FROM=%s CHAT=%s CALLBACK=%s DATA:%s \n" -1\
|
||||
"${iBUTTON[USERNAME]:0:20} (${iBUTTON[USER_ID]})" "${iBUTTON[CHAT_ID]}" "${iBUTTON[ID]}" "${iBUTTON[DATA]}" >>"${UPDATELOG}"
|
||||
else
|
||||
if grep -qs -e '\["result",'"${num}"',"edited_message"' <<<"${UPDATE}"; then
|
||||
# edited message
|
||||
UPDATE="${UPDATE//,${num},\"edited_message\",/,${num},\"message\",}"
|
||||
Json2Array 'UPD' <<<"${UPDATE}"
|
||||
MESSAGE[0]="/_edited_message "
|
||||
fi
|
||||
process_message "${num}" "${debug}"
|
||||
printf "%(%c)T: update received FROM=%s CHAT=%s CMD=%s\n" -1 "${USER[USERNAME]:0:20} (${USER[ID]})"\
|
||||
"${CHAT[USERNAME]:0:20}${CHAT[TITLE]:0:30} (${CHAT[ID]})"\
|
||||
"${MESSAGE:0:30}${CAPTION:0:30}$(: "${URLS[*]//bot*:}"; printf "%s" "${_//[A-Z-]}")" >>"${UPDATELOG}"
|
||||
fi
|
||||
#####
|
||||
# process inline and message events
|
||||
# first classic command dispatcher
|
||||
# shellcheck disable=SC2153,SC1090
|
||||
{ source "${COMMANDS}" "${debug}"; } &
|
||||
|
||||
# then all registered addons
|
||||
if [ -z "${iQUERY[ID]}" ]; then
|
||||
event_message "${debug}"
|
||||
else
|
||||
event_inline "${debug}"
|
||||
fi
|
||||
|
||||
# last count users
|
||||
jssh_countKeyDB_async "${CHAT[ID]}" "${COUNTFILE}"
|
||||
}
|
||||
|
||||
pre_process_message(){
|
||||
local num="$1"
|
||||
# unset everything to not have old values
|
||||
CMD=( ); iQUERY=( ); iBUTTON=(); MESSAGE=(); CHAT=(); USER=(); CONTACT=(); LOCATION=(); unset CAPTION
|
||||
REPLYTO=( ); FORWARD=( ); URLS=(); VENUE=( ); SERVICE=( ); NEWMEMBER=( ); LEFTMEMBER=( ); PINNED=( ); MIGRATE=( )
|
||||
iQUERY[ID]="${UPD["result,${num},inline_query,id"]}"
|
||||
iBUTTON[ID]="${UPD["result,${num},callback_query,id"]}"
|
||||
CHAT[ID]="${UPD["result,${num},message,chat,id"]}"
|
||||
USER[ID]="${UPD["result,${num},message,from,id"]}"
|
||||
[ -z "${CHAT[ID]}" ] && CHAT[ID]="${UPD["result,${num},edited_message,chat,id"]}"
|
||||
[ -z "${USER[ID]}" ] && USER[ID]="${UPD["result,${num},edited_message,from,id"]}"
|
||||
# always true
|
||||
return 0
|
||||
}
|
||||
|
||||
process_inline_query() {
|
||||
local num="$1"
|
||||
iQUERY[0]="$(JsonDecode "${UPD["result,${num},inline_query,query"]}")"
|
||||
iQUERY[USER_ID]="${UPD["result,${num},inline_query,from,id"]}"
|
||||
iQUERY[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,first_name"]}")"
|
||||
iQUERY[LAST_NAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,last_name"]}")"
|
||||
iQUERY[USERNAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,username"]}")"
|
||||
# always true
|
||||
return 0
|
||||
}
|
||||
|
||||
process_inline_button() {
|
||||
# debugging for impelemetation
|
||||
local num="$1"
|
||||
iBUTTON[DATA]="${UPD["result,${num},callback_query,data"]}"
|
||||
iBUTTON[CHAT_ID]="${UPD["result,${num},callback_query,message,chat,id"]}"
|
||||
iBUTTON[MESSAGE_ID]="${UPD["result,${num},callback_query,message,message_id"]}"
|
||||
iBUTTON[MESSAGE]="$(JsonDecode "${UPD["result,${num},callback_query,message,text"]}")"
|
||||
# XXX should we give back pressed button, all buttons or nothing?
|
||||
iBUTTON[USER_ID]="${UPD["result,${num},callback_query,from,id"]}"
|
||||
iBUTTON[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,first_name"]}")"
|
||||
iBUTTON[LAST_NAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,last_name"]}")"
|
||||
iBUTTON[USERNAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,username"]}")"
|
||||
# always true
|
||||
return 0
|
||||
}
|
||||
|
||||
process_message() {
|
||||
local num="$1"
|
||||
# Message
|
||||
MESSAGE[0]+="$(JsonDecode "${UPD["result,${num},message,text"]}" | sed 's|\\/|/|g')"
|
||||
MESSAGE[ID]="${UPD["result,${num},message,message_id"]}"
|
||||
|
||||
# Chat ID is now parsed when update is received
|
||||
CHAT[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,chat,last_name"]}")"
|
||||
CHAT[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,chat,first_name"]}")"
|
||||
CHAT[USERNAME]="$(JsonDecode "${UPD["result,${num},message,chat,username"]}")"
|
||||
# set real name as username if empty
|
||||
[ -z "${CHAT[USERNAME]}" ] && CHAT[USERNAME]="${CHAT[FIRST_NAME]} ${CHAT[LAST_NAME]}"
|
||||
CHAT[TITLE]="$(JsonDecode "${UPD["result,${num},message,chat,title"]}")"
|
||||
CHAT[TYPE]="$(JsonDecode "${UPD["result,${num},message,chat,type"]}")"
|
||||
CHAT[ALL_ADMIN]="${UPD["result,${num},message,chat,all_members_are_administrators"]}"
|
||||
|
||||
# user ID is now parsed when update is received
|
||||
USER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,first_name"]}")"
|
||||
USER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,last_name"]}")"
|
||||
USER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,from,username"]}")"
|
||||
# set real name as username if empty
|
||||
[ -z "${USER[USERNAME]}" ] && USER[USERNAME]="${USER[FIRST_NAME]} ${USER[LAST_NAME]}"
|
||||
|
||||
# in reply to message from
|
||||
if [ -n "${UPD["result,${num},message,reply_to_message,from,id"]}" ]; then
|
||||
REPLYTO[UID]="${UPD["result,${num},message,reply_to_message,from,id"]}"
|
||||
REPLYTO[0]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,text"]}")"
|
||||
REPLYTO[ID]="${UPD["result,${num},message,reply_to_message,message_id"]}"
|
||||
REPLYTO[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,first_name"]}")"
|
||||
REPLYTO[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,last_name"]}")"
|
||||
REPLYTO[USERNAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,username"]}")"
|
||||
fi
|
||||
|
||||
# forwarded message from
|
||||
if [ -n "${UPD["result,${num},message,forward_from,id"]}" ]; then
|
||||
FORWARD[UID]="${UPD["result,${num},message,forward_from,id"]}"
|
||||
FORWARD[ID]="${MESSAGE[ID]}" # same as message ID
|
||||
FORWARD[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,first_name"]}")"
|
||||
FORWARD[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,last_name"]}")"
|
||||
FORWARD[USERNAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,username"]}")"
|
||||
fi
|
||||
|
||||
# get file URL from telegram, check for any of them!
|
||||
if grep -qs -e '\["result",'"${num}"',"message","[avpsd].*,"file_id"\]' <<<"${UPDATE}"; then
|
||||
URLS[AUDIO]="$(get_file "${UPD["result,${num},message,audio,file_id"]}")"
|
||||
URLS[DOCUMENT]="$(get_file "${UPD["result,${num},message,document,file_id"]}")"
|
||||
URLS[PHOTO]="$(get_file "${UPD["result,${num},message,photo,0,file_id"]}")"
|
||||
URLS[STICKER]="$(get_file "${UPD["result,${num},message,sticker,file_id"]}")"
|
||||
URLS[VIDEO]="$(get_file "${UPD["result,${num},message,video,file_id"]}")"
|
||||
URLS[VOICE]="$(get_file "${UPD["result,${num},message,voice,file_id"]}")"
|
||||
fi
|
||||
# Contact, must have phone_number
|
||||
if [ -n "${UPD["result,${num},message,contact,phone_number"]}" ]; then
|
||||
CONTACT[USER_ID]="$(JsonDecode "${UPD["result,${num},message,contact,user_id"]}")"
|
||||
CONTACT[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,contact,first_name"]}")"
|
||||
CONTACT[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,contact,last_name"]}")"
|
||||
CONTACT[NUMBER]="${UPD["result,${num},message,contact,phone_number"]}"
|
||||
CONTACT[VCARD]="${UPD["result,${num},message,contact,vcard"]}"
|
||||
fi
|
||||
|
||||
# venue, must have a position
|
||||
if [ -n "${UPD["result,${num},message,venue,location,longitude"]}" ]; then
|
||||
VENUE[TITLE]="$(JsonDecode "${UPD["result,${num},message,venue,title"]}")"
|
||||
VENUE[ADDRESS]="$(JsonDecode "${UPD["result,${num},message,venue,address"]}")"
|
||||
VENUE[LONGITUDE]="${UPD["result,${num},message,venue,location,longitude"]}"
|
||||
VENUE[LATITUDE]="${UPD["result,${num},message,venue,location,latitude"]}"
|
||||
VENUE[FOURSQUARE]="${UPD["result,${num},message,venue,foursquare_id"]}"
|
||||
fi
|
||||
|
||||
# Caption
|
||||
CAPTION="$(JsonDecode "${UPD["result,${num},message,caption"]}")"
|
||||
|
||||
# Location
|
||||
LOCATION[LONGITUDE]="${UPD["result,${num},message,location,longitude"]}"
|
||||
LOCATION[LATITUDE]="${UPD["result,${num},message,location,latitude"]}"
|
||||
|
||||
# service messages, group or channel only!
|
||||
if [[ "${CHAT[ID]}" == "-"* ]] ; then
|
||||
# new chat member
|
||||
if [ -n "${UPD["result,${num},message,new_chat_member,id"]}" ]; then
|
||||
SERVICE[NEWMEMBER]="${UPD["result,${num},message,new_chat_member,id"]}"
|
||||
NEWMEMBER[ID]="${SERVICE[NEWMEMBER]}"
|
||||
NEWMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,first_name"]}")"
|
||||
NEWMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,last_name"]}")"
|
||||
NEWMEMBER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,username"]}")"
|
||||
NEWMEMBER[ISBOT]="${UPD["result,${num},message,new_chat_member,is_bot"]}"
|
||||
[ -z "${MESSAGE[0]}" ] &&\
|
||||
MESSAGE[0]="/_new_chat_member ${NEWMEMBER[ID]} ${NEWMEMBER[USERNAME]:=${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]}}"
|
||||
fi
|
||||
# left chat member
|
||||
if [ -n "${UPD["result,${num},message,left_chat_member,id"]}" ]; then
|
||||
SERVICE[LEFTMEMBER]="${UPD["result,${num},message,left_chat_member,id"]}"
|
||||
LEFTMEMBER[ID]="${SERVICE[LEFTMEBER]}"
|
||||
LEFTMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,first_name"]}")"
|
||||
LEFTMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,last_name"]}")"
|
||||
LEFTMEBER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,username"]}")"
|
||||
LEFTMEMBER[ISBOT]="${UPD["result,${num},message,left_chat_member,is_bot"]}"
|
||||
[ -z "${MESSAGE[0]}" ] &&\
|
||||
MESSAGE[0]="/_left_chat_member ${LEFTMEMBER[ID]} ${LEFTMEMBER[USERNAME]:=${LEFTMEMBER[FIRST_NAME]} ${LEFTMEMBER[LAST_NAME]}}"
|
||||
fi
|
||||
# chat title / photo, check for any of them!
|
||||
if grep -qs -e '\["result",'"${num}"',"message","new_chat_[tp]' <<<"${UPDATE}"; then
|
||||
SERVICE[NEWTITLE]="$(JsonDecode "${UPD["result,${num},message,new_chat_title"]}")"
|
||||
[ -z "${MESSAGE[0]}" ] && [ -n "${SERVICE[NEWTITLE]}" ] &&\
|
||||
MESSAGE[0]="/_new_chat_title ${USER[ID]} ${SERVICE[NEWTITLE]}"
|
||||
SERVICE[NEWPHOTO]="$(get_file "${UPD["result,${num},message,new_chat_photo,0,file_id"]}")"
|
||||
[ -z "${MESSAGE[0]}" ] && [ -n "${SERVICE[NEWPHOTO]}" ] &&\
|
||||
MESSAGE[0]="/_new_chat_photo ${USER[ID]} ${SERVICE[NEWPHOTO]}"
|
||||
fi
|
||||
# pinned message
|
||||
if [ -n "${UPD["result,${num},message,pinned_message,message_id"]}" ]; then
|
||||
SERVICE[PINNED]="${UPD["result,${num},message,pinned_message,message_id"]}"
|
||||
PINNED[ID]="${SERVICE[PINNED]}"
|
||||
PINNED[MESSAGE]="$(JsonDecode "${UPD["result,${num},message,pinned_message,text"]}")"
|
||||
[ -z "${MESSAGE[0]}" ] &&\
|
||||
MESSAGE[0]="/_new_pinned_message ${USER[ID]} ${PINNED[ID]} ${PINNED[MESSAGE]}"
|
||||
fi
|
||||
# migrate to super group
|
||||
if [ -n "${UPD["result,${num},message,migrate_to_chat_id"]}" ]; then
|
||||
MIGRATE[TO]="${UPD["result,${num},message,migrate_to_chat_id"]}"
|
||||
MIGRATE[FROM]="${UPD["result,${num},message,migrate_from_chat_id"]}"
|
||||
# CHAT is already migrated, so set new chat id
|
||||
[ "${CHAT[ID]}" = "${MIGRATE[FROM]}" ] && CHAT[ID]="${MIGRATE[FROM]}"
|
||||
SERVICE[MIGRATE]="${MIGRATE[FROM]} ${MIGRATE[TO]}"
|
||||
[ -z "${MESSAGE[0]}" ] &&\
|
||||
MESSAGE[0]="/_migrate_group ${SERVICE[MIGRATE]}"
|
||||
fi
|
||||
# set SERVICE to yes if a service message was received
|
||||
[[ "${SERVICE[*]}" =~ ^[[:blank:]]*$ ]] || SERVICE[0]="yes"
|
||||
fi
|
||||
|
||||
# split message in command and args
|
||||
[[ "${MESSAGE[0]}" == "/"* ]] && read -r CMD <<<"${MESSAGE[0]}" && CMD[0]="${CMD[0]%%@*}"
|
||||
# everything went well
|
||||
return 0
|
||||
}
|
||||
|
||||
#########################
|
||||
# main get updates loop, should never terminate
|
||||
declare -A BASHBOTBLOCKED
|
||||
start_bot() {
|
||||
local DEBUGMSG
|
||||
# startup message
|
||||
DEBUGMSG="Start BASHBOT updates in Mode \"${1:-normal}\" =========="
|
||||
log_update "${DEBUGMSG}"
|
||||
# redirect to Debug.log
|
||||
# shellcheck disable=SC2153
|
||||
[[ "$1" == *"debug" ]] && exec &>>"${DEBUGLOG}"
|
||||
log_debug "${DEBUGMSG}"; DEBUGMSG="$1"
|
||||
[[ "${DEBUGMSG}" == "xdebug"* ]] && set -x
|
||||
# cleaup old pipes and empty logfiles
|
||||
find "${DATADIR}" -type p -delete
|
||||
find "${DATADIR}" -size 0 -name "*.log" -delete
|
||||
# load addons on startup
|
||||
for addons in "${ADDONDIR:-.}"/*.sh ; do
|
||||
# shellcheck disable=SC1090
|
||||
[ -r "${addons}" ] && source "${addons}" "startbot" "${DEBUGMSG}"
|
||||
done
|
||||
# shellcheck disable=SC1090
|
||||
source "${COMMANDS}" "startbot"
|
||||
# start timer events
|
||||
if [ -n "${BASHBOT_START_TIMER}" ] ; then
|
||||
# shellcheck disable=SC2064
|
||||
trap "event_timer ${DEBUGMSG}" ALRM
|
||||
start_timer &
|
||||
# shellcheck disable=SC2064
|
||||
trap "kill -9 $!; exit" EXIT INT HUP TERM QUIT
|
||||
fi
|
||||
# cleanup countfile on startup
|
||||
jssh_deleteKeyDB "CLEAN_COUNTER_DATABASE_ON_STARTUP" "${COUNTFILE}"
|
||||
[ -f "${COUNTFILE}.jssh.flock" ] && rm -f "${COUNTFILE}.jssh.flock"
|
||||
# store start time and cleanup botconfig on startup
|
||||
jssh_updateKeyDB "startup" "$(_date)" "${BOTCONFIG}"
|
||||
[ -f "${BOTCONFIG}.jssh.flock" ] && rm -f "${BOTCONFIG}.jssh.flock"
|
||||
# read blocked users
|
||||
jssh_readDB_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
||||
# inform botadmin about start
|
||||
send_normal_message "$(getConfigKey "botadmin")" "Bot $(getConfigKey "botname") started ..." &
|
||||
##########
|
||||
# bot is ready, start processing updates ...
|
||||
get_updates "${DEBUGMSG}"
|
||||
}
|
||||
|
||||
|
||||
get_updates(){
|
||||
local errsleep="200" DEBUG="$1" OFFSET=0
|
||||
# adaptive sleep defaults
|
||||
local nextsleep="100"
|
||||
local stepsleep="${BASHBOT_SLEEP_STEP:-100}"
|
||||
local maxsleep="${BASHBOT_SLEEP:-5000}"
|
||||
while true; do
|
||||
# adaptive sleep in ms rounded to next 0.1 s
|
||||
sleep "$(_round_float "${nextsleep}e-3" "1")"
|
||||
# get next update
|
||||
# shellcheck disable=SC2153
|
||||
UPDATE="$(getJson "${URL}/getUpdates?offset=${OFFSET}" 2>/dev/null | "${JSONSHFILE}" -b -n 2>/dev/null | iconv -f utf-8 -t utf-8 -c)"
|
||||
# did we get an response?
|
||||
if [ -n "${UPDATE}" ]; then
|
||||
# we got something, do processing
|
||||
[ "${OFFSET}" = "-999" ] && [ "${nextsleep}" -gt "$((maxsleep*2))" ] &&\
|
||||
log_error "Recovered from timeout/broken/no connection, continue with telegram updates"
|
||||
# calculate next sleep interval
|
||||
((nextsleep+= stepsleep , nextsleep= nextsleep>maxsleep ?maxsleep:nextsleep))
|
||||
# escape bash $ expansion bug
|
||||
UPDATE="${UPDATE//$/\\$}"
|
||||
# warn if webhook is set
|
||||
if grep -q '^\["error_code"\] 409' <<<"${UPDATE}"; then
|
||||
[ "${OFFSET}" != "-999" ] && nextsleep="${stepsleep}"
|
||||
OFFSET="-999"; errsleep="$(_round_float "$(( errsleep= 300*nextsleep ))e-3")"
|
||||
log_error "Warning conflicting webhook set, can't get updates until your run delete_webhook! Sleep $((errsleep/60)) min ..."
|
||||
sleep "${errsleep}"
|
||||
continue
|
||||
fi
|
||||
# Offset
|
||||
OFFSET="$(grep <<<"${UPDATE}" '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)"
|
||||
((OFFSET++))
|
||||
|
||||
if [ "${OFFSET}" != "1" ]; then
|
||||
nextsleep="100"
|
||||
process_multi_updates "${DEBUG}"
|
||||
fi
|
||||
else
|
||||
# oops, something bad happened, wait maxsleep*10
|
||||
(( nextsleep=nextsleep*2 , nextsleep= nextsleep>maxsleep*10 ?maxsleep*10:nextsleep ))
|
||||
# second time, report problem
|
||||
if [ "${OFFSET}" = "-999" ]; then
|
||||
log_error "Repeated timeout/broken/no connection on telegram update, sleep $(_round_float "${nextsleep}e-3")s"
|
||||
# try to recover
|
||||
if _is_function bashbotBlockRecover && [ -z "$(getJson "${ME_URL}")" ]; then
|
||||
log_error "Try to recover, calling bashbotBlockRecover ..."
|
||||
bashbotBlockRecover >>"${ERRORLOG}"
|
||||
fi
|
||||
fi
|
||||
OFFSET="-999"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
declare -Ax BASHBOT_EVENT_INLINE BASHBOT_EVENT_MESSAGE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLYTO BASHBOT_EVENT_FORWARD BASHBOT_EVENT_SEND
|
||||
declare -Ax BASHBOT_EVENT_CONTACT BASHBOT_EVENT_LOCATION BASHBOT_EVENT_FILE BASHBOT_EVENT_TEXT BASHBOT_EVENT_TIMER BASHBOT_BLOCKED
|
||||
|
||||
start_timer(){
|
||||
# send alarm every ~60 s
|
||||
while :; do
|
||||
sleep 59.5
|
||||
kill -ALRM $$
|
||||
done;
|
||||
}
|
||||
|
||||
EVENT_TIMER="0"
|
||||
event_timer() {
|
||||
local key timer debug="$1"
|
||||
(( EVENT_TIMER++ ))
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_TIMER[@]}"
|
||||
do
|
||||
timer="${key##*,}"
|
||||
[[ ! "${timer}" =~ ^-*[1-9][0-9]*$ ]] && continue
|
||||
if [ "$(( EVENT_TIMER % timer ))" = "0" ]; then
|
||||
_exec_if_function "${BASHBOT_EVENT_TIMER[${key}]}" "timer" "${key}" "${debug}"
|
||||
[ "$(( EVENT_TIMER % timer ))" -lt "0" ] && \
|
||||
unset BASHBOT_EVENT_TIMER["${key}"]
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
event_inline() {
|
||||
local key debug="$1"
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_INLINE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_INLINE[${key}]}" "inline" "${key}" "${debug}"
|
||||
done
|
||||
}
|
||||
event_message() {
|
||||
local key debug="$1"
|
||||
# ${MESSAEG[*]} event_message
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_MESSAGE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_MESSAGE[${key}]}" "message" "${key}" "${debug}"
|
||||
done
|
||||
|
||||
# ${TEXT[*]} event_text
|
||||
if [ -n "${MESSAGE[0]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_TEXT[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_TEXT[${key}]}" "text" "${key}" "${debug}"
|
||||
done
|
||||
|
||||
# ${CMD[*]} event_cmd
|
||||
if [ -n "${CMD[0]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_CMD[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_CMD[${key}]}" "command" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
# ${REPLYTO[*]} event_replyto
|
||||
if [ -n "${REPLYTO[UID]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_REPLYTO[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_REPLYTO[${key}]}" "replyto" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${FORWARD[*]} event_forward
|
||||
if [ -n "${FORWARD[UID]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_FORWARD[@]}"
|
||||
do
|
||||
_exec_if_function && "${BASHBOT_EVENT_FORWARD[${key}]}" "forward" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${CONTACT[*]} event_contact
|
||||
if [ -n "${CONTACT[FIRST_NAME]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_CONTACT[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_CONTACT[${key}]}" "contact" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${VENUE[*]} event_location
|
||||
# ${LOCATION[*]} event_location
|
||||
if [ -n "${LOCATION[LONGITUDE]}" ] || [ -n "${VENUE[TITLE]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_LOCATION[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_LOCATION[${key}]}" "location" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${URLS[*]} event_file
|
||||
# NOTE: compare again #URLS -1 blanks!
|
||||
if [[ "${URLS[*]}" != " " ]]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_FILE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_FILE[${key}]}" "file" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
# shellcheck disable=SC1117
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
@ -137,15 +137,63 @@ remove_keyboard() {
|
||||
#JSON='"text":"$2", "reply_markup": {"remove_keyboard":true}'
|
||||
}
|
||||
|
||||
# buttons will specified as "texts
|
||||
#|url" ... "text|url" empty arg starts new row
|
||||
# url not starting with http:// or https:// will be send as callback_data
|
||||
send_inline_buttons(){
|
||||
send_inline_keyboard "$1" "$2" "$(_button_row "${@:3}")"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 message-id $3 buttons
|
||||
# buttons will specified as "text|url" ... "text|url" empty arg starts new row
|
||||
# url not starting with http:// or https:// will be send as callback_data
|
||||
edit_inline_buttons(){
|
||||
edit_inline_keyboard "$1" "$2" "$(_button_row "${@:3}")"
|
||||
}
|
||||
|
||||
|
||||
# $1 CHAT $2 message $3 button text $4 button url
|
||||
send_button() {
|
||||
send_inline_keyboard "$1" "$2" '[{"text":"'"$(JsonEscape "$3")"'", "url":"'"$4"'"}]'
|
||||
}
|
||||
|
||||
# helper function to create json for a button row
|
||||
# buttons will specified as "text|url" ... "text|url" empty arg starts new row
|
||||
# url not starting with http:// or https:// will be send as callback_data
|
||||
_button_row() {
|
||||
[ -z "$1" ] && return 1
|
||||
local arg type json sep
|
||||
for arg in "$@"
|
||||
do
|
||||
[ -z "${arg}" ] && sep="],[" && continue
|
||||
type="callback_data"
|
||||
[[ "${arg##*|}" =~ ^(https*://|tg://) ]] && type="url"
|
||||
json+="${sep}"'{"text":"'"$(JsonEscape "${arg%|*}")"'", "'"${type}"'":"'"${arg##*|}"'"}'
|
||||
sep=","
|
||||
done
|
||||
printf "[%s]" "${json}"
|
||||
}
|
||||
|
||||
# raw inline functions, for special use
|
||||
# $1 CHAT $2 message-id $3 keyboard
|
||||
edit_inline_keyboard() {
|
||||
sendJson "$1" '"message_id":'"$2"', "reply_markup": {"inline_keyboard": [ '"$3"' ]}' "${URL}/editMessageReplyMarkup"
|
||||
# JSON='"message_id":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}'
|
||||
}
|
||||
|
||||
|
||||
# $1 CHAT $2 message $3 keyboard
|
||||
send_inline_keyboard() {
|
||||
local text; text='"text":"'$(JsonEscape "$2")'"'; [ -z "$2" ] && text='"text":"'"Keyboard:"'"'
|
||||
local text; text='"text":"'$(JsonEscape "$2")'"'; [ -z "$2" ] && text='"text":"..."'
|
||||
sendJson "$1" "${text}"', "reply_markup": {"inline_keyboard": [ '"$3"' ]}' "${MSG_URL}"
|
||||
# JSON='"text":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}'
|
||||
}
|
||||
# $1 CHAT $2 message $3 button text $4 URL
|
||||
send_button() {
|
||||
send_inline_keyboard "$1" "$2" '[ {"text":"'"$(JsonEscape "$3")"'", "url":"'"$4"'"}]'
|
||||
|
||||
# $1 callback id, $2 text to show, alert if not empty
|
||||
answer_callback_query() {
|
||||
local alert
|
||||
[ -n "$3" ] && alert='","show_alert": true'
|
||||
sendJson "" '"callback_query_id": "'"$1"'","text":"'"$2${alert}"'"' "${URL}/answerCallbackQuery"
|
||||
}
|
||||
|
||||
# $1 chat, $2 file_id on telegram server
|
||||
@ -160,7 +208,7 @@ if detect_curl ; then
|
||||
# $1 chat $3 ... $n URL or ID
|
||||
send_album(){
|
||||
[ -z "$1" ] && return 1
|
||||
[ -z "$3" ] && return 2 # minimum 2 files
|
||||
[ -z "$3" ] && return 2 # minimum 2 files
|
||||
local CHAT JSON IMAGE; CHAT="$1"; shift
|
||||
for IMAGE in "$@"
|
||||
do
|
||||
@ -196,13 +244,13 @@ send_file(){
|
||||
else
|
||||
# we have a file, check file location ...
|
||||
media="FILE"
|
||||
[[ "${file}" = *'..'* || "${file}" = '.'* ]] && err=1 # no directory traversal
|
||||
[[ "${file}" = *'..'* || "${file}" = '.'* ]] && err=1 # no directory traversal
|
||||
if [[ "${file}" = '/'* ]] ; then
|
||||
[[ ! "${file}" =~ ${FILE_REGEX} ]] && err=2 # absolute must match REGEX
|
||||
[[ ! "${file}" =~ ${FILE_REGEX} ]] && err=2 # absolute must match REGEX
|
||||
else
|
||||
file="${UPLOADDIR:-NOUPLOADDIR}/${file}" # others must be in UPLOADDIR
|
||||
file="${UPLOADDIR:-NOUPLOADDIR}/${file}" # others must be in UPLOADDIR
|
||||
fi
|
||||
[ ! -r "${file}" ] && err=3 # and file must exits of course
|
||||
[ ! -r "${file}" ] && err=3 # and file must exits of course
|
||||
# file path error, generate error response
|
||||
if [ -n "${err}" ]; then
|
||||
BOTSENT=(); BOTSENT[OK]="false"
|
||||
@ -295,7 +343,7 @@ forward_message() {
|
||||
[ -z "$3" ] && return
|
||||
sendJson "$1" '"from_chat_id": '"$2"', "message_id": '"$3"'' "${URL}/forwardMessage"
|
||||
}
|
||||
forward() { # backward compatibility
|
||||
forward() { # backward compatibility
|
||||
forward_message "$@" || return
|
||||
}
|
||||
|
||||
@ -323,7 +371,7 @@ send_message() {
|
||||
sent=y
|
||||
fi
|
||||
if [ -n "${keyboard}" ]; then
|
||||
if [[ "${keyboard}" != *"["* ]]; then # pre 0.60 style
|
||||
if [[ "${keyboard}" != *"["* ]]; then # pre 0.60 style
|
||||
keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]"
|
||||
fi
|
||||
send_keyboard "$1" "${text}" "${keyboard}"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC2034
|
||||
#######################################################
|
||||
#
|
||||
# File: mycommands.conf
|
||||
@ -11,7 +12,7 @@
|
||||
# Author: KayM (gnadelwartz), kay@rrr.de
|
||||
# Created: 09.01.2021 07:27
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#######################################################
|
||||
|
||||
##########
|
||||
@ -46,6 +47,10 @@ Edit commands and messages in mycommands.sh!
|
||||
# To enable this option in your bot, send the /setinline command to @BotFather.
|
||||
export INLINE="0"
|
||||
|
||||
# Set CALLBACK to 1 in order to receive callback queries.
|
||||
# callbacks are sent from inline_keyboards (buttons) attached tp bot messages
|
||||
export CALLBACK="0"
|
||||
|
||||
# if your bot is group admin it get commands sent to other bots
|
||||
# Set MEONLY to 1 to ignore commands sent to other bots
|
||||
export MEONLY="0"
|
||||
@ -63,7 +68,11 @@ unset BASHBOT_RETRY
|
||||
|
||||
# set value for adaptive sleeping while waiting for uodates in millisconds
|
||||
# max slepp between polling updates 10s (default 5s)
|
||||
export BASHBOT_SLEEP="10000"
|
||||
# export BASHBOT_SLEEP="10000"
|
||||
|
||||
# max slepp between polling updates 2s (default 5s)
|
||||
# export BASHBOT_SLEEP="2000"
|
||||
|
||||
# add 0.2s if no update available, up to BASHBOT_SLEEP (default 0.1s)
|
||||
export BASHBOT_SLEEP_STEP="200"
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
# License: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# Author: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#######################################################
|
||||
# shellcheck disable=SC1117
|
||||
|
||||
@ -131,6 +131,9 @@ else
|
||||
'/echo'*) # example echo command
|
||||
send_normal_message "${CHAT[ID]}" "${MESSAGE}"
|
||||
;;
|
||||
'/button'*)# inline button, set CALLBACK=1 for processing callbacks
|
||||
send_inline_buttons "${CHAT[ID]}" "Press Button ..." " Button |RANDOM-BUTTON"
|
||||
;;
|
||||
'/question'*) # start interactive questions
|
||||
checkproc
|
||||
if [ "${res}" -gt 0 ] ; then
|
||||
@ -179,6 +182,47 @@ else
|
||||
esac
|
||||
}
|
||||
|
||||
mycallbacks() {
|
||||
#######################
|
||||
# callbacks from buttons attached to messages will be processed here
|
||||
# no standard use case for processing callbacks, let's log them for some users and chats
|
||||
case "${iBUTTON[USER_ID]}+${iBUTTON[CHAT_ID]}" in
|
||||
'USERID1+'*) # do something for all callbacks from USER
|
||||
printf "%s: U=%s C=%s D=%s\n" "$(date)" "${iBUTTON[USER_ID]}" "${iBUTTON[CHAT_ID]}" "${iBUTTON[DATA]}"\
|
||||
>>"${DATADIR}/${iBUTTON[USER_ID]}.log"
|
||||
answer_callback_query "${iBUTTON[ID]}" "Request has been logged in your user log..."
|
||||
return
|
||||
;;
|
||||
*'+CHATID1') # do something for all callbacks from CHAT
|
||||
printf "%s: U=%s C=%s D=%s\n" "$(date)" "${iBUTTON[USER_ID]}" "${iBUTTON[CHAT_ID]}" "${iBUTTON[DATA]}"\
|
||||
>>"${DATADIR}/${iBUTTON[CHAT_ID]}.log"
|
||||
answer_callback_query "${iBUTTON[ID]}" "Request has been logged in chat log..."
|
||||
return
|
||||
;;
|
||||
'USERID2+CHATID2') # do something only for callbacks form USER in CHAT
|
||||
printf "%s: U=%s C=%s D=%s\n" "$(date)" "${iBUTTON[USER_ID]}" "${iBUTTON[CHAT_ID]}" "${iBUTTON[DATA]}"\
|
||||
>>"${DATADIR}/${iBUTTON[USER_ID]}-${iBUTTON[CHAT_ID]}.log"
|
||||
answer_callback_query "${iBUTTON[ID]}" "Request has been logged in user-chat log..."
|
||||
return
|
||||
;;
|
||||
*) # all other callbacks are processed here
|
||||
local callback_answer
|
||||
# your processing here ...
|
||||
# message available?
|
||||
if [[ -n "${iBUTTON[CHAT_ID]}" && -n "${iBUTTON[MESSAGE_ID]}" ]]; then
|
||||
if [ "${iBUTTON[DATA]}" = "RANDOM-BUTTON" ]; then
|
||||
callback_answer="Button pressed"
|
||||
edit_inline_buttons "${iBUTTON[CHAT_ID]}" "${iBUTTON[MESSAGE_ID]}" "Button ${RANDOM}|RANDOM-BUTTON"
|
||||
fi
|
||||
else
|
||||
callback_answer="Button to old, sorry."
|
||||
fi
|
||||
# Telegram needs an ack each callback query, default empty
|
||||
answer_callback_query "${iBUTTON[ID]}" "${callback_answer}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
myinlines() {
|
||||
#######################
|
||||
# Inline query examples, do not use them in production (except image search ;-)
|
||||
|
@ -10,7 +10,7 @@
|
||||
# License: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# Author: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#######################################################
|
||||
# shellcheck disable=SC1117
|
||||
|
||||
@ -55,6 +55,8 @@ else
|
||||
[ -n "${REMOVEKEYBOARD}" ] && remove_keyboard "${CHAT[ID]}" &
|
||||
[[ -n "${REMOVEKEYBOARD_PRIVATE}" && "${CHAT[ID]}" == "${USER[ID]}" ]] && remove_keyboard "${CHAT[ID]}" &
|
||||
|
||||
# uncommet to fix first letter upper case because of smartphone auto correction
|
||||
#[[ "${MESSAGE}" =~ ^/[[:upper:]] ]] && MESSAGE="${MESSAGE:0:1}$(tr '[:upper:]' '[:lower:]' <<<"${MESSAGE:1:1}")${MESSAGE:2}"
|
||||
case "${MESSAGE}" in
|
||||
##################
|
||||
# example command, replace them by your own
|
||||
@ -77,6 +79,19 @@ else
|
||||
esac
|
||||
}
|
||||
|
||||
mycallbacks() {
|
||||
#######################
|
||||
# callbacks from buttons attached to messages will be processed here
|
||||
case "${iBUTTON[USER_ID]}+${iBUTTON[CHAT_ID]}" in
|
||||
*) # all other callbacks are processed here
|
||||
local callback_answer
|
||||
: # your processing here ...
|
||||
:
|
||||
# Telegram needs an ack each callback query, default empty
|
||||
answer_callback_query "${iBUTTON[ID]}" "${callback_answer}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
myinlines() {
|
||||
#######################
|
||||
# this fuinction is called only if you has set INLINE=1 !!
|
||||
|
@ -12,7 +12,7 @@
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
########################################################################
|
||||
|
||||
######
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
|
@ -11,7 +11,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# common variables
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
../dev/hooks/pre-commit.sh
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
|
||||
# include common functions and definitions
|
||||
# shellcheck source=test/ALL-tests.inc.sh
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
@ -41,7 +41,7 @@ source <( printf 'UPD=( %s )' "$(sed <<<"${UPDATE}" -E -e 's/\t/=/g' -e 's/=(tru
|
||||
printf "Check process_inline ...\n"
|
||||
printf " ... with JsonDecode Bash\n"
|
||||
set -x
|
||||
{ process_inline "0"; set +x; } >>"${LOGFILE}" 2>&1;
|
||||
{ process_inline_query "0"; set +x; } >>"${LOGFILE}" 2>&1;
|
||||
|
||||
# output processed input
|
||||
print_array "iQUERY" >"${OUTPUTFILE}"
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
@ -34,10 +34,10 @@ URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?12345
|
||||
chat:123456 JSON:"text":"\# test for new inline button"
|
||||
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
|
||||
|
||||
chat:123456 JSON:"text":"Text plus keyboard will appear in chat", "reply_markup": {"inline_keyboard": [ [ {"text":"Button Text", "url":"https://www..."}] ]}
|
||||
chat:123456 JSON:"text":"Text plus keyboard will appear in chat", "reply_markup": {"inline_keyboard": [ [{"text":"Button Text", "url":"https://www..."}] ]}
|
||||
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
|
||||
|
||||
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"}] ]}
|
||||
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"}] ]}
|
||||
URL:https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?123456789:BASHBOTTESTSCRIPTbashbottestscript_/sendMessage
|
||||
|
||||
chat:123456 JSON:"text":"\# test for sendfile"
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
@ -10,7 +10,7 @@
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.30-0-g3266427
|
||||
#### $$VERSION$$ v1.40-0-gf9dab50
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
Loading…
Reference in New Issue
Block a user