fix misspellings

This commit is contained in:
Kay Marquardt (Gnadelwartz) 2019-05-30 12:14:23 +02:00
parent 60b1a59a8e
commit 405276bbbc
52 changed files with 7435 additions and 13 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,208 @@
#!/bin/sh
throw() {
echo "$*" >&2
exit 1
}
BRIEF=0
LEAFONLY=0
PRUNE=0
NO_HEAD=0
NORMALIZE_SOLIDUS=0
usage() {
echo
echo "Usage: JSON.sh [-b] [-l] [-p] [-s] [-h]"
echo
echo "-p - Prune empty. Exclude fields with empty values."
echo "-l - Leaf only. Only show leaf nodes, which stops data duplication."
echo "-b - Brief. Combines 'Leaf only' and 'Prune empty' options."
echo "-n - No-head. Do not show nodes that have no path (lines that start with [])."
echo "-s - Remove escaping of the solidus symbol (straight slash)."
echo "-h - This help text."
echo
}
parse_options() {
set -- "$@"
local ARGN=$#
while [ "$ARGN" -ne 0 ]
do
case $1 in
-h) usage
exit 0
;;
-b) BRIEF=1
LEAFONLY=1
PRUNE=1
;;
-l) LEAFONLY=1
;;
-p) PRUNE=1
;;
-n) NO_HEAD=1
;;
-s) NORMALIZE_SOLIDUS=1
;;
?*) echo "ERROR: Unknown option."
usage
exit 0
;;
esac
shift 1
ARGN=$((ARGN-1))
done
}
awk_egrep () {
local pattern_string=$1
gawk '{
while ($0) {
start=match($0, pattern);
token=substr($0, start, RLENGTH);
print token;
$0=substr($0, start+RLENGTH);
}
}' pattern="$pattern_string"
}
tokenize () {
local GREP
local ESCAPE
local CHAR
if echo "test string" | egrep -ao --color=never "test" >/dev/null 2>&1
then
GREP='egrep -ao --color=never'
else
GREP='egrep -ao'
fi
if echo "test string" | egrep -o "test" >/dev/null 2>&1
then
ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
CHAR='[^[:cntrl:]"\\]'
else
GREP=awk_egrep
ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
CHAR='[^[:cntrl:]"\\\\]'
fi
local STRING="\"$CHAR*($ESCAPE$CHAR*)*\""
local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?'
local KEYWORD='null|false|true'
local SPACE='[[:space:]]+'
# Force zsh to expand $A into multiple words
local is_wordsplit_disabled=$(unsetopt 2>/dev/null | grep -c '^shwordsplit$')
if [ $is_wordsplit_disabled != 0 ]; then setopt shwordsplit; fi
$GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$"
if [ $is_wordsplit_disabled != 0 ]; then unsetopt shwordsplit; fi
}
parse_array () {
local index=0
local ary=''
read -r token
case "$token" in
']') ;;
*)
while :
do
parse_value "$1" "$index"
index=$((index+1))
ary="$ary""$value"
read -r token
case "$token" in
']') break ;;
',') ary="$ary," ;;
*) throw "EXPECTED , or ] GOT ${token:-EOF}" ;;
esac
read -r token
done
;;
esac
[ "$BRIEF" -eq 0 ] && value=$(printf '[%s]' "$ary") || value=
:
}
parse_object () {
local key
local obj=''
read -r token
case "$token" in
'}') ;;
*)
while :
do
case "$token" in
'"'*'"') key=$token ;;
*) throw "EXPECTED string GOT ${token:-EOF}" ;;
esac
read -r token
case "$token" in
':') ;;
*) throw "EXPECTED : GOT ${token:-EOF}" ;;
esac
read -r token
parse_value "$1" "$key"
obj="$obj$key:$value"
read -r token
case "$token" in
'}') break ;;
',') obj="$obj," ;;
*) throw "EXPECTED , or } GOT ${token:-EOF}" ;;
esac
read -r token
done
;;
esac
[ "$BRIEF" -eq 0 ] && value=$(printf '{%s}' "$obj") || value=
:
}
parse_value () {
local jpath="${1:+$1,}$2" isleaf=0 isempty=0 print=0
case "$token" in
'{') parse_object "$jpath" ;;
'[') parse_array "$jpath" ;;
# At this point, the only valid single-character tokens are digits.
''|[!0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;;
*) value=$token
# if asked, replace solidus ("\/") in json strings with normalized value: "/"
[ "$NORMALIZE_SOLIDUS" -eq 1 ] && value=$(echo "$value" | sed 's#\\/#/#g')
isleaf=1
[ "$value" = '""' ] && isempty=1
;;
esac
[ "$value" = '' ] && return
[ "$NO_HEAD" -eq 1 ] && [ -z "$jpath" ] && return
[ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 0 ] && print=1
[ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && [ $PRUNE -eq 0 ] && print=1
[ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 1 ] && [ "$isempty" -eq 0 ] && print=1
[ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && \
[ $PRUNE -eq 1 ] && [ $isempty -eq 0 ] && print=1
[ "$print" -eq 1 ] && printf "[%s]\t%s\n" "$jpath" "$value"
:
}
parse () {
read -r token
parse_value
read -r token
case "$token" in
'') ;;
*) throw "EXPECTED EOF GOT $token" ;;
esac
}
if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]);
then
parse_options "$@"
tokenize | parse
fi
# vi: expandtab sw=2 ts=2

View File

@ -0,0 +1,18 @@
This project is released to the public domain where applicable.
Otherwise, it is released under the terms of the WTFPLv2:
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@ -0,0 +1,195 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashbot README</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashbot README</h1>
</div>
<h2>
<img align="middle" src="https://raw.githubusercontent.com/odb/official-bash-logo/master/assets/Logos/Icons/PNG/64x64.png" > Bashbot - A Telegram bot written in bash.
</h2>
<p>Written by Drew (<span class="citation">@topkecleon</span>), Daniil Gentili (<span class="citation">@danogentili</span>), and Kay M (<span class="citation">@gnadelwartz</span>).</p>
<p>Contributions by JuanPotato, BigNerd95, TiagoDanin, and iicc1.</p>
<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>
<h2 id="prerequisites">Prerequisites</h2>
<p>Uses <a href="http://github.com/dominictarr/JSON.sh">JSON.sh</a>, but no more TMUX.</p>
<p>Even bashbot is written in bash, it depends on commands typically availible in a Unix/Linux Environment. More concret on the common commands provided by <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="html/7_develop.html">Developer Notes</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 availible on www.github.com</p>
<h2 id="documentation">Documentation</h2>
<ul>
<li><a href="https://core.telegram.org/bots">Introdution to Telegram Bots</a>
<ul>
<li><a href="https://core.telegram.org/bots#3-how-do-i-create-a-bot">One Bot to rule them all</a></li>
<li><a href="https://core.telegram.org/bots#commands">Bot commands</a></li>
</ul></li>
<li><a href="html/0_install.html">Install Bashbot</a>
<ul>
<li>Install release</li>
<li>Install from githup</li>
<li>Update Bashbot</li>
<li>Notes on Updates</li>
</ul></li>
<li><a href="html/1_firstbot.html">Create a new Telegram Bot with botfather</a></li>
<li><a href="html/2_usage.html">Getting Started</a>
<ul>
<li>Managing your Bot</li>
<li>Recieve data</li>
<li>Send messages</li>
<li>Send files, locations, keyboards</li>
</ul></li>
<li><a href="html/3_advanced.html">Advanced Features</a>
<ul>
<li>Access Control</li>
<li>Interactive Chats</li>
<li>Background Jobs</li>
<li>Inline queries</li>
</ul></li>
<li><a href="html/4_expert.html">Expert Use</a>
<ul>
<li>Handling UTF-8 character sets</li>
<li>Run as other user or system service</li>
<li>Scedule bashbot from Cron</li>
<li>Use from CLI and Scripts</li>
<li>Customize Bashbot Environment</li>
</ul></li>
<li><a href="html/5_practice.html">Best Practices</a>
<ul>
<li>Customize commands.sh</li>
<li>Seperate logic from commands</li>
<li>Test your Bot with shellcheck</li>
</ul></li>
<li><a href="html/6_reference.html">Function Reference</a>
<ul>
<li>Sending Messages, Files, Keyboards</li>
<li>User Access Control</li>
<li>Inline Queries</li>
<li>Background and Interactive Jobs</li>
</ul></li>
<li><a href="html/7_develop.html">Deveoper Notess</a>
<ul>
<li>Debug bashbot</li>
<li>Modules, addons, events</li>
<li>Setup your environment</li>
<li>Bashbot testsuite</li>
</ul></li>
<li><a href="examples/README.html">Examples Dir</a></li>
</ul>
<h3 id="your-really-first-bashbot-in-a-nutshell">Your really first bashbot in a nutshell</h3>
<p>To install and run bashbot you need acess to a linux/unix/bsd command line. If you dont know how to get accces to a linux/unix/bsd like command line you should stop reading here :-(</p>
<p>In addition you need a <a href="https://telegram.org">Telegram client</a> and a mobile phone to <a href="https://telegramguide.com/create-a-telegram-account/">register an account</a>. If you dont want to register for Telegram you should stop reading here ;-)</p>
<p>After youre registered to Telegram send a message to <span class="citation">[@botfather]</span>(https://telegram.me/botfather), <a href="html/1_firstbot.html">create a new Telegram Bot token</a> and write it down. You need the token to install the bot.</p>
<p>Now open a linux/unix/bsd terminal and check if bash is installed: <code>which bash &amp;&amp; echo &quot;bash installed!&quot;</code>. If you get an error message bash is not installed.</p>
<p>Create a new directory and change to it: <code>mkdir tbb; cd tbb</code> and download the latest *.tar.gz file from <a href="https://github.com/topkecleon/telegram-bot-bash/releases" class="uri">https://github.com/topkecleon/telegram-bot-bash/releases</a>. This can be done with the commands:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="fu">wget</span> -q https://github.com/<span class="va">$(</span><span class="fu">wget</span> -q https://github.com/topkecleon/telegram-bot-bash/releases/latest -O - <span class="kw">|</span> <span class="fu">egrep</span> <span class="st">&#39;/.*/.*/.*tar.gz&#39;</span> -o<span class="va">)</span></code></pre></div>
<p>Extract the *.tar.gz file and change to bashbot directory: <code>tar -xzf *.tar.gz; cd telegram-bot-bash</code>, install bashbot: <code>./bashbot.sh init</code> and enter your bot token when asked. All other questions can be answered by hitting the &lt;Return&gt; key.</p>
<p>Thats all, now you can start your bot with <code>./bashbot.sh start</code> and send him messages:</p>
<pre><code>/start
You are Botadmin
*Available commands*:
*• /start*: _Start bot and get this message_.
*• /help*: _Get this message_.
*• /info*: _Get shorter info message about this bot_....
/info
his is bashbot, the Telegram bot written entirely in bash.
It features background tasks and interactive chats, and can serve as an interface for CLI programs.</code></pre>
<p>For more Information on how to install, customize and use your new bot, read the <a href="#Documentation">Documentation</a></p>
<hr />
<h2 id="security-considerations">Security Considerations</h2>
<p>Running a Telegram Bot means it is connected to the public and you never know whats send to your Bot.</p>
<p>Bash scripts in general are not designed to be bullet proof, 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 from untrusted sources (messages, files, network) you must be as carefull as possible, e.g. set IFS appropriate, disable globbing (set -f) and quote everthing. In addition delete unused scripts and examples from your Bot, e.g. scripts notify, calc, question, and disable all not used commands.</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 extensive in bashbot development to enshure a high code quality, e.g. its not allowed to push changes without passing all shellcheck tests. In addition bashbot has a <a href="html/7_develop.html">test suite</a> to check if important functionality is working as expected.</p>
<h3 id="run-your-bot-as-a-restricted-user">Run your Bot as a restricted user</h3>
<p><strong>I recommend to run your bot as a user, with almost no access rights.</strong> All files your Bot have write access to are in danger to be overwritten/deleted if your bot is hacked. For the same reason ervery file your Bot can read is in danger to be disclosed. Restict your Bots access rigths to the absolute minimum.</p>
<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 Unix/Linux systems. See <a href="html/4_expert.html">Expert use</a> on how to run your Bot as an other user.</p>
<h3 id="secure-your-bot-installation">Secure your Bot installation</h3>
<p><strong>Your Bot configuration must no be readable from other users.</strong> Everyone who can read your Bots token can act as your Bot and has access to all chats your Bot is in!</p>
<p>Everyone with read access to your Bot files can extract your Bots data. Especially your Bot Token in <code>token</code> must be protected against other users. No one exept you must have write access to the Bot files. The Bot must be restricted to have write access to <code>count</code> and <code>tmp-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>
<h2 id="faq">FAQ</h2>
<h3 id="is-this-bot-insecure">Is this Bot insecure?</h3>
<p>Bashbot is not more (in)secure as any other Bot written in any other 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>
<h3 id="why-bash-and-not-the-much-better-xyz">Why Bash and not the much better xyz?</h3>
<p>Well, thats a damn good question … may be because Im an Unix/Linux admin from stone age. Nevertheless there are more reasons from my side:</p>
<ul>
<li>bashbot will run everywhere where bash is availible, from ebedded linux to mainframe</li>
<li>easy to integrate with other shell script, e.g. for sending system message / health status</li>
<li>no need to install or learn a new programming language, library or framework</li>
<li>no database, not event driven, not OO …</li>
</ul>
<h3 id="can-i-have-the-single-bashbot.sh-file-back">Can I have the single bashbot.sh file back?</h3>
<p>At the beginning bashbot was simply the file <code>bashbot.sh</code> you can 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="html/7_develop.html">Create a stripped down Version of your Bot</a></p>
<h3 id="can-i-send-messages-from-cli-and-scripts">Can I send messages from CLI and scripts?</h3>
<p>Of course, you can send messages from CLI and scripts, simply install bashbot as <a href="#Your-really-first-bashbot-in-a-nutshell">described here</a>, send the messsage /start to set yourself as botadmin and stop the bot with <code>./bashbot.sh kill</code>.</p>
<p>Run the following commands in your bash shell or script while you are in the installation directory:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># prepare bash / script to send commands</span>
<span class="bu">export</span> <span class="va">BASHBOT_HOME=</span><span class="st">&quot;</span><span class="va">$(</span><span class="bu">pwd</span><span class="va">)</span><span class="st">&quot;</span>
<span class="bu">source</span> ./bashbot.sh source
<span class="co"># send me a test message</span>
<span class="ex">send_message</span> <span class="st">&quot;</span><span class="va">$(</span><span class="fu">cat</span> <span class="st">&quot;</span><span class="va">$BOTADMIN</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span> <span class="st">&quot;test&quot;</span>
<span class="co"># send me output of a system command</span>
<span class="ex">send_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span><span class="st">&quot;</span><span class="va">$BOTADMIN</span><span class="st">&quot;</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$(</span><span class="fu">df</span> -h<span class="va">)</span><span class="st">&quot;</span></code></pre></div>
<p>For more information see <a href="html/8_custom.html">Expert Use</a></p>
<h3 id="why-do-i-get-expected-value-got-eof-on-start">Why do I get “EXPECTED value GOT EOF” on start?</h3>
<p>May be your IP is blocked by telegram. You can test this by running curl or wget manually:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">curl</span> -m 10 https://api.telegram.org/bot
<span class="co">#curl: (28) Connection timed out after 10001 milliseconds</span>
<span class="fu">wget</span> -t 1 -T 10 https://api.telegram.org/bot
<span class="co">#Connecting to api.telegram.org (api.telegram.org)|46.38.243.234|:443... failed: Connection timed out.</span></code></pre></div>
<p>This may happen if to many wrong requests are sent to api.telegram.org, e.g. using a wrong token or not existing API calls. If you have a fixed IP you can ask telegram service to unblock your ip or change your IP. If you are running a tor proxy on your server you may uncomment the <code>BASHBOT_CURL_ARGS</code> line in mycommands.sh</p>
<p><span class="citation">@Gnadelwartz</span></p>
<h2 id="thats-it">Thats it!</h2>
<p>If you feel that theres something missing or if you found a bug, feel free to submit a pull request!</p>
<h4 id="version-v0.90-dev2-19-g5779acc"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-19-g5779acc</h4>
</body>
</html>

View File

@ -0,0 +1,184 @@
<h2><img align="middle" src="https://raw.githubusercontent.com/odb/official-bash-logo/master/assets/Logos/Icons/PNG/64x64.png" >
Bashbot - A Telegram bot written in bash.
</h2>
Written by Drew (@topkecleon), Daniil Gentili (@danogentili), and Kay M (@gnadelwartz).
Contributions by JuanPotato, BigNerd95, TiagoDanin, and iicc1.
Released to the public domain wherever applicable.
Elsewhere, consider it released under the [WTFPLv2](http://www.wtfpl.net/txt/copying/).
## Prerequisites
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh), but no more TMUX.
Even bashbot is written in bash, it depends on commands typically availible in a Unix/Linux Environment.
More concret on the common commands provided by [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)
Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and [Downloads](https://github.com/topkecleon/telegram-bot-bash/releases) are availible on www.github.com
## Documentation
* [Introdution to Telegram Bots](https://core.telegram.org/bots)
* [One Bot to rule them all](https://core.telegram.org/bots#3-how-do-i-create-a-bot)
* [Bot commands](https://core.telegram.org/bots#commands)
* [Install Bashbot](doc/0_install.md)
* Install release
* Install from githup
* Update Bashbot
* Notes on Updates
* [Create a new Telegram Bot with botfather](doc/1_firstbot.md)
* [Getting Started](doc/2_usage.md)
* Managing your Bot
* Recieve data
* Send messages
* Send files, locations, keyboards
* [Advanced Features](doc/3_advanced.md)
* Access Control
* Interactive Chats
* Background Jobs
* Inline queries
* [Expert Use](doc/4_expert.md)
* Handling UTF-8 character sets
* Run as other user or system service
* Scedule bashbot from Cron
* Use from CLI and Scripts
* Customize Bashbot Environment
* [Best Practices](doc/5_practice.md)
* Customize commands.sh
* Seperate logic from commands
* Test your Bot with shellcheck
* [Function Reference](doc/6_reference.md)
* Sending Messages, Files, Keyboards
* User Access Control
* Inline Queries
* Background and Interactive Jobs
* [Deveoper Notes](doc/7_develop.md)
* Debug bashbot
* Modules, addons, events
* Setup your environment
* Bashbot testsuite
* [Examples Dir](examples/README.md)
### Your really first bashbot in a nutshell
To install and run bashbot you need acess to a linux/unix/bsd command line. If you don't know how to get accces to a linux/unix/bsd like command line you should stop reading here :-(
In addition you need a [Telegram client](https://telegram.org) and a mobile phone to [register an account](https://telegramguide.com/create-a-telegram-account/).
If you don't want to register for Telegram you should stop reading here ;-)
After you're registered to Telegram send a message to [@botfather](https://telegram.me/botfather),
[create a new Telegram Bot token](doc/1_firstbot.md) and write it down. You need the token to install the bot.
Now open a linux/unix/bsd terminal and check if bash is installed: ```which bash && echo "bash installed!"```.
If you get an error message bash is not installed.
Create a new directory and change to it: ```mkdir tbb; cd tbb``` and download the latest '*.tar.gz' file from
[https://github.com/topkecleon/telegram-bot-bash/releases](https://github.com/topkecleon/telegram-bot-bash/releases). This can be done with the commands:
```bash
wget -q https://github.com/$(wget -q https://github.com/topkecleon/telegram-bot-bash/releases/latest -O - | egrep '/.*/.*/.*tar.gz' -o)
```
Extract the '*.tar.gz' file and change to bashbot directory: ```tar -xzf *.tar.gz; cd telegram-bot-bash```,
install bashbot: ```./bashbot.sh init``` and enter your bot token when asked. All other questions can be answered
by hitting the \<Return\> key.
Thats all, now you can start your bot with ```./bashbot.sh start``` and send him messages:
```
/start
You are Botadmin
*Available commands*:
*• /start*: _Start bot and get this message_.
*• /help*: _Get this message_.
*• /info*: _Get shorter info message about this bot_....
/info
his is bashbot, the Telegram bot written entirely in bash.
It features background tasks and interactive chats, and can serve as an interface for CLI programs.
```
For more Information on how to install, customize and use your new bot, read the [Documentation](#Documentation)
----
## Security Considerations
Running a Telegram Bot means it is connected to the public and you never know whats send to your Bot.
Bash scripts in general are not designed to be bullet proof, so consider this Bot as a proof of concept. Bash programmers often struggle with 'quoting hell' and globbing, see [Implications of wrong quoting](https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells)
Whenever you are processing input from from untrusted sources (messages, files, network) you must be as carefull as possible, e.g. set IFS appropriate, disable globbing (set -f) and quote everthing. In addition delete unused scripts and examples from your Bot, e.g. scripts 'notify', 'calc', 'question', and disable all not used commands.
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 extensive in bashbot development to enshure 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.
### Run your Bot as a restricted user
**I recommend to run your bot as a user, with almost no access rights.**
All files your Bot have write access to are in danger to be overwritten/deleted if your bot is hacked.
For the same reason ervery file your Bot can read is in danger to be disclosed. Restict your Bots access rigths to the absolute minimum.
**Never run your Bot as root, this is the most dangerous you can do!** Usually the user 'nobody' has almost no rights on Unix/Linux systems. See [Expert use](doc/4_expert.md) on how to run your Bot as an other user.
### Secure your Bot installation
**Your Bot configuration must no be readable from other users.** Everyone who can read your Bots token can act as your Bot and has access to all chats your Bot is in!
Everyone with read access to your Bot files can extract your Bots data. Especially your Bot Token in ```token``` must be protected against other users. No one exept you must have write access to the Bot files. The Bot must be restricted to have write access to ```count``` and ```tmp-bot-bash``` 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.
## FAQ
### Is this Bot insecure?
Bashbot is not more (in)secure as any other Bot written in any other 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 ...
### Why Bash and not the much better xyz?
Well, thats a damn good question ... may be because I'm an Unix/Linux admin from stone age. Nevertheless there are more reasons from my side:
- bashbot will run everywhere where bash is availible, from ebedded linux to mainframe
- easy to integrate with other shell script, e.g. for sending system message / health status
- no need to install or learn a new programming language, library or framework
- no database, not event driven, not OO ...
### Can I have the single bashbot.sh file back?
At the beginning bashbot was simply the file ```bashbot.sh``` you can 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
'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?
Of course, you can send messages from CLI and scripts, simply install bashbot as [described here](#Your-really-first-bashbot-in-a-nutshell),
send the messsage '/start' to set yourself as botadmin and stop the bot with ```./bashbot.sh kill```.
Run the following commands in your bash shell or script while you are in the installation directory:
```bash
# prepare bash / script to send commands
export BASHBOT_HOME="$(pwd)"
source ./bashbot.sh source
# send me a test message
send_message "$(cat "$BOTADMIN")" "test"
# send me output of a system command
send_message "$(<"$BOTADMIN")" "$(df -h)"
```
For more information see [Expert Use](doc/8_custom.md)
### Why do I get "EXPECTED value GOT EOF" on start?
May be your IP is blocked by telegram. You can test this by running curl or wget manually:
```bash
curl -m 10 https://api.telegram.org/bot
#curl: (28) Connection timed out after 10001 milliseconds
wget -t 1 -T 10 https://api.telegram.org/bot
#Connecting to api.telegram.org (api.telegram.org)|46.38.243.234|:443... failed: Connection timed out.
```
This may happen if to many wrong requests are sent to api.telegram.org, e.g. using a wrong token or not existing API calls. If you have a fixed IP you can ask telegram service to unblock your ip or change your IP. If you are running a tor proxy on your server you may uncomment the ```BASHBOT_CURL_ARGS``` line in 'mycommands.sh'
@Gnadelwartz
## That's it!
If you feel that there's something missing or if you found a bug, feel free to submit a pull request!
#### $$VERSION$$ v0.90-dev2-19-g5779acc

View File

@ -0,0 +1,258 @@
<h2><img align="middle"
src="https://raw.githubusercontent.com/odb/official-bash-logo/master/assets/Logo
s/Icons/PNG/64x64.png" >
Bashbot - A Telegram bot written in bash.
</h2>
Written by Drew (@topkecleon), Daniil Gentili (@danogentili), and Kay M
(@gnadelwartz).
Contributions by JuanPotato, BigNerd95, TiagoDanin, and iicc1.
Released to the public domain wherever applicable.
Elsewhere, consider it released under the
[WTFPLv2](http://www.wtfpl.net/txt/copying/).
## Prerequisites
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh), but no more TMUX.
Even bashbot is written in bash, it depends on commands typically availible in
a Unix/Linux Environment.
More concret on the common commands provided by
[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)
Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and
[Downloads](https://github.com/topkecleon/telegram-bot-bash/releases) are
availible on www.github.com
## Documentation
* [Introdution to Telegram Bots](https://core.telegram.org/bots)
* [One Bot to rule them
all](https://core.telegram.org/bots#3-how-do-i-create-a-bot)
* [Bot commands](https://core.telegram.org/bots#commands)
* [Install Bashbot](doc/0_install.md)
* Install release
* Install from githup
* Update Bashbot
* Notes on Updates
* [Create a new Telegram Bot with botfather](doc/1_firstbot.md)
* [Getting Started](doc/2_usage.md)
* Managing your Bot
* Recieve data
* Send messages
* Send files, locations, keyboards
* [Advanced Features](doc/3_advanced.md)
* Access Control
* Interactive Chats
* Background Jobs
* Inline queries
* [Expert Use](doc/4_expert.md)
* Handling UTF-8 character sets
* Run as other user or system service
* Scedule bashbot from Cron
* Use from CLI and Scripts
* Customize Bashbot Environment
* [Best Practices](doc/5_practice.md)
* Customize commands.sh
* Seperate logic from commands
* Test your Bot with shellcheck
* [Function Reference](doc/6_reference.md)
* Sending Messages, Files, Keyboards
* User Access Control
* Inline Queries
* Background and Interactive Jobs
* [Deveoper Notess](doc/7_develop.md)
* Debug bashbot
* Modules, addons, events
* Setup your environment
* Bashbot testsuite
* [Examples Dir](examples/README.md)
### Your really first bashbot in a nutshell
To install and run bashbot you need acess to a linux/unix/bsd command line. If
you don't know how to get accces to a linux/unix/bsd like command line you
should stop reading here :-(
In addition you need a [Telegram client](https://telegram.org) and a mobile
phone to [register an
account](https://telegramguide.com/create-a-telegram-account/).
If you don't want to register for Telegram you should stop reading here ;-)
After you're registered to Telegram send a message to
[@botfather](https://telegram.me/botfather),
[create a new Telegram Bot token](doc/1_firstbot.md) and write it down. You
need the token to install the bot.
Now open a linux/unix/bsd terminal and check if bash is installed: ```which
bash && echo "bash installed!"```.
If you get an error message bash is not installed.
Create a new directory and change to it: ```mkdir tbb; cd tbb``` and download
the latest '*.tar.gz' file from
[https://github.com/topkecleon/telegram-bot-bash/releases](https://github.com/to
pkecleon/telegram-bot-bash/releases). This can be done with the commands:
```bash
wget -q https://github.com/$(wget -q
https://github.com/topkecleon/telegram-bot-bash/releases/latest -O - | egrep
'/.*/.*/.*tar.gz' -o)
```
Extract the '*.tar.gz' file and change to bashbot directory: ```tar -xzf
*.tar.gz; cd telegram-bot-bash```,
install bashbot: ```./bashbot.sh init``` and enter your bot token when asked.
All other questions can be answered
by hitting the \<Return\> key.
Thats all, now you can start your bot with ```./bashbot.sh start``` and send
him messages:
```
/start
You are Botadmin
*Available commands*:
*• /start*: _Start bot and get this message_.
*• /help*: _Get this message_.
*• /info*: _Get shorter info message about this bot_....
/info
his is bashbot, the Telegram bot written entirely in bash.
It features background tasks and interactive chats, and can serve as an
interface for CLI programs.
```
For more Information on how to install, customize and use your new bot, read
the [Documentation](#Documentation)
----
## Security Considerations
Running a Telegram Bot means it is connected to the public and you never know
whats send to your Bot.
Bash scripts in general are not designed to be bullet proof, so consider this
Bot as a proof of concept. Bash programmers often struggle with 'quoting hell'
and globbing, see [Implications of wrong
quoting](https://unix.stackexchange.com/questions/171346/security-implications-o
f-forgetting-to-quote-a-variable-in-bash-posix-shells)
Whenever you are processing input from from untrusted sources (messages, files,
network) you must be as carefull as possible, e.g. set IFS appropriate, disable
globbing (set -f) and quote everthing. In addition delete unused scripts and
examples from your Bot, e.g. scripts 'notify', 'calc', 'question', and disable
all not used commands.
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
extensive in bashbot development to enshure 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.
### Run your Bot as a restricted user
**I recommend to run your bot as a user, with almost no access rights.**
All files your Bot have write access to are in danger to be overwritten/deleted
if your bot is hacked.
For the same reason ervery file your Bot can read is in danger to be disclosed.
Restict your Bots access rigths to the absolute minimum.
**Never run your Bot as root, this is the most dangerous you can do!** Usually
the user 'nobody' has almost no rights on Unix/Linux systems. See [Expert
use](doc/4_expert.md) on how to run your Bot as an other user.
### Secure your Bot installation
**Your Bot configuration must no be readable from other users.** Everyone who
can read your Bots token can act as your Bot and has access to all chats your
Bot is in!
Everyone with read access to your Bot files can extract your Bots data.
Especially your Bot Token in ```token``` must be protected against other users.
No one exept you must have write access to the Bot files. The Bot must be
restricted to have write access to ```count``` and ```tmp-bot-bash``` 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.
## FAQ
### Is this Bot insecure?
Bashbot is not more (in)secure as any other Bot written in any other 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 ...
### Why Bash and not the much better xyz?
Well, thats a damn good question ... may be because I'm an Unix/Linux admin
from stone age. Nevertheless there are more reasons from my side:
- bashbot will run everywhere where bash is availible, from ebedded linux to
mainframe
- easy to integrate with other shell script, e.g. for sending system message /
health status
- no need to install or learn a new programming language, library or framework
- no database, not event driven, not OO ...
### Can I have the single bashbot.sh file back?
At the beginning bashbot was simply the file ```bashbot.sh``` you can 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
'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?
Of course, you can send messages from CLI and scripts, simply install bashbot
as [described here](#Your-really-first-bashbot-in-a-nutshell),
send the messsage '/start' to set yourself as botadmin and stop the bot with
```./bashbot.sh kill```.
Run the following commands in your bash shell or script while you are in the
installation directory:
```bash
# prepare bash / script to send commands
export BASHBOT_HOME="$(pwd)"
source ./bashbot.sh source
# send me a test message
send_message "$(cat "$BOTADMIN")" "test"
# send me output of a system command
send_message "$(<"$BOTADMIN")" "$(df -h)"
```
For more information see [Expert Use](doc/8_custom.md)
### Why do I get "EXPECTED value GOT EOF" on start?
May be your IP is blocked by telegram. You can test this by running curl or
wget manually:
```bash
curl -m 10 https://api.telegram.org/bot
#curl: (28) Connection timed out after 10001 milliseconds
wget -t 1 -T 10 https://api.telegram.org/bot
#Connecting to api.telegram.org (api.telegram.org)|46.38.243.234|:443...
failed: Connection timed out.
```
This may happen if to many wrong requests are sent to api.telegram.org, e.g.
using a wrong token or not existing API calls. If you have a fixed IP you can
ask telegram service to unblock your ip or change your IP. If you are running a
tor proxy on your server you may uncomment the ```BASHBOT_CURL_ARGS``` line in
'mycommands.sh'
@Gnadelwartz
## That's it!
If you feel that there's something missing or if you found a bug, feel free to
submit a pull request!
#### $$VERSION$$ v0.90-dev2-19-g5779acc

View File

@ -0,0 +1,77 @@
#!/bin/bash
# file: addons/antiFlood.sh.dist
#
# this addon counts how many files, e.g. stickers, are sent to
# a chat and takes actions if threshold is reached
#
# used events:
#
# BASHBOT_EVENT_TEXT message containing message text received
# BASHBOT_EVENT_CMD a command is recieved
# BASHBOT_EVENT_FILE file received
#
# all global variables and functions can be used in registered functions.
#
# parameters when loaded
# $1 event: init, startbot ...
# $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
#
# prameters on events
# $1 event: inline, message, ..., file
# $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
#
# shellcheck disable=SC2140
# export used events
export BASHBOT_EVENT_TEXT BASHBOT_EVENT_CMD BASHBOT_EVENT_FILE
# any global variable defined by addons MUST be prefixed by addon name
ANTIFLOOD_ME="antiflood"
declare -Ax ANTIFLOOD_CHATS ANTIFLOOD_ACTUALS
ANTIFLOOD_DEFAULT="5" # 5 files per minute
ANTIFLOOD_BAN="5" # 5 minutes
# initialize after installation or update
if [[ "$1" = "init"* ]]; then
: # nothing
fi
# register on startbot
if [[ "$1" = "start"* ]]; then
#load existing chat settings on start
jssh_readDB "ANTIFLOOD_CHATS" "${ADDONDIR:-./addons}/$ANTIFLOOD_ME"
# register to CMD
BASHBOT_EVENT_CMD["${ANTIFLOOD_ME}"]="${ANTIFLOOD_ME}_cmd"
# command /antiflood starts addon, $1 floodlevel $2 bantime
antiflood_cmd(){
case "${CMD[0]}" in
"/antifl"*)
ANTIFLOOD_CHATS["${CHAT[ID]}","level"]="${ANTIFLOOD_DEFAULT}"
ANTIFLOOD_CHATS["${CHAT[ID]}","ban"]="${ANTIFLOOD_BAN}"
[[ "${CMD[1]}" =~ ^[0-9]+$ ]] && ANTIFLOOD_CHATS["${CHAT[ID]}","level"]="${CMD[1]}"
[[ "${CMD[2]}" =~ ^[0-9]+$ ]] && ANTIFLOOD_CHATS["${CHAT[ID]}","ban"]="${CMD[2]}"
# antiflood_save &
;;
esac
}
# register to inline and command
BASHBOT_EVENT_TEXT["${ANTIFLOOD_ME}"]="${ANTIFLOOD_ME}_multievent"
BASHBOT_EVENT_FILE["${ANTIFLOOD_ME}"]="${ANTIFLOOD_ME}_multievent"
antiflood_multievent(){
# not started
[ "${ANTIFLOOD_CHATS["${CHAT[ID]}","level"]}" = "" ] && return
# count flood messages
[ "$1" = "text" ] && [ "${#MESSAGE[0]}" -lt "5" ] && (( ANTIFLOOD_ACTUALS["${CHAT[ID]}","${USER[ID]}"] += 1 ))
# shellcheck disable=SC2154
[ "$1" = "file" ] && (( ANTIFLOOD_ACTUALS["${CHAT[ID]}","${USER[ID]}","file"] += 1 ))
# antiflood_check &
}
fi

View File

@ -0,0 +1,97 @@
#!/bin/bash
# file: addons/example.sh.dist
#
# Addons can register to bashbot events at statup
# by providing their name and a callback per event
#
# If an event occours each registered event function is called.
#
# Events run in the same context as the main bashbot event loop
# so variables set here are persistent as long bashbot is running.
#
# Note: For the same reason event function MUST return imideatly!
# compute intensive tasks must be run in a nonblocking subshell,
# e.g. "(long running) &"
#
# Availible events:
# on events startbot and init, this file is sourced
#
# BASHBOT_EVENT_INLINE inline query received
# BASHBOT_EVENT_MESSAGE any type of message received
# BASHBOT_EVENT_TEXT message containing message text received
# BASHBOT_EVENT_CMD a command is recieved
# BASHBOT_EVENT_REPLYTO reply to message received
# BASHBOT_EVENT_FORWARD forwarded message received
# BASHBOT_EVENT_CONTACT contact received
# BASHBOT_EVENT_LOCATION location or venue received
# BASHBOT_EVENT_FILE file received
#
# BAHSBOT_EVENT_TIMER this event is a bit special as it fires every Minute
# and has 3 meanings: oneshot, everytime, every X minutes.
#
# all global variables and functions can be used in registered functions.
#
# parameters when loaded
# $1 event: init, startbot ...
# $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
#
# prameters on events
# $1 event: inline, message, ..., file
# $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
#
# export used events
export BASHBOT_EVENT_INLINE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLY BASHBOT_EVENT_TIMER
# any global variable defined by addons MUST be prefixed by addon name
EXAMPLE_ME="example"
# initialize after installation or update
if [[ "$1" = "init"* ]]; then
: # nothing to do
fi
# register on startbot
if [[ "$1" = "start"* ]]; then
# register to reply
BASHBOT_EVENT_REPLY["${EXAMPLE_ME}"]="${EXAMPLE_ME}_reply"
# any function defined by addons MUST be prefixed by addon name
# function local variables can have any name, but must be LOCAL
example_reply(){
local msg="message"
send_markdown_message "${CHAT[ID]}" "User *${USER[USERNAME]}* replied to ${msg} from *${REPLYTO[USERNAME]}*" &
}
# register to inline and command
BASHBOT_EVENT_INLINE["${EXAMPLE_ME}"]="${EXAMPLE_ME}_multievent"
BASHBOT_EVENT_CMD["${EXAMPLE_ME}"]="${EXAMPLE_ME}_multievent"
# any function defined by addons MUST be prefixed by addon name
# function local variables can have any name, but must be LOCAL
example_multievent(){
local type="$1"
local msg="${MESSAGE[0]}"
# shellcheck disable=SC2154
[ "${type}" = "inline" ] && msg="${iQUERY[0]}"
send_normal_message "${CHAT[ID]}" "${type} received: ${msg}" &
}
BASHBOT_EVENT_TIMER["${EXAMPLE_ME}after5min","-5"]="${EXAMPLE_ME}_after5min"
# any function defined by addons MUST be prefixed by addon name
# function local variables can have any name, but must be LOCAL
example_after5min(){
send_markdown_message "$(< "${BOTADMIN}")" "This is a one time event after 5 Minutes!" &
}
BASHBOT_EVENT_TIMER["${EXAMPLE_ME}every2min","2"]="${EXAMPLE_ME}_every2min"
# any function defined by addons MUST be prefixed by addon name
# function local variables can have any name, but must be LOCAL
example_every2min(){
send_markdown_message "$(< "${BOTADMIN}")" "This a a every 2 minute event ..." &
}
fi

View File

@ -0,0 +1,86 @@
#!/bin/sh
# description: Start or stop telegram-bash-bot
#
#### $$VERSION$$ v0.90-dev2-0-gec85636
# shellcheck disable=SC2009
# shellcheck disable=SC2181
#
### BEGIN INIT INFO
# Provides: bashbot
# Required-Start: $network $syslog
# Required-Stop: $network
# Default-Start: 2 3 5
# Default-Stop: 0 1 6
# Description: Start or stop telegram-bot-bash server
### END INIT INFO
# save default values
TERM="" # disable bashbot clear and color output
runas="nobody"
runcmd="echo Dry run:" # not actived until you edit lines below
#######################
# Configuration Section
# edit the next line to fit the user you want to run bashbot, e.g. nobody:
# runas="nobody"
# uncomment one of the following lines to fit your system
# runcmd="su $runas -s /bin/bash -c " # runasuser with *su*
# runcmd="runuser $runas -s /bin/bash -c " # runasuser with *runuser*
# edit the values of the following lines to fit your config:
start="/usr/local/telegram-bot-bash/bashbot.sh" # location of your bashbot.sh script
name='' # your bot name as given to botfather, e.g. mysomething_bot
# END Configuration
#######################
lockfile="$(dirname $start)/lockfile"
[ "$name" = "" ] && name="$runas"
case "$1" in
'start')
$runcmd "$start start" # >/dev/null 2>&1 </dev/null
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
touch "$lockfile" >/dev/null 2>&1
fi
;;
'stop')
$runcmd "$start kill"
RETVAL=$?
if [ "$RETVAL" = "0" ]; then
rm -f "$lockfile"
fi
;;
'status')
ps -f -u "$runas" | grep "$name" | grep -qF "bashbot.sh startbot"
if [ "$?" = "0" ]; then
echo "bashbot ($name) is running"
RETVAL=0
else
echo "bashbot ($name) is stopped"
RETVAL=1
fi
;;
'restart'|'reload')
$0 stop; $0 start
RETVAL=$?
;;
'restartback')
$0 suspendback; $0 resumeback
RETVAL=$?
;;
'suspendback'|'resumeback'|'killback')
$runcmd "$start $1"
RETVAL=$?
;;
*)
echo "Usage: $0 { start | stop | restart | reload | restartback | suspendback | resumeback | killback }"
RETVAL=1
;;
esac
exit $RETVAL

784
DIST/telegram-bot-bash/bashbot.sh Executable file
View File

@ -0,0 +1,784 @@
#!/bin/bash
# file: bashbot.sh
# do not edit, this file will be overwritten on update
# bashbot, the Telegram bot written in bash.
# Written by Drew (@topkecleon) and Daniil Gentili (@danogentili), KayM (@gnadelwartz).
# Also contributed: JuanPotato, BigNerd95, TiagoDanin, iicc1.
# https://github.com/topkecleon/telegram-bot-bash
# Depends on JSON.sh (http://github.com/dominictarr/JSON.sh) (MIT/Apache),
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#
#### $$VERSION$$ v0.90-dev2-16-g74cb204
#
# Exit Codes:
# - 0 sucess (hopefully)
# - 1 can't change to dir
# - 2 can't write to tmp, count or token
# - 3 user / command / file not found
# - 4 unkown command
# - 5 cannot connect to telegram bot
# shellcheck disable=SC2140
# are we runnig in a terminal?
if [ -t 1 ] && [ "$TERM" != "" ]; then
CLEAR='clear'
RED='\e[31m'
GREEN='\e[32m'
ORANGE='\e[35m'
NC='\e[0m'
fi
# get location and name of bashbot.sh
SCRIPT="$0"
REALME="${BASH_SOURCE[0]}"
SCRIPTDIR="$(dirname "${REALME}")"
RUNDIR="$(dirname "$0")"
MODULEDIR="${SCRIPTDIR}/modules"
if [ "${SCRIPT}" != "${REALME}" ] || [ "$1" = "source" ]; then
SOURCE="yes"
else
SCRIPT="./$(basename "${SCRIPT}")"
fi
if [ "$BASHBOT_HOME" != "" ]; then
SCRIPTDIR="$BASHBOT_HOME"
[ "${BASHBOT_ETC}" = "" ] && BASHBOT_ETC="$BASHBOT_HOME"
[ "${BASHBOT_VAR}" = "" ] && BASHBOT_VAR="$BASHBOT_HOME"
fi
ADDONDIR="${BASHBOT_ETC:-./addons}"
RUNUSER="${USER}" # USER is overwritten by bashbot array
if [ "${SOURCE}" != "yes" ] && [ "$BASHBOT_HOME" = "" ] && ! cd "${RUNDIR}" ; then
echo -e "${RED}ERROR: Can't change to ${RUNDIR} ...${NC}"
exit 1
fi
if [ ! -w "." ]; then
echo -e "${ORANGE}WARNING: ${RUNDIR} is not writeable!${NC}"
ls -ld .
fi
TOKENFILE="${BASHBOT_ETC:-.}/token"
if [ ! -f "${TOKENFILE}" ]; then
if [ "${CLEAR}" = "" ] && [ "$1" != "init" ]; then
echo "Running headless, run ${SCRIPT} init first!"
exit 2
else
${CLEAR}
echo -e "${RED}TOKEN MISSING.${NC}"
echo -e "${ORANGE}PLEASE WRITE YOUR TOKEN HERE OR PRESS CTRL+C TO ABORT${NC}"
read -r token
printf '%s\n' "${token}" > "${TOKENFILE}"
fi
fi
BOTADMIN="${BASHBOT_ETC:-.}/botadmin"
if [ ! -f "${BOTADMIN}" ]; then
if [ "${CLEAR}" = "" ]; then
echo "Running headless, set botadmin to AUTO MODE!"
printf '%s\n' '?' > "${BOTADMIN}"
else
${CLEAR}
echo -e "${RED}BOTADMIN MISSING.${NC}"
echo -e "${ORANGE}PLEASE WRITE YOUR TELEGRAM ID HERE OR ENTER '?'${NC}"
echo -e "${ORANGE}TO MAKE FIRST USER TYPING '/start' TO BOTADMIN${NC}"
read -r admin
[ "${admin}" = "" ] && admin='?'
printf '%s\n' "${admin}" > "${BOTADMIN}"
fi
fi
BOTACL="${BASHBOT_ETC:-.}/botacl"
if [ ! -f "${BOTACL}" ]; then
echo -e "${ORANGE}Create empty ${BOTACL} file.${NC}"
printf '\n' >"${BOTACL}"
fi
DATADIR="${BASHBOT_VAR:-.}/data-bot-bash"
if [ ! -d "${DATADIR}" ]; then
mkdir "${DATADIR}"
elif [ ! -w "${DATADIR}" ]; then
echo -e "${RED}ERROR: Can't write to ${DATADIR}!.${NC}"
ls -ld "${DATADIR}"
exit 2
fi
COUNTFILE="${BASHBOT_VAR:-.}/count"
if [ ! -f "${COUNTFILE}" ]; then
printf '\n' >"${COUNTFILE}"
elif [ ! -w "${COUNTFILE}" ]; then
echo -e "${RED}ERROR: Can't write to ${COUNTFILE}!.${NC}"
ls -l "${COUNTFILE}"
exit 2
fi
BOTTOKEN="$(< "${TOKENFILE}")"
URL="${BASHBOT_URL:-https://api.telegram.org/bot}${BOTTOKEN}"
ME_URL=$URL'/getMe'
UPD_URL=$URL'/getUpdates?offset='
GETFILE_URL=$URL'/getFile'
declare -rx SCRIPT SCRIPTDIR MODULEDIR RUNDIR ADDONDIR TOKENFILE BOTADMIN BOTACL DATADIR COUNTFILE
declare -rx BOTTOKEN URL ME_URL UPD_URL GETFILE_URL
declare -ax CMD
declare -Ax UPD BOTSENT USER MESSAGE URLS CONTACT LOCATION CHAT FORWARD REPLYTO VENUE iQUERY
export res CAPTION
COMMANDS="${BASHBOT_ETC:-.}/commands.sh"
if [ "${SOURCE}" = "yes" ]; then
for modules in ${MODULEDIR:-.}/*.sh ; do
# shellcheck source=./modules/aliases.sh
[ -r "${modules}" ] && source "${modules}" "source"
done
else
if [ ! -f "${COMMANDS}" ] || [ ! -r "${COMMANDS}" ]; then
echo -e "${RED}ERROR: ${COMMANDS} does not exist or is not readable!.${NC}"
ls -l "${COMMANDS}"
exit 3
fi
# shellcheck source=./commands.sh
source "${COMMANDS}" "source"
fi
#################
# BASHBOT INTERNAL functions
# $1 URL, $2 filename in DATADIR
# outputs final filename
download() {
local empty="no.file" file="${2:-${empty}}"
if [[ "$file" = *"/"* ]] || [[ "$file" = "."* ]]; then file="${empty}"; fi
while [ -f "${DATADIR:-.}/${file}" ] ; do file="$RAMDOM-${file}"; done
getJson "$1" >"${DATADIR:-.}/${file}" || return
printf '%s\n' "${DATADIR:-.}/${file}"
}
# $1 postfix, e.g. chatid
# $2 prefix, back- or startbot-
procname(){
printf '%s\n' "$2${ME}_$1"
}
# $1 sting to search for proramm incl. parameters
# retruns a list of PIDs of all current bot proceeses matching $1
proclist() {
# shellcheck disable=SC2009
ps -fu "${UID}" | grep -F "$1" | grep -v ' grep'| grep -F "${ME}" | sed 's/\s\+/\t/g' | cut -f 2
}
# $1 sting to search for proramm to kill
killallproc() {
local procid; procid="$(proclist "$1")"
if [ "${procid}" != "" ] ; then
# shellcheck disable=SC2046
kill $(proclist "$1")
sleep 1
procid="$(proclist "$1")"
# shellcheck disable=SC2046
[ "${procid}" != "" ] && kill $(proclist -9 "$1")
fi
}
# returns true if command exist
_exists()
{
[ "$(LC_ALL=C type -t "$1")" = "file" ]
}
# execute function if exists
_exec_if_function() {
[ "$(LC_ALL=C type -t "${1}")" != "function" ] || "$@"
}
# returns true if function exist
_is_function()
{
[ "$(LC_ALL=C type -t "$1")" = "function" ]
}
declare -xr DELETE_URL=$URL'/deleteMessage'
delete_message() {
sendJson "${1}" 'message_id: '"${2}"'' "${DELETE_URL}"
}
get_file() {
[ "$1" = "" ] && return
sendJson "" '"file_id": '"${1}""${GETFILE_URL}"
printf '%s\n' "${URL}"/"$(jsonGetString <<< "${res}" '"result","file_path"')"
}
# curl is preffered, but may not availible on ebedded systems
TIMEOUT="${BASHBOT_TIMEOUT}"
[[ "$TIMEOUT" =~ ^[0-9]+$ ]] || TIMEOUT="20"
if [ "${BASHBOT_WGET}" = "" ] && _exists curl ; then
# simple curl or wget call, output to stdout
getJson(){
# shellcheck disable=SC2086
curl -sL ${BASHBOT_CURL_ARGS} -m "${TIMEOUT}" "$1"
}
# usage: sendJson "chat" "JSON" "URL"
sendJson(){
local chat="";
[ "${1}" != "" ] && chat='"chat_id":'"${1}"','
# shellcheck disable=SC2086
res="$(curl -s ${BASHBOT_CURL_ARGS} -m "${TIMEOUT}" -d '{'"${chat} $2"'}' -X POST "${3}" \
-H "Content-Type: application/json" | "${JSONSHFILE}" -s -b -n )"
BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")"
BOTSENT[ID]="$(JsonGetValue '"result","message_id"' <<< "$res")"
}
#$1 Chat, $2 what , $3 file, $4 URL, $5 caption
sendUpload() {
[ "$#" -lt 4 ] && return
if [ "$5" != "" ]; then
# shellcheck disable=SC2086
res="$(curl -s ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1" -F "$2=@$3;${3##*/}" -F "caption=$5" | "${JSONSHFILE}" -s -b -n )"
else
# shellcheck disable=SC2086
res="$(curl -s ${BASHBOT_CURL_ARGS} "$4" -F "chat_id=$1" -F "$2=@$3;${3##*/}" | "${JSONSHFILE}" -s -b -n )"
fi
BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")"
}
else
# simple curl or wget call outputs result to stdout
getJson(){
# shellcheck disable=SC2086
wget -t 2 -T "${TIMEOUT}" ${BASHBOT_WGET_ARGS} -qO - "$1"
}
# usage: sendJson "chat" "JSON" "URL"
sendJson(){
local chat="";
[ "${1}" != "" ] && chat='"chat_id":'"${1}"','
# shellcheck disable=SC2086
res="$(wget -t 2 -T "${TIMEOUT}" ${BASHBOT_WGET_ARGS} -qO - --post-data='{'"${chat} $2"'}' \
--header='Content-Type:application/json' "${3}" | "${JSONSHFILE}" -s -b -n )"
BOTSENT[OK]="$(JsonGetLine '"ok"' <<< "$res")"
BOTSENT[ID]="$(JsonGetValue '"result","message_id"' <<< "$res")"
}
sendUpload() {
sendJson "$1" '"text":"Sorry, wget does not support file upload"' "${MSG_URL}"
BOTSENT[OK]="false"
}
fi
# convert common telegram entities to JSON
# title caption description markup inlinekeyboard
title2Json(){
local title caption desc markup keyboard
[ "$1" != "" ] && title=',"title":"'$1'"'
[ "$2" != "" ] && caption=',"caption":"'$2'"'
[ "$3" != "" ] && desc=',"description":"'$3'"'
[ "$4" != "" ] && markup=',"parse_mode":"'$4'"'
[ "$5" != "" ] && keyboard=',"reply_markup":"'$5'"'
echo "${title}${caption}${desc}${markup}${keyboard}"
}
# get bot name
getBotName() {
getJson "$ME_URL" | "${JSONSHFILE}" -s -b -n | JsonGetString '"result","username"'
}
# pure bash implementaion, done by KayM (@gnadelwartz)
# see https://stackoverflow.com/a/55666449/9381171
JsonDecode() {
local out="$1" remain="" U=""
local regexp='(.*)\\u[dD]([0-9a-fA-F]{3})\\u[dD]([0-9a-fA-F]{3})(.*)'
while [[ "${out}" =~ $regexp ]] ; do
U=$(( ( (0xd${BASH_REMATCH[2]} & 0x3ff) <<10 ) | ( 0xd${BASH_REMATCH[3]} & 0x3ff ) + 0x10000 ))
remain="$(printf '\\U%8.8x' "${U}")${BASH_REMATCH[4]}${remain}"
out="${BASH_REMATCH[1]}"
done
echo -e "${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'
}
# read JSON.sh style data and asssign to an ARRAY
# $1 ARRAY name, must be declared with "declare -A ARRAY" before calling
Json2Array() {
# shellcheck source=./commands.sh
[ "$1" = "" ] || source <( printf "$1"'=( %s )' "$(sed -E -e 's/\t/=/g' -e 's/=(true|false)/="\1"/')" )
}
# output ARRAY as JSON.sh style data
# $1 ARRAY name, must be declared with "declare -A ARRAY" before calling
Array2Json() {
local key
declare -n ARRAY="$1"
for key in "${!ARRAY[@]}"
do
printf '["%s"]\t"%s"\n' "${key//,/\",\"}" "${ARRAY[${key}]//\"/\\\"}"
done
}
################
# processing of updates starts here
process_updates() {
local max num debug="$1"
max="$(sed <<< "${UPDATE}" '/\["result",[0-9]*\]/!d' | tail -1 | sed 's/\["result",//g;s/\].*//g')"
Json2Array 'UPD' <<<"${UPDATE}"
for ((num=0; num<=max; num++)); do
process_client "$num" "${debug}"
done
}
process_client() {
local num="$1" debug="$2"
CMD=( )
iQUERY[ID]="${UPD["result",${num},"inline_query","id"]}"
if [ "${iQUERY[ID]}" = "" ]; then
[[ "${debug}" = *"debug"* ]] && cat <<< "$UPDATE" >>"MESSAGE.log"
process_message "${num}" "${debug}"
else
[[ "${debug}" = *"debug"* ]] && cat <<< "$UPDATE" >>"INLINE.log"
process_inline "${num}" "${debug}"
fi
#####
# process inline and message events
# first classic commnad dispatcher
# shellcheck source=./commands.sh
source "${COMMANDS}" "${debug}" &
# then all registered addons
if [ "${iQUERY[ID]}" = "" ]; then
event_message "${debug}"
else
event_inline "${debug}"
fi
# last count users
tmpcount="COUNT${CHAT[ID]}"
grep -q "$tmpcount" <"${COUNTFILE}" &>/dev/null || cat <<< "$tmpcount" >>"${COUNTFILE}"
}
declare -Ax BASBOT_EVENT_INLINE BASBOT_EVENT_MESSAGE BASHBOT_EVENT_CMD BASBOT_EVENT_REPLY BASBOT_EVENT_FORWARD
declare -Ax BASBOT_EVENT_CONTACT BASBOT_EVENT_LOCATION BASBOT_EVENT_FILE BASHBOT_EVENT_TEXT BASHBOT_EVENT_TIMER
start_timer(){
# send alarm every ~60 s
while :; do
sleep 59.5
kill -ALRM $$
done;
}
EVENT_TIMER="0"
event_timer() {
local event timer debug="$1"
(( EVENT_TIMER += 1 ))
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_TIMER[@]}"
do
timer="${BASHBOT_EVENT_TIMER[${event}]##*,}"
[[ ! "$timer" =~ ^-*[0-9]+$ ]] && continue
[[ "$timer" =~ ^-*0+$ ]] && continue
if [ "$(( EVENT_TIMER % timer ))" = "0" ]; then
_exec_if_function "${BASHBOT_EVENT_TIMER[${event}]}" "timer" "${debug}"
[ "$(( EVENT_TIMER % timer ))" -lt "0" ] && \
unset BASHBOT_EVENT_TIMER["${event}"]
fi
done
}
event_inline() {
local event debug="$1"
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_INLINE[@]}"
do
_exec_if_function "${BASHBOT_EVENT_INLINE[${event}]}" "inline" "${debug}"
done
}
event_message() {
local event debug="$1"
# ${MESSAEG[*]} event_message
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_MESSAGE[@]}"
do
_exec_if_function "${BASHBOT_EVENT_MESSAGE[${event}]}" "messsage" "${debug}"
done
# ${TEXT[*]} event_text
if [ "${MESSAGE[0]}" != "" ]; then
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_TEXT[@]}"
do
_exec_if_function "${BASHBOT_EVENT_TEXT[${event}]}" "text" "${debug}"
done
# ${CMD[*]} event_cmd
if [ "${CMD[0]}" != "" ]; then
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_CMD[@]}"
do
_exec_if_function "${BASHBOT_EVENT_CMD[${event}]}" "command" "${debug}"
done
fi
fi
# ${REPLYTO[*]} event_replyto
if [ "${REPLYTO[UID]}" != "" ]; then
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_REPLYTO[@]}"
do
_exec_if_function "${BASHBOT_EVENT_REPLYTO[${event}]}" "replyto" "${debug}"
done
fi
# ${FORWARD[*]} event_forward
if [ "${FORWARD[UID]}" != "" ]; then
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_FORWARD[@]}"
do
_exec_if_function && "${BASHBOT_EVENT_FORWARD[${event}]}" "forward" "${debug}"
done
fi
# ${CONTACT[*]} event_contact
if [ "${CONTACT[FIRST_NAME]}" != "" ]; then
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_CONTACT[@]}"
do
_exec_if_function "${BASHBOT_EVENT_CONTACT[${event}]}" "contact" "${debug}"
done
fi
# ${VENUE[*]} event_location
# ${LOCALTION[*]} event_location
if [ "${LOCATION[*]}" != "" ] || [ "${VENUE[TITLE]}" != "" ]; then
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_LOCATION[@]}"
do
_exec_if_function "${BASHBOT_EVENT_LOCATION[${event}]}" "location" "${debug}"
done
fi
# ${URLS[*]} event_file
if [ "${URLS[*]}" = "" ]; then
# shellcheck disable=SC2153
for event in "${!BASHBOT_EVENT_FILE[@]}"
do
_exec_if_function "${BASHBOT_EVENT_FILE[${event}]}" "file" "${debug}"
done
fi
}
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"]}")"
# event_inline &
}
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
CHAT[ID]="${UPD["result",${num},"message","chat","id"]}"
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"]}")"
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"]}"
CHAT[ALL_MEMBERS_ARE_ADMINISTRATORS]="${CHAT[ALL_ADMIN]}" # backward compatibility
# User
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"]}")"
# in reply to message from
REPLYTO[UID]="${UPD["result",${num},"message","reply_to_message","from","id"]}"
if [ "${REPLYTO[UID]}" != "" ]; then
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
FORWARD[UID]="${UPD["result",${num},"message","forward_from","id"]}"
if [ "${FORWARD[UID]}" != "" ]; then
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
# Audio
URLS[AUDIO]="$(get_file "${UPD["result",${num},"message","audio","file_id"]}")"
# Document
URLS[DOCUMENT]="$(get_file "${UPD["result",${num},"message","document","file_id"]}")"
# Photo
URLS[PHOTO]="$(get_file "${UPD["result",${num},"message","photo",0,"file_id"]}")"
# Sticker
URLS[STICKER]="$(get_file "${UPD["result",${num},"message","sticker","file_id"]}")"
# Video
URLS[VIDEO]="$(get_file "${UPD["result",${num},"message","video","file_id"]}")"
# Voice
URLS[VOICE]="$(get_file "${UPD["result",${num},"message","voice","file_id"]}")"
# Contact
CONTACT[FIRST_NAME]="$(JsonDecode "${UPD["result",${num},"message","contact","first_name"]}")"
if [ "${CONTACT[FIRST_NAME]}" != "" ]; then
CONTACT[USER_ID]="$(JsonDecode "${UPD["result",${num},"message","contact","user_id"]}")"
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
# vunue
VENUE[TITLE]="$(JsonDecode "${UPD["result",${num},"message","venue","title"]}")"
if [ "${VENUE[TITLE]}" != "" ]; then
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"]}"
# split message in command and args
if [[ "${MESSAGE[0]}" = "/"* ]]; then
set -f; unset IFS
# shellcheck disable=SC2206
CMD=( ${MESSAGE[0]} )
set +f
fi
}
#########################
# main get updates loop, should never terminate
start_bot() {
local DEBUG="$1"
local OFFSET=0
local mysleep="100" # ms
local addsleep="100"
local maxsleep="$(( ${BASHBOT_SLEEP:-5000} + 100 ))"
[[ "${DEBUG}" = *"debug" ]] && exec &>>"DEBUG.log"
[ "${DEBUG}" != "" ] && date && echo "Start BASHBOT in Mode \"${DEBUG}\""
[[ "${DEBUG}" = "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" "${DEBUG}"
done
# start timer events
if _is_function start_timer ; then
# shellcheck disable=SC2064
trap "event_timer $DEBUG" ALRM
start_timer &
# shellcheck disable=SC2064
trap "kill -9 $!; exit" EXIT INT HUP TERM QUIT
fi
while true; do
UPDATE="$(getJson "$UPD_URL$OFFSET" | "${JSONSHFILE}" -s -b -n)"
# Offset
OFFSET="$(grep <<< "${UPDATE}" '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)"
((OFFSET++))
if [ "$OFFSET" != "1" ]; then
mysleep="100"
process_updates "${DEBUG}"
fi
# adaptive sleep in ms rounded to next lower second
[ "${mysleep}" -gt "999" ] && sleep "${mysleep%???}"
# bash aritmetic
((mysleep+= addsleep , mysleep= mysleep>maxsleep ?maxsleep:mysleep))
done
}
# initialize bot environment, user and permissions
bot_init() {
local DEBUG="$1"
# upgrade from old version
local OLDTMP="${BASHBOT_VAR:-.}/tmp-bot-bash"
[ -d "${OLDTMP}" ] && { mv -n "${OLDTMP}/"* "${DATADIR}"; rmdir "${OLDTMP}"; }
[ -f "modules/inline.sh" ] && rm -f "modules/inline.sh"
# load addons on startup
for addons in ${ADDONDIR:-.}/*.sh ; do
# shellcheck source=./modules/aliases.sh
[ -r "${addons}" ] && source "${addons}" "init" "${DEBUG}"
done
#setup bashbot
[[ "${UID}" -eq "0" ]] && RUNUSER="nobody"
echo -n "Enter User to run basbot [$RUNUSER]: "
read -r TOUSER
[ "$TOUSER" = "" ] && TOUSER="$RUNUSER"
if ! id "$TOUSER" &>/dev/null; then
echo -e "${RED}User \"$TOUSER\" not found!${NC}"
exit 3
else
# shellcheck disable=SC2009
oldbot="$(ps -fu "$TOUSER" | grep startbot | grep -v -e 'grep' -e '\-startbot' )"
[ "${oldbot}" != "" ] && \
echo -e "${ORANGE}Warning: At least one not upgraded TMUX bot is running! You must stop it with kill command:${NC}\\n${oldbot}"
echo "Adjusting user \"${TOUSER}\" files and permissions ..."
[ -w "bashbot.rc" ] && sed -i '/^[# ]*runas=/ s/runas=.*$/runas="'$TOUSER'"/' "bashbot.rc"
chown -R "$TOUSER" . ./*
chmod 711 .
chmod -R a-w ./*
chmod -R u+w "${COUNTFILE}" "${DATADIR}" "${BOTADMIN}" ./*.log 2>/dev/null
chmod -R o-r,o-w "${COUNTFILE}" "${DATADIR}" "${TOKENFILE}" "${BOTADMIN}" "${BOTACL}" 2>/dev/null
ls -la
fi
}
if ! _is_function send_message ; then
echo -e "${RED}ERROR: send_message is not availible, did you deactivate ${MODULEDIR}/sendMessage.sh?${NC}"
exit 1
fi
JSONSHFILE="${BASHBOT_JSONSH:-${RUNDIR}/JSON.sh/JSON.sh}"
[[ "${JSONSHFILE}" != *"/JSON.sh" ]] && echo -e "${RED}ERROR: \"${JSONSHFILE}\" ends not with \"JSONS.sh\".${NC}" && exit 3
if [ ! -f "${JSONSHFILE}" ]; then
echo "Seems to be first run, Downloading ${JSONSHFILE}..."
[[ "${JSONSHFILE}" = "${RUNDIR}/JSON.sh/JSON.sh" ]] && mkdir "JSON.sh" 2>/dev/null && chmod +w "JSON.sh"
getJson "https://cdn.jsdelivr.net/gh/dominictarr/JSON.sh/JSON.sh" >"${JSONSHFILE}"
chmod +x "${JSONSHFILE}"
fi
if [ "${SOURCE}" != "yes" ] && [ "$1" != "init" ] && [ "$1" != "help" ] && [ "$1" != "" ]; then
ME="$(getBotName)"
if [ "$ME" = "" ]; then
echo -e "${RED}ERROR: Can't connect to Telegram Bot! May be your TOKEN is invalid ...${NC}"
exit 1
fi
fi
# source the script with source as param to use functions in other scripts
# do not execute if read from other scripts
if [ "${SOURCE}" != "yes" ]; then
##############
# internal options only for use from bashbot and developers
case "$1" in
"outproc") # forward output from interactive and jobs to chat
[ "$3" = "" ] && echo "No file to read from" && exit 3
[ "$2" = "" ] && echo "No chat to send to" && exit 3
while read -r line ;do
[ "$line" != "" ] && send_message "$2" "$line"
done
rm -f -r "${DATADIR:-.}/$3"
[ -s "${DATADIR:-.}/$3.log" ] || rm -f "${DATADIR:-.}/$3.log"
exit
;;
"startbot" )
start_bot "$2"
exit
;;
"init") # adjust users and permissions
bot_init "$2"
exit
;;
esac
###############
# "official" arguments as shown to users
SESSION="${ME:-unknown}-startbot"
BOTPID="$(proclist "${SESSION}")"
case "$1" in
"count")
echo "A total of $(wc -l <"${COUNTFILE}") users used me."
exit
;;
"broadcast")
NUMCOUNT="$(wc -l <"${COUNTFILE}")"
echo "Sending the broadcast $* to $NUMCOUNT users."
[ "$NUMCOUNT" -gt "300" ] && sleep="sleep 0.5"
shift
while read -r f; do send_markdown_message "${f//COUNT}" "$*"; $sleep; done <"${COUNTFILE}"
;;
"status")
if [ "${BOTPID}" != "" ]; then
echo -e "${GREEN}Bot is running.${NC}"
exit
else
echo -e "${ORANGE}Bot not running.${NC}"
exit 5
fi
;;
"start")
# shellcheck disable=SC2086
[ "${BOTPID}" != "" ] && kill ${BOTPID}
nohup "$SCRIPT" "startbot" "$2" "${SESSION}" &>/dev/null &
echo "Session Name: ${SESSION}"
if [ "$(proclist "${SESSION}")" != "" ]; then
echo -e "${GREEN}Bot started successfully.${NC}"
else
echo -e "${RED}An error occurred while starting the bot.${NC}"
exit 5
fi
;;
"kill"|"stop")
if [ "${BOTPID}" != "" ]; then
# shellcheck disable=SC2086
if kill ${BOTPID}; then
echo -e "${GREEN}OK. Bot stopped successfully.${NC}"
else
echo -e "${RED}An error occured while stopping bot.${NC}"
exit 5
fi
fi
exit
;;
"resumeb"* | "killb"* | "suspendb"*)
_is_function job_control || { echo -e "${RED}Module background is not availible!${NC}"; exit 3; }
job_control "$1"
;;
"help")
less "README.txt"
exit
;;
*)
echo -e "${RED}${REALME}: BAD REQUEST${NC}"
echo -e "${RED}Available arguments: start, stop, kill, status, count, broadcast, help, suspendback, resumeback, killback${NC}"
exit 4
;;
esac
# warn if root
if [[ "${UID}" -eq "0" ]] ; then
echo -e "\\n${ORANGE}WARNING: ${SCRIPT} was started as ROOT (UID 0)!${NC}"
echo -e "${ORANGE}You are at HIGH RISK when running a Telegram BOT with root privilegs!${NC}"
fi
fi # end source

View File

@ -0,0 +1,117 @@
#!/bin/bash
# file: commands.sh
# do not edit this file, instead place all your commands in mycommands.sh
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#
#### $$VERSION$$ v0.90-dev2-14-gafc669c
#
# adjust your language setting here, e.g.when run from other user or cron.
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
unset IFS
# set -f # if you are paranoid use set -f to disable globbing
# to change the default info message overwrite bashbot_info in mycommands.sh
bashbot_info='This is bashbot, the Telegram bot written entirely in bash.
It features background tasks and interactive chats, and can serve as an interface for CLI programs.
It currently can send, recieve and forward messages, custom keyboards, photos, audio, voice, documents, locations and video files.
'
# to change the default help messages overwrite in mycommands.sh
bashbot_help='*Available commands*:
*• /start*: _Start bot and get this message_.
*• /help*: _Get this message_.
*• /info*: _Get shorter info message about this bot_.
*• /question*: _Start interactive chat_.
*• /cancel*: _Cancel any currently running interactive chats_.
*• /kickme*: _You will be autokicked from the chat_.
*• /leavechat*: _The bot will leave the group with this command _.
Written by Drew (@topkecleon), Daniil Gentili (@danogentili) and KayM(@gnadelwartz).
Get the code in my [GitHub](http://github.com/topkecleon/telegram-bot-bash)
'
# load modues on startup and always on on debug
if [ "${1}" = "source" ] || [[ "${1}" = *"debug"* ]] ; then
# load all readable modules
for modules in ${MODULEDIR:-.}/*.sh ; do
# shellcheck source=./modules/aliases.sh
[ -r "${modules}" ] && source "${modules}" "${1}"
done
fi
# defaults to no inline and nonsense home dir
export INLINE="0"
export FILE_REGEX='/home/user/allowed/.*'
# load mycommands
# shellcheck source=./commands.sh
[ -r "${BASHBOT_ETC:-.}/mycommands.sh" ] && source "${BASHBOT_ETC:-.}/mycommands.sh" "${1}"
if [ "${1}" != "source" ];then
# detect inline commands....
# no default commands, all processing is done in myinlines()
if [ "$INLINE" != "0" ] && [ "${iQUERY[ID]}" != "" ]; then
# forward iinline query to optional dispatcher
_exec_if_function myinlines
# regular (gobal) commands ...
# your commands are in mycommands()
else
###################
# user defined commands must placed in mycommands
_exec_if_function mycommands
# run commands if true (0) is returned or if mycommands dose not exist
# shellcheck disable=SC2181
if [ "$?" = "0" ]; then
case "${MESSAGE}" in
################################################
# GLOBAL commands start here, edit messages only
'/info'*)
_markdown_message "${bashbot_info}"
;;
'/start'*)
send_action "${CHAT[ID]}" "typing"
_is_botadmin && _markdown_message "You are *BOTADMIN*."
if _is_botadmin || _is_allowed "start" ; then
_markdown_message "${bashbot_help}"
else
_message "You are not allowed to start Bot."
fi
;;
'/help'*)
_markdown_message "${bashbot_help}"
;;
'/leavechat'*) # bot leave chat if user is admin in chat
if _is_admin ; then
_markdown_message "*LEAVING CHAT...*"
_leave
fi
;;
'/kickme'*)
_kick_user "${USER[ID]}"
_unban_user "${USER[ID]}"
;;
'/cancel'*)
checkproc
if [ "$res" -eq 0 ] ; then killproc && _message "Command canceled.";else _message "No command is currently running.";fi
;;
*) # forward messages to optional dispatcher
_exec_if_function send_interactive "${CHAT[ID]}" "${MESSAGE}"
;;
esac
fi
fi
fi

View File

@ -0,0 +1,91 @@
#### [Home](../README.md)
## Install bashbot
1. Go to the directory you want to install bashbot, e.g.
* your $HOME directory (install and run with your user-ID)
* /usr/local if you want to run as service
2. [Download latest release zip from github](https://github.com/topkecleon/telegram-bot-bash/releases) and extract all files.
3. Change into the directory ```telegram-bot-bash```
4. Acticate the bot example commands ``cp mycommands.sh.dist mycommands.sh```
5. Run ```./bashbot.sh init``` to setup the environment and enter your Bots token given by botfather.
Edit 'mycommands.sh to your needs.
Now your Bot is ready to start ...
**If you are new to Bot development read [Bots: An introduction for developers](https://core.telegram.org/bots)**
### Install from Github
As an alternative to download the zip files, you can clone the github repository to get the latest improvements/fixes.
1. Go to the directory you want to install bashbot, e.g.
* your $HOME directory (install and run with your user-ID)
* /usr/local if you want to run as service
2. Run ```git clone https://github.com/topkecleon/telegram-bot-bash.git```
3. Change into the directory ```telegram-bot-bash```
4. Run ``` test/ALL-tests.sh``` and if everthing finish OK ...
5. Run ```sudo ./bashbot.sh init``` to setup the environment and enter your Bots token given by botfather.
### Update bashbot
**Note: all files including 'mycommands.sh' may overwritten, make a backup!**
1. Go to the directory where you had installed bashbot, e.g.
* your $HOME directory
* /usr/local
2. [Download latest release zip from github](https://github.com/topkecleon/telegram-bot-bash/releases)
3. Stop all running instances of bashbot
4. Extract all files to your existing bashbot dir
5. Run ```sudo ./bashbot.sh init``` to setup your environment after the update
If you modified 'commands.sh' move your changes to 'mycommands.sh', this avoids overwrrite of you changes on updates.
Now you can restart your bashbot instances.
### Notes on Updates
#### removal of TMUX
From version 0.80 on TMUX is no longer needed and the bachsbot command 'attach' is deleted. Old function 'inproc'
is replaced by 'send_interactive'. send_interactive does checks if an interactive job is running internaly.
Pls check if you make use of inproc and remove it including the old checks, e.g.
```bash
if tmux ls | grep -v send | grep -q "$copname"; then inproc; fi
# or
[ checkprog ] && inproc
```
must be replaced by ```send_interactive "${CHATD[ID]}" "${MESSAGE}"```
### Do not edit commands.sh
From version 0.60 on your commands must be placed in 'mycommands.sh'. If you update from a version with your commands
in 'commands.sh' move all your commands and functions to 'mycommands.sh'.
From version 0.80 on 'commands.sh' will be overwritten on update!
#### Location of var / tmp / data dirs
From version 0.70 on the tmp dir is renamed to 'data-bot-bash' to reflect the fact that not only temporary files are stored. an existing 'tmp-bot-bash' will be automatically renamed after update.
From version 0.50 on the temporary files are no more placed in '/tmp'. instead a dedicated tmp dir is used.
#### Changes to send_keyboard in v0.6
From Version 0.60 on keybord format for ```send_keyboard``` and ```send_message "mykeyboardstartshere ..."``` was changed.
Keybords are now defined in JSON Array notation e.g. "[ \\"yes\\" , \\"no\\" ]".
This has the advantage that you can create any type of keyboard supported by Telegram.
The old format is supported for backward compatibility, but may fail for corner cases.
*Example Keyboards*:
- 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" ]'
- numpad style keyboard: '[ "1" , "2" , "3" ] , [ "4" , "5" , "6" ] , [ "7" , "8" , "9" ] , [ "0" ]'
#### [Next Create Bot](1_firstbot.md)
#### $$VERSION$$ v0.90-dev2-0-gec85636

View File

@ -0,0 +1,69 @@
#### [Home](../README.md)
## Create a Telegram Bot with botfather
**[BotFather is the one bot to rule them all](https://core.telegram.org/bots#3-how-do-i-create-a-bot). It will help you create new bots and change settings for existing ones.** [Commands known by Botfather](https://core.telegram.org/bots#generating-an-authorization-token)
### Creating a new Bot
1. Message @botfather https://telegram.me/botfather with the following
text: `/newbot`
If you don't know how to message by username, click the search
field on your Telegram app and type `@botfather`, you should be able
to initiate a conversation. Be careful not to send it to the wrong
contact, because some users has similar usernames to `botfather`.
![botfather initial conversation](http://i.imgur.com/aI26ixR.png)
2. @botfather replies with `Alright, a new bot. How are we going to
call it? Please choose a name for your bot.`
3. Type whatever name you want for your bot.
4. @botfather replies with `Good. Now let's choose a username for your
bot. It must end in bot. Like this, for example: TetrisBot or
tetris_bot.`
5. Type whatever username you want for your bot, minimum 5 characters,
and must end with `bot`. For example: `telesample_bot`
6. @botfather replies with:
Done! Congratulations on your new bot. You will find it at
telegram.me/telesample_bot. You can now add a description, about
section and profile picture for your bot, see /help for a list of
commands.
Use this token to access the HTTP API:
<b>123456789:AAG90e14-0f8-40183D-18491dDE</b>
For a description of the Bot API, see this page:
https://core.telegram.org/bots/api
7. Note down the 'token' mentioned above.
8. Type `/setprivacy` to @botfather.
![botfather later conversation](http://i.imgur.com/tWDVvh4.png)
9. @botfather replies with `Choose a bot to change group messages settings.`
10. Type `@telesample_bot` (change to the username you set at step 5
above, but start it with `@`)
11. @botfather replies with
'Enable' - your bot will only receive messages that either start
with the '/' symbol or mention the bot by username.
'Disable' - your bot will receive all messages that people send to groups.
Current status is: ENABLED
12. Type `Disable` to let your bot receive all messages sent to a
group. This step is up to you actually.
13. @botfather replies with `Success! The new status is: DISABLED. /help`
#### [Prev Installation](0_install.md)
#### [Next Getting started](2_usage.md)
#### $$VERSION$$ v0.90-dev2-0-gec85636

View File

@ -0,0 +1,225 @@
#### [Home](../README.md)
## Gettting Started
The Bots standard commands are in the commands dispatcher ```commands.sh```, Do not edit this file! Add your commands and functions to ```mycommands.sh```. In 'mycommands.sh.dist' you find examples how to add own commands and overwrite existing ones. See [Best practices](5_practice.md) for more information.
Once you're done with editing start the Bot with ```./bashbot.sh start```. To stop the Bot run ```./bashbot.sh kill```
If something doesn't work as expected, debug with ```./bashbot.sh startbot DEBUG```, where DEBUG can be 'debug', 'xdebug' or 'xdebugx'.
See [Bashbot Development](7_develop.md) for more information.
To use the functions provided in this script in other scripts simply source bashbot: ```source bashbot.sh source```. see [Expert Use](8_expert.md#Expert-use)
Have FUN!
----
### Files
```
.
├── bashbot.sh # main bashbot script - do not edit
├── commands.sh # command dispatcher - do not edit
├── mycommands.sh # place your functions and commands here!
├── JSON.sh # bashbots JSON parser, see https://github.com/dominictarr/JSON.sh
├── modules # optional functions, sourced by commands.sh
│   ├── aliases.sh # to disable modules rename them xxx.sh.off
│   ├── answerInline.sh
│   ├── jsonDB.sh
│   ├── background.sh
│   ├── chatMember.sh
│   └── sendMessage.sh # main send message functions, do not disable
├── addons # optional addons, disbaled by default
│   ├── example.sh # to enable addons change their XXX_ENABLE to true
│   └── xxxxxage.sh
├── bashbot.rc # start/stop script if you run basbot as service
├── examples # example scripts and configs for bashbot
│   └── bashbot.cron # example crontab
├── doc # Documentation and License
├── html
├── LICENSE
├── README.html
├── README.md
└── README.txt
```
----
## Managing your Bot
#### Note: running bashbot as root is highly danger and not recommended. See Expert use.
### Start / Stop
Start or Stop your Bot use the following commands:
```bash
./bashbot.sh start
```
```bash
./bashbot.sh kill
```
### User count
To count the total number of users that ever used the bot run the following command:
```bash
./bashbot.sh count
```
### Sending broadcasts to all users
To send a broadcast to all of users that ever used the bot run the following command:
```bash
./bashbot.sh broadcast "Hey! I just wanted to let you know that the bot's been updated!"
```
----
## Recieve data
Evertime a Message is recieved, you can read incoming data using the following variables:
### Regular Messages
* ```${MESSAGE}```: Current message
* ```${MESSAGE[ID]}```: ID of current message
* ```$CAPTION```: Captions
* ```$REPLYTO```: Original message wich was replied to
* ```$USER```: This array contains the First name, last name, username and user id of the sender of the current message.
* ```${USER[ID]}```: User id
* ```${USER[FIRST_NAME]}```: User's first name
* ```${USER[LAST_NAME]}```: User's last name
* ```${USER[USERNAME]}```: Username
* ```$CHAT```: This array contains the First name, last name, username, title and user id of the chat of the current message.
* ```${CHAT[ID]}```: Chat id
* ```${CHAT[FIRST_NAME]}```: Chat's first name
* ```${CHAT[LAST_NAME]}```: Chat's last name
* ```${CHAT[USERNAME]}```: Username
* ```${CHAT[TITLE]}```: Title
* ```${CHAT[TYPE]}```: Type
* ```${CHAT[ALL_MEMBERS_ARE_ADMINISTRATORS]}```: All members are administrators (true if true)
* ```$REPLYTO```: This array contains the First name, last name, username and user id of the ORIGINAL sender of the message REPLIED to.
* ```${REPLYTO[ID]}```: ID of message wich was replied to
* ```${REPLYTO[UID]}```: Original user's id
* ```${REPLYTO[FIRST_NAME]}```: Original user's first name
* ```${REPLYTO[LAST_NAME]}```: Original user's' last name
* ```${REPLYTO[USERNAME]}```: Original user's username
* ```$FORWARD```: This array contains the First name, last name, username and user id of the ORIGINAL sender of the FORWARDED message.
* ```${FORWARD[ID]}```: Same as MESSAGE[ID] if message is forwarded
* ```${FORWARD[UID]}```: Original user's id
* ```${FORWARD[FIRST_NAME]}```: Original user's first name
* ```${FORWARD[LAST_NAME]}```: Original user's' last name
* ```${FORWARD[USERNAME]}```: Original user's username
* ```$URLS```: This array contains documents, audio files, voice recordings and stickers as URL.
* ```${URLS[AUDIO]}```: Audio files
* ```${URLS[VIDEO]}```: Videos
* ```${URLS[PHOTO]}```: Photos (maximum quality)
* ```${URLS[VOICE]}```: Voice recordings
* ```${URLS[STICKER]}```: Stickers
* ```${URLS[DOCUMENT]}```: Any other file
* ```$CONTACT```: This array contains info about contacts sent in a chat.
* ```${CONTACT[ID]}```: User id
* ```${CONTACT[NUMBER]}```: Phone number
* ```${CONTACT[FIRST_NAME]}```: First name
* ```${CONTACT[LAST_NAME]}```: Last name
* ```${CONTACT[VCARD]}```: User's complete Vcard
* ```$LOCATION```: This array contains info about locations sent in a chat.
* ```${LOCATION[LONGITUDE]}```: Longitude
* ```${LOCATION[LATITUDE]}```: Latitude
* ```$VENUE```: This array contains info about venue (a place) sent in a chat.
* ```${VENUE[TITLE]}```: Name of the place
* ```${VENUE[ADDRESS]}```: Address of the place
* ```${VENUE[LONGITUDE]}```: Longitude
* ```${VENUE[LATITUDE]}```: Latitude
* ```${VENUE[FOURSQUARE]}```: Fouresquare ID
### Inline queries
Evertime a Message is recieved, you can read incoming data using the following variables:
* ```${iQUERY}```: Current inline query
* ```$iQUERY```: This array contains the ID, First name, last name, username and user id of the sender of the current inline query.
* ```${iQUERY[ID]}```: Inline query ID
* ```${iQUERY[USER_ID]}```: User's id
* ```${iQUERY[FIRST_NAME]}```: User's first name
* ```${iQUERY[LAST_NAME]}```: User's last name
## Usage of bashbot functions
#### sending messages
To send messages use the ```send_xxx_message``` functions.
To send regular text without any markdown use:
```bash
send_text_message "${CHAT[ID]}" "lol"
```
To send text with markdown:
```bash
send_markdown_message "${CHAT[ID]}" "lol *bold*"
```
To send text with html:
```bash
send_html_message "${CHAT[ID]}" "lol <b>bold</b>"
```
To forward messages use the ```forward``` function:
```bash
forward "${CHAT[ID]}" "from_chat_id" "message_id"
```
If your Bot is Admin in a Chat you can delete every message, if not you can delete only your messages.
To delete a message with a known ${MESSAGE[ID]} you can simple use:
```bash
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
```
#### send_message
In addition there is a universal send_massage function which can output any type of message.
This function is used to process output from external scrips like interactive chats or background jobs.
**For safety and performance reasons I recommend to use send_xxxx_message functions above for sending messages**
```bash
send_message "${CHAT[ID]}" "lol"
```
To send html or markdown put the following strings before the text, depending on the parsing mode you want to enable:
```bash
send_message "${CHAT[ID]}" "markdown_parse_mode lol *bold*"
```
```bash
send_message "${CHAT[ID]}" "html_parse_mode lol <b>bold</b>"
```
This function also allows a third parameter that disables additional function parsing (for safety use this when reprinting user input):
```bash
send_message "${CHAT[ID]}" "lol" "safe"
```
**See also [Interactive chats](3_advanced.md#Interactive-Chats)**
#### Send files, locations, keyboards.
To send images, videos, voice files, photos etc. use the ```send_photo``` function (remember to change the safety Regex @ line 14 of command.sh to allow sending files only from certain directories):
```bash
send_file "${CHAT[ID]}" "/home/user/doge.jpg" "Lool"
```
To send custom keyboards use the ```send_keyboard``` function:
```bash
send_keyboard "${CHAT[ID]}" "Text that will appear in chat?" '[ "Yep" , "No" ]' # note the simgle quotes!
send_keyboard "${CHAT[ID]}" "Text that will appear in chat?" "[ \\"Yep\\" , \\"No\\" ]" # within double quotes you must excape the inside double quots
```
To send locations use the ```send_location``` function:
```bash
send_location "${CHAT[ID]}" "Latitude" "Longitude"
```
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.
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"
```
**See also [Bashbot function reference](6_reference.md#Interactive_Chats)**
#### [Prev Create Bot](1_firstbot.md)
#### [Next Advanced Usage](3_advanced.md)
#### $$VERSION$$ v0.90-dev2-0-gec85636

View File

@ -0,0 +1,184 @@
#### [Home](../README.md)
## Advanced Features
### Access control
Bashbot offers functions to check what Telegram capabilities like 'chat admin' or 'chat creator' the given user has:
```bash
# return true if user is admin/owner of the bot
# -> botadmin is stored in file './botadmin'
user_is_botadmin "user"
# return true if user is creator or admin of a chat
user_is_admin "chat" "user"
# return true if user is creator of a chat or it's a one to one chat
user_is_creator "chat" "user"
# examples:
user_is_botadmin "${USER[ID]}" && send_markdown_message "${CHAT[ID]}" "You are *BOTADMIN*."
user_is_admin "${CHAT[ID]}" "${USER[ID]}" && send_markdown_message "${CHAT[ID]}" "You are *CHATADMIN*."
```
In addition you can check individual capabilities of users as you must define in the file ```./botacl```:
```bash
# file: botacl
# a user not listed here, will return false from 'user_is_allowed'
#
# Format:
# user:ressource:chat
# allow user 123456789 access to all resources in all chats
123456789:*:*
# allow user 12131415 to start bot in all chats
12131415:start:*
# allow user 987654321 only to start bot in chat 98979695
987654321:start:98979695
# * are only allowed on the right hand side and not for user!
# the following exaples are NOT valid!
*:*:*
*:start:*
*:*:98979695
```
You must use the function ```user_is_allowed``` to check if a user has the capability to do something. Example: Check if user has capability to start bot.
```bash
case "$MESSAGE" in
################################################
# GLOBAL commands start here, only edit messages
'/start'*)
user_is_botadmin "${USER[ID]}" && send_markdown_message "${CHAT[ID]}" "You are *BOTADMIN*."
if user_is_allowed "${USER[ID]}" "start" "${CHAT[ID]}" ; then
bot_help "${CHAT[ID]}"
else
send_normal_message "${CHAT[ID]}" "You are not allowed to start Bot."
;;
esac
```
**See also [Bashbot User Access Control functions](6_reference.md#User-Access-Control)**
### Interactive Chats
To create interactive chats, write *(or edit the 'exmaples/question.sh' script)* a bash *(or C or python)* script, make it executable
and then use the 'startproc' function to start the script.
The output of the script will be sent to the user and user input will be sent to the script.
To stop the script use the function 'killprog'
The output of the script will be processed by 'send_messages' to enable you to not only send text, but also keyboards, files, locations and more.
Each newline in the output will start an new message to the user, to have line breaks in your message you can use 'mynewlinestartshere'.
To open up a keyboard in an interactive script, print out the keyboard layout in the following way:
```bash
echo "Text that will appear in chat? mykeyboardstartshere [ \"Yep, sure\" , \"No, highly unlikely\" ]"
```
Same goes for files:
```bash
echo "Text that will appear in chat? myfilelocationstartshere /home/user/doge.jpg"
```
And buttons:
```bash
echo "Text that will appear in chat. mybtextstartshere Klick me myburlstartshere https://dealz.rrr.de"
```
And locations:
```bash
echo "Text that will appear in chat. mylatstartshere 45 mylongstartshere 45"
```
And venues:
```bash
echo "Text that will appear in chat. mylatstartshere 45 mylongstartshere 45 mytitlestartshere my home myaddressstartshere Diagon Alley N. 37"
```
You can combine them:
```bash
echo "Text that will appear in chat? mykeyboardstartshere [ \"Yep, sure\" , \"No, highly unlikely\" ] myfilelocationstartshere /home/user/doge.jpg mylatstartshere 45 mylongstartshere 45"
```
Please note that you can either send a location or a venue, not both. To send a venue add the mytitlestartshere and the myaddressstartshere keywords.
New in v0.6: To insert a linebreak in your message you can insert ```mynewlinestartshere``` in your echo command:
```bash
echo "Text that will appear in one message mynewlinestartshere with this text on a new line"
```
New in v0.7: In case you must extend a message already containing a location, a file, a keyboard etc.,
with 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."
echo "$out"
```
Note: Interactive Chats run independent from main bot and continue running until your script exits or you /cancel if from your Bot.
### Background Jobs
A background job is similar to an interactive chat, but runs in the background and does only output massages and does not get user input. In contrast to interactive chats it's possible to run multiple background jobs. To create a background job write a script or edit 'examples/notify.sh' script and use the funtion ```background``` to start it:
```bash
background "examples/notify.sh" "jobname"
```
All output of the script will be sent to the user, to stop a background job use:
```bash
killback "jobname"
```
You can also suspend and resume the last running background jobs from outside bashbot, e.g. in your startup schripts:
```bash
./bashbot.sh suspendback
./bashbot.sh resumeback
```
If you want to kill all background jobs permantly run:
```bash
./bashbot.sh killback
```
Note: Background Jobs run independent from main bot and continue running until your script exits or you stop if from your Bot. Backgound Jobs will continue running if your Bot is stopeda and must be terminated, e.g. by ```bashbot.sh killback```
### Inline queries
**Inline queries** allow users to send commands to your bot from every chat without going to a private chat. An inline query is started if the user type the bots name, e.g. @myBot. Everything after @myBot is immediatly send to the bot.
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 bots 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'.
To send messsages or links through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "article" "Title of the result" "Content of the message to be sent"
```
To send photos in jpeg format and less than 5MB, from a website through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "photo" "A valid URL of the photo" "URL of the thumbnail"
```
To send standard gifs from a website (less than 1MB) through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "gif" "gif url"
```
To send mpeg4 gifs from a website (less than 1MB) through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "mpeg4_gif" "mpeg4 gif url"
```
To send videos from a website through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "video" "valid video url" "Select one mime type: text/html or video/mp4" "URL of the thumbnail" "Title for the result"
```
To send photos stored in Telegram servers through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "cached_photo" "identifier for the photo"
```
To send gifs stored in Telegram servers through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "cached_gif" "identifier for the gif"
```
To send mpeg4 gifs stored in Telegram servers through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "cached_mpeg4_gif" "identifier for the gif"
```
To send stickers through an *inline query*:
```bash
answer_inline_query "${iQUERY[ID]}" "cached_sticker" "identifier for the sticker"
```
See also [answer_inline_multi, answer_inline_compose](6_reference.md#answer_inline_multi) and [mycommands.sh](../mycommands.sh) for more information.
#### [Prev Getting started](2_usage.md)
#### [Next Expert Use](4_expert.md)
#### $$VERSION$$ v0.90-dev2-0-gec85636

View File

@ -0,0 +1,352 @@
#### [Home](../README.md)
## Expert Use
### Handling UTF-8 character sets
UTF-8 is a variable length encoding of Unicode. UTF-8 is recommended as the default encoding in JSON, XML and HTML, also Telegram make use of it.
The first 128 characters are regular ASCII, so it's a superset of and compatible with ASCII environments. The next 1,920 characters need
two bytes for encoding and covers almost all ```Latin``` alphabets, also ```Greek```, ```Cyrillic```,
```Hebrew```, ```Arabic``` and more. See [Wikipedia](https://en.wikipedia.org/wiki/UTF-8) for more details.
#### Setting up your Environment
In general ```bash``` and ```GNU``` utitities are UTF-8 aware if you to setup your environment
and your scripts accordingly:
1. Your Terminal and Editor must support UTF-8:
Set Terminal and Editor locale to UTF-8, eg. in ```Settings/Configuration``` select UTF-8 (Unicode) as Charset.
2. Set ```Shell``` environment to UTF-8 in your ```.profile``` and your scripts. The usual settings are:
```bash
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
```
If you use other languages, eg. german or US english, change the shell settings to:
```bash
export 'LC_ALL=de_DE.UTF-8'
export 'LANG=de_DE.UTF-8'
export 'LANGUAGE=de_DE.UTF-8'
```
```bash
export 'LC_ALL=en_US.UTF-8'
export 'LANG=de_en_US.UTF-8'
export 'LANGUAGE=den_US.UTF-8'
```
3. make shure your bot scripts use the correct settings, eg. include the lines above at the beginning of your scripts
To display all availible locales on your system run ```locale -a | more```. [Gentoo Wiki](https://wiki.gentoo.org/wiki/UTF-8)
#### Bashbot UTF-8 Support
Bashbot handles all messages transparently, regardless of the charset in use. The only exception is when converting from JSON data to strings.
Telegram use JSON to send / recieve data. JSON encodes strings as follow: Characters not ASCII *(>127)* are escaped as sequences of ```\uxxxx``` to be regular ASCII. In addition multibyte characters, *e.g. Emoticons or Arabic characters*, are send in double byte UTF-16 notation.
The Emoticons ``` 😁 😘 ❤️ 😊 👍 ``` are encoded as: ``` \uD83D\uDE01 \uD83D\uDE18 \u2764\uFE0F \uD83D\uDE0A \uD83D\uDC4D ```
**This "mixed" JSON encoding needs special handling and can not decoded from** ```echo -e``` or ```printf '%s\\n'```
Most complete support for decoding of multibyte characters can only be provided if python is installed on your system.
**Without phyton bashbot falls back to an internal, pure bash implementation which may not work for some corner cases**.
### Run as other user or system service
Bashbot is desingned to run manually by the user who installed it. Nevertheless it's possible to run it by an other user-ID, as a system service or sceduled from cron. This is onyl recommended for experiend linux users.
Setup the environment for the user you want to run bashbot and enter desired username, e.g. nobody :
```bash
sudo ./bashbot.sh init
```
Edit the file ```bashbot.rc``` and edit the following lines to fit your configuration:
```bash
#######################
# Configuration Section
# edit the next line to fit the user you want to run bashbot, e.g. nobody:
runas="nobody"
# uncomment one of the following lines
# runcmd="su $runas -s /bin/bash -c " # runasuser with su
# runcmd="runuser $runas -s /bin/bash -c " # runasuser with runuser
# edit the values of the following lines to fit your config:
start="/usr/local/telegram-bot-bash/bashbot.sh" # location of your bashbot.sh script
name='' # your bot name as given to botfather, e.g. mysomething_bot
# END Configuration
#######################
```
From now on use 'bashbot.rc' to manage your bot:
```bash
sudo ./bashbot.rc start
```
Type ```ps -ef | grep bashbot``` to verify your Bot is running as the desired user.
If your Bot is started by 'bashbot.rc', you must use 'bashbot.rc' also to manage your Bot! The following commands are availible:
```bash
sudo ./bashbot.rc start
sudo ./bashbot.rc stop
sudo ./bashbot.rc status
sudo ./bashbot.rc suspendback
sudo ./bashbot.rc resumeback
sudo ./bashbot.rc killback
```
To change back the environment to your user-ID run ```sudo ./bashbot.sh init``` again and enter your user name.
To use bashbot as a system servive include a working ```bashbot.rc``` in your init system (systemd, /etc/init.d).
### Scedule bashbot from Cron
An example crontab is provided in ```examples/bashbot.cron```.
- If you are running bashbot with your user-ID, copy the examples lines to your crontab and remove username ```nobody```.
- if you run bashbot as an other user or a system service edit ```examples/bashbot.cron``` to fit your needs and replace username```nobody``` with the username you want to run bashbot. copy the modified file to ```/etc/cron.d/bashbot```
### Use bashbot from CLI and scripts
You can use bashbot to send *messages*, *locations*, *venues*, *pictures* etc. from command line and scripts
by sourcing it:
*usage:* . bashbot.sh source
Before sourcing 'bahsbot.sh' for interactive and script use, you should export and set BASHBOT_HOME to bashbots installation dir,
e.g. '/usr/local/telegram-bot-bash'. see [Bashbot Environemt](#Bashbot-environment)
**Note:** *If you don't set BASHBOT_HOME bashbot will use the actual directory as NEW home directory
which means it will create all needed files and ask for bot token and botadmin if you are not in the real bot home!*
*Examples:*
```bash
# if you are in the bashbot directory
. bashbot.sh source
# same, but more readable in scripts
source ./bashbot.sh source
# use bashbot config in BASHBOT_HOME from any directory
export BASHBOT_HOME=/usr/local/telegram-bot-bash
source ${BASHBOT_HOME}/bashbot.sh source
# use / create new config in current directory
unset BASHBOT_HOME
source /path/to/bashbot.sh source
```
#### Environment variable exported from bashbot
If you have sourced 'bashbot.sh' you have the following bashot internal variables availible:
```bash
COMMANDS # default: ./commands.sh"
MODULEDIR # default: ./modules"
TOKENFILE # default: ./token"
BOTADMIN # default: ./botadmin"
BOTACL # default: ./botacl"
TMPDIR # default: ./data-bot-bash"
COUNTFILE # default: ./count"
BOTTOKEN # default: content of ${TOKENFILE}
URL # telegram api URL - default: https://api.telegram.org/bot${BOTTOKEN}"
```
#### Interacctive use
For testing your setup or sending messages yoursel you can use bashbot functions from bash command line:
```bash
# are we running bash?
echo $SHELL
/bin/bash
# source bashbot.sh WITHOUT BASHBOT_HOME set
./bashbot.sh source
# output bashbot internal variables
echo $COMMANDS $MODULEDIR $TOKENFILE $BOTADMIN $BOTACL $TMPDIR $COUNTFILE
./commands.sh ./modules ./token ./botadmin ./botacl ./data-bot-bash ./count
# source bashbot.sh WITH BASHBOT_HOME set
export BASHBOT_HOME=/usr/local/telegram-bot-bash
source ./bashbot.sh source
# output bashbot internal variables
echo $COMMANDS $MODULEDIR $TOKENFILE $BOTADMIN $BOTACL $TMPDIR $COUNTFILE
/usr/local/telegram-bot-bash/commands.sh /usr/local/telegram-bot-bash/modules /usr/local/telegram-bot-bash/token
/usr/local/telegram-bot-bash/botadmin /usr/local/telegram-bot-bash/botacl /usr/local/telegram-bot-bash/data-bot-bash
/usr/local/telegram-bot-bash/count
```
After sourcing you can use bashbot functions to send Messages, Locations, Pictures etc. to any Telegram
User or Chat you are in. See [Send Messages](2_usage.md#sending-messages).
*Examples:* You can test this by sending messages to yourself:
```bash
# fist Hello World
send_normal_message "$(< $BOTADMIN)" "Hello World! This is my first message"
# now with some markdown and HTML
send_markdown_message "$(< $BOTADMIN)" '*Hello World!* _This is my first markdown message_'
send_html_message "$(< $BOTADMIN)" '<b>Hello World!</b> <em>This is my first HTML message</em>'
send_keyboard "$(< $BOTADMIN)" 'Do you like it?' '[ "Yep" , "No" ]'
```
Now something more useful ...
```bash
# sending output from system commands:
send_normal_message "$(< $BOTADMIN)" "$(date)"
send_normal_message "$(< $BOTADMIN)" "$(uptime)"
send_normal_message "$(< $BOTADMIN)" '`'$(free)'`'
# same but markdown style 'code' (monospaced)
send_markdown_message "$(< $BOTADMIN)" "\`$(free)\`"
```
### Bashbot environment
This section describe how you can customize bashbot to your needs by setting environment variables.
#### Change file locations
In standard setup bashbot is self containing, this means you can place 'telegram-bot-bash' any location
and run it from there. All files - programm, config, data etc - will reside in 'telegram-bot-bash'.
If you want to have other locations for config, data etc, define and export the following environment variables.
**Note: all specified directories and files must exist or running 'bashbot.sh' will fail.**
##### BASHBOT_ETC
Location of the files ```commands.sh```, ```mycommands.sh```, ```token```, ```botadmin```, ```botacl``` ...
```bash
unset BASHBOT_ETC # keep in telegram-bot-bash (default)
export BASHBOT_ETC "" # keep in telegram-bot-bash
export BASHBOT_ETC "/etc/bashbot" # unix like config location
export BASHBOT_ETC "/etc/bashbot/bot1" # multibot configuration bot 1
export BASHBOT_ETC "/etc/bashbot/bot2" # multibot configuration bot 2
```
e.g. /etc/bashbot
##### BASHBOT_VAR
Location of runtime data ```data-bot-bash```, ```count```
```bash
unset BASHBOT_VAR # keep in telegram-bot-bash (default)
export BASHBOT_VAR "" # keep in telegram-bot-bash
export BASHBOT_VAR "/var/spool/bashbot" # unix like config location
export BASHBOT_VAR "/var/spool/bashbot/bot1" # multibot configuration bot 1
export BASHBOT_VAR "/var/spool/bashbot/bot2" # multibot configuration bot 2
```
##### BASHBOT_JSONSH
Full path to JSON.sh script, default: './JSON.sh/JSON.sh', must end with '/JSON.sh'.
```bash
unset BASHBOT_JSONSH # telegram-bot-bash/JSON.sh/JSON.sh (default)
export BASHBOT_JSONSH "" # telegram-bot-bash/JSON.sh/JSON.sh
export BASHBOT_JSONSH "/usr/local/bin/JSON.sh" # installed in /usr/local/bin
```
##### BASHBOT_HOME
Set bashbot home directory, where bashot will look for additional files.
If BASHBOT_ETC, BASHBOT_VAR or BASHBOT_JSONSH are set the have precedence over BASHBOT_HOME.
This is also usefull if you want to force bashbot to always use full pathnames instead of relative ones.
```bash
unset BASHBOT_HOME # autodetection (default)
export BASHBOT_HOME "" # autodetection
export BASHBOT_HOME "/usr/local/telegram-bot-bash" # unix like location
export BASHBOT_HOME "/usr/local/bin" # Note: you MUST set ETC, VAR and JSONSH to other locations to make this work!
```
----
#### Change config values
##### BASHBOT_URL
Uses given URL instead of offical telegram API URL, useful if you have your own telegram server or for testing.
```bash
unset BASHBOT_URL # use Telegram URL https://api.telegram.org/bot<token> (default)
export BASHBOT_URL "" # use use Telegram https://api.telegram.org/bot<token>
export BASHBOT_URL "https://my.url.com/bot" # use your URL https://my.url.com/bot<token>
```
##### BASHBOT_TOKEN
##### BASHBOT_WGET
Bashbot uses ```curl``` to communicate with telegram server. if ```curl``` is not availible ```wget``` is used.
If 'BASHBOT_WGET' is set to any value (not undefined or not empty) wget is used even is curl is availible.
```bash
unset BASHBOT_WGET # use curl (default)
export BASHBOT_WGET "" # use curl
export BASHBOT_WGET "yes" # use wget
export BASHBOT_WGET "no" # use wget!
```
##### BASHBOT_SLEEP
Instead of polling permanently or with a fixed delay, bashbot offers a simple adaptive polling.
If messages are recieved bashbot polls with no dealy. If no messages are availible bashbot add 100ms delay
for every poll until the maximum of BASHBOT_SLEEP ms.
```bash
unset BASHBOT_SLEEP # 5000ms (default)
export BASHBOT_SLEEP "" # 5000ms
export BASHBOT_SLEEP "1000" # 1s maximum sleep
export BASHBOT_SLEEP "10000" # 10s maximum sleep
export BASHBOT_SLEEP "1" # values < 1000 disables sleep (not recommended)
```
#### Testet configs as of v0.90 release
**Note: Environment variables are not stored, you must setup them before every call to bashbot.sh, e.g. from a script.**
##### simple Unix like config, for one bot. bashbot is installed in '/usr/local/telegram-bot-bash'
```bash
# Note: all dirs and files must exist!
export BASHBOT_ETC "/etc/bashbot"
export BASHBOT_VAR "/var/spool/bashbot"
/usr/local/telegram-bot-bash/bashbot.sh start
```
##### Unix like config for one bot. bashbot.sh is installed in '/usr/bin'
```bash
# Note: all dirs and files must exist!
export BASHBOT_ETC "/etc/bashbot"
export BASHBOT_VAR "/var/spool/bashbot"
export BASHBOT_JSONSH "/var/spool/bashbot"
/usr/local/bin/bashbot.sh start
```
##### simple multibot config, everything is keept inside 'telegram-bot-bash' dir
```bash
# config for running Bot 1
# Note: all dirs and files must exist!
export BASHBOT_ETC "./mybot1"
export BASHBOT_VAR "./mybot1"
/usr/local/telegram-bot-bash/bashbot.sh start
```
```bash
# config for running Bot 2
# Note: all dirs and files must exist!
export BASHBOT_ETC "./mybot2"
export BASHBOT_VAR "./mybot2"
/usr/local/telegram-bot-bash/bashbot.sh start
```
#### [Prev Advanced Use](3_advanced.md)
#### [Next Best Practice](5_practice.md)
#### $$VERSION$$ v0.90-dev2-19-g5779acc

View File

@ -0,0 +1,156 @@
#### [Home](../README.md)
## Best Practices
### New to bot development?
If you are new to Bot development read [Bots: An introduction for developers](https://core.telegram.org/bots) and consult [Telegram Bot API Documentation](https://core.telegram.org/bots/api/).
In addition you should know about [BotFather, the one bot to rule them all](https://core.telegram.org/bots#3-how-do-i-create-a-bot). It will help you create new bots and change settings for existing ones. [Commands known by Botfather](https://core.telegram.org/bots#generating-an-authorization-token)
If you dont't have a github account, it may time to [sepup a free account now](https://github.com/pricing)
### Add commands to mycommands.sh only
To ease updates never change ```bashbot.sh```, instead your commands and functions must go to ```mycommands.sh``` . Insert your Bot commands in the ```case ... esac``` block of the 'mycommands()' function:
```bash
# file: mycommands.sh
# your additional bahsbot commands
# uncomment the following lines to overwrite info and help messages
bashbot_info='This is *MY* variant of _bashbot_, the Telegram bot written entirely in bash.
'
bashbot_help='*Available commands*:
/echo message - _echo the given messsage_
'
# NOTE: command can have @botname attached, you must add * in case tests...
mycommands() {
case "$MESSAGE" in
'/echo'*) # example echo command
send_normal_message "${CHAT[ID]}" "$MESSAGE"
;;
# .....
esac
}
```
### Overwrite, extend and disable global commands
You can overwrite a global bashbot command by placing the same commands in ```mycommands.sh``` and add ```return 1```
ad the end of your command, see '/kickme' below.
To disable a global bashbot command place create a command simply containing 'return 1', see '/leave' below.
In case you want to add some processing to the global bashbot command add ```return 0```, then both command will be executed.
**Learn more about [Bot commands](https://core.telegram.org/bots#commands).**
```bash
# file: commands.sh
case "$MESSAGE" in
##########
# command overwrite examples
'info'*) # output date in front of regular info
send_normal_message "${CHAT[ID]}" "$(date)"
return 0
;;
'/kickme'*) # this will replace the /kickme command
send_markdown_mesage "${CHAT[ID]}" "*This bot will not kick you!*"
return 1
;;
'/leave'*) # disable all commands starting with leave
return 1
;;
esac
```
### Seperate logic from commands
If a command need more than 2-3 lines of code, you should use a function to seperate logic from command. Place your functions in ```mycommands.sh``` and call the from your command. Example:
```bash
# file: mycommands.sh
# your additional bahsbot commands
mycommands() {
case "$MESSAGE" in
'/process'*) # logic for /process is done in process_message
result="$(process_message "$MESSAGE")"
send_normal_message "${CHAT[ID]}" "$result"
;;
esac
}
# place your functions here
process_message() {
local ARGS="${1#/* }" # remove command
local TEXT OUTPUT=""
# process every word in MESSAGE, avoid globbing
set -f
for WORD in $ARGS
do
# process links
if [[ "$WORD" == "https://"* ]]; then
REPORT="$(dosomething_with_link "$WORD")"
# no link, add as text
else
TEXT="$(echo "${TEXT} $WORD")"
continue
fi
# compose result
OUTPUT="* ${REPORT} ${WORD} ${TEXT}"
TEXT=""
done
# return result, reset globbing in case we had no ARGS
echo "${OUTPUT}${TEXT}"
}
```
### Test your Bot with shellcheck
Shellcheck is a static linter for shell scripts providing excellent tips and hints for shell coding pittfalls. You can [use it online](https://www.shellcheck.net/) or [install it on your system](https://github.com/koalaman/shellcheck#installing).
All bashbot scripts are linted by shellcheck.
Shellcheck examples:
```bash
$ shellcheck -x mybotcommands.inc.sh
Line 17:
TEXT="$(echo "${TEXT} $WORD")"
^-- SC2116: Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'.
```
As you can see my ```mybotcommands.inc.sh``` contains an useless echo command in 'TEXT=' assigment and can be replaced by ```TEXT="${TEXT}${WORD}"```
```bash
$ shellcheck -x examples/notify
OK
$ shellcheck -x examples/question
OK
$ shellcheck -x commands.sh
OK
$ shellcheck -x bashbot.sh
In bashbot.sh line 123:
text="$(echo "$text" | sed 's/ mynewlinestartshere /\r\n/g')" # hack for linebreaks in startproc scripts
^-- SC2001: See if you can use ${variable//search/replace} instead.
In bashbot.sh line 490:
CONTACT[USER_ID]="$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","contact","user_id"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")"
^-- SC2034: CONTACT appears unused. Verify it or export it.
```
The example show two warnings in bashbots scripts. The first is a hint you may use shell substitions instead of sed, this is fixed and much faster as the "echo | sed" solution.
The second warning is about an unused variable, this is true because in our examples CONTACT is not used but assigned in case you want to use it :-)
#### [Prev Best Practice](5_practice.md)
#### [Next Functions Reference](6_reference.md)
#### $$VERSION$$ v0.90-dev2-0-gec85636

View File

@ -0,0 +1,692 @@
#### [Home](../README.md)
## Bashbot function reference
### Send, forward, delete messages
##### send_action
```send_action``` shows users what your bot is currently doing.
*usage:* send_action "${CHAT[ID]}" "action"
*"action":* ```typing```, ```upload_photo```, ```record_video```, ```upload_video```, ```record_audio```, ```upload_audio```, ```upload_document```, ```find_location```.
*alias:* _action "action"
*example:*
```bash
send_action "${CHAT[ID]}" "typing"
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"
*alias:* _normal_message "message"
*example:*
```bash
send_normal_message "${CHAT[ID]}" "this is a text message"
```
##### send_markdown_message
```send_markdown_message``` sends markdown style messages to the given chat.
Telegram supports a [reduced set of Markdown](https://core.telegram.org/bots/api#markdown-style) only
*usage:* send_markdown_message "${CHAT[ID]}" "markdown message"
*alias:* _markdown "message"
*example:*
```bash
send_markdown_message "${CHAT[ID]}" "this is a markdown message, next word is *bold*"
send_markdown_message "${CHAT[ID]}" "*bold* _italic_ [text](link)"
```
##### send_html_message
```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"
*alias:* _html_message "message"
*example:*
```bash
send_normal_message "${CHAT[ID]}" "this is a markdown message, next word is <b>bold</b>"
send_normal_message "${CHAT[ID]}" "<b>bold</b> <i>italic><i> <em>italic>/em> <a href="link">Text</a>"
```
##### forward_message
```forward_mesage``` forwards a messsage to the given chat.
*usage:* forward_message "chat_to" "chat_from" "${MESSAGE[ID]}"
*old call:* forward "${CHAT[ID]}" "$FROMCHAT" "${MESSAGE[ID]}"
*alias:* _forward "$FROMCHAT" "${MESSAGE[ID]}"
See also [Text formating options](https://core.telegram.org/bots/api#formatting-options)
----
##### delete_message
If your Bot is admin of a Chat he can delete every message, if not he can delete only his messages.
*usage:* delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
*alias:* _del_message "${MESSAGE[ID]}"
See also [deleteMessage limitations](https://core.telegram.org/bots/api#deletemessage)
----
##### send_message
```send_message``` sends any type of message to the given chat. Type of output is steered by keywords within the message.
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"
*example:* - see [Usage](2_usage.md#send_message) and [Advanced Usage](3_advanced.md#Interactive-Chats)
----
### File, Location, Venue, Keyboard
##### send_file
send_file allows you to send different type's of files, e.g. photos, stickers, audio, media, etc. [see more](https://core.telegram.org/bots/api#sending-files)
Starting with version 0.80 send_file implements the following rules:
- file names must not contain ".."
- file names must not start with "."
- file names not starting wit "/" are realtive to $TMPDIR, e.g. ./data-bot-bash
- abolute filenames must match $FILE_REGEX
*usage:* send_file "${CHAT[ID]}" "file" "caption"
*example:*
```bash
send_file "${CHAT[ID]}" "/home/user/doge.jpg" "Lool"
send_file "${CHAT[ID]}" "https://www.domain,com/something.gif" "Something"
```
##### send_location
*usage:* send_location "${CHAT[ID]}" "Latitude" "Longitude"
##### send_venue
*usage:* send_venue "${CHAT[ID]}" "Latitude" "Longitude" "Title" "Address" "foursquare id (optional)"
----
##### send_keyboard
Note: since version 0.6 send_keyboard was changed to use native "JSON Array" notation as used from Telegram. Example Keybord 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" ]'
- numpad style keyboard: '[ "1" , "2" , "3" ] , [ "4" , "5" , "6" ] , [ "7" , "8" , "9" ] , [ "0" ]'
*usage:* send_keyboard "chat-id" "message" "keyboard"
*alias:* _keyboard "message" "keyboard"
*example:*
```bash
send_keyboard "${CHAT[ID]}" "Say yes or no" "[ \\"yes\" , \\"no\" ]""
send_keyboard "${CHAT[ID]}" "Say yes or no" "[ \\"yes\\" ] , [ \\"no\\" ]"
send_keyboard "${CHAT[ID]}" "Enter digit" "[ \\"1\\" , \\"2\\" , \\"3\\" ] , [ \\"4\\" , \\"5\\" , \\"6\\" ] , [ \\"7\\" , \\"8\\" , \\"9\\" ] , [ \\"0\\" ]"
```
##### remove_keyboard
*usage:* remove_keybord "$CHAT[ID]" "message"
*alias:* _del_keyboard "message"
*See also: [Keyboard Markup](https://core.telegram.org/bots/api/#replykeyboardmarkup)*
----
##### send_button
*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_inline_keyboard
This allows to place multiple inline buttons in a row. The inline buttons must specified as a JSON array in the following format:
```[ {"text":"text1", "url":"url1"}, ... {"text":"textN", "url":"urlN"} ]```
Each button consists of a pair of text and URL values, sourrounded by '{ }', multiple buttons are seperated by '**,**' and everthing 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"} ]'
```
*See also [Inline keyboard markup](https://core.telegram.org/bots/api/#inlinekeyboardmarkup)*
----
### User Access Control
##### 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]}"
*alias:* _kick_user "${USER[ID]}"
##### unban_chat_member
If your Bot is a chat admine can unban a kicked user.
*usage:* unban_chat_member "${CHAT[ID]}" "${USER[ID]}"
*alias:* _unban "${USER[ID]}"
##### leave_chat
Your Bot will leave the chat.
*usage:* leave_chat "${CHAT[ID]}"
*alias:* _leave
```bash
if _is_admin ; then
send_markdown_message "${CHAT[ID]}" "*LEAVING CHAT...*"
leave_chat "${CHAT[ID]}"
fi
```
'See also [kick Chat Member](https://core.telegram.org/bots/api/#kickchatmember)*
----
##### 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]}"
*alias:* _is_botadmin
*example:*
```bash
_is_botadmin && send_markdown_message "${CHAT[ID]}" "You are *BOTADMIN*."
```
##### 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]}"
*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]}"
*alias:* _is_admin
*example:*
```bash
if _is_admin ; then
send_markdown_message "${CHAT[ID]}" "*LEAVING CHAT...*"
leave_chat "${CHAT[ID]}"
fi
```
*See also [Chat Member](https://core.telegram.org/bots/api/#chatmember)*
##### user_is_allowed
Bahsbot supports User Access Control, see [Advanced Usage](3_advanced.md)
*usage:* user_is_allowed "${USER[ID]}" "what" "${CHAT[ID]}"
*example:*
```bash
if ! user_is_allowed "${USER[ID]}" "start" "${CHAT[ID]}" ; then
send_normal_message "${CHAT[ID]}" "You are not allowed to start Bot."
fi
```
----
### Inline Queries - answer direct queries to bot
You must include ```source modules/inline.sh``` in 'commands.sh' to have the following functions availible.
Inline Queries allows users to interact with your bot directly without sending extra commands.
As an answer to an inline query you can send back one or more results to the Telegram client.
The Telegram client will then show the results to the user and let him select one.
##### answer_inline_query
answer_inline_query is provided for backward compatibility with older versions of bashbot.
It send back only one response to an inline query.
*usage:* answer_inline_query "$i{QUERY[ID]}" "type" "type arg 1" ... "type arg n"
*example:* - see [Advanced Usage](3_advanced.md#Inline-queries)
##### answer_inline_multi
anser_inline_multi allows you to send back a list of responses. responses must be seperated by ','.
*usage:* answer_inline_multi "${iQUERY[ID]}" "res, res, ... res"
*example:*
```bash
# note the starting " and ending " !!
answer_inline_multi "${iQUERY[ID]}" "
$(inline_query_compose "1" "photo" "https://avatars0.githubusercontent.com/u/13046303") ,
...
$(inline_query_compose "n" "photo" "https://avatars1.githubusercontent.com/u/4593242")
"
```
#### inline_query_compose
inline_query_compose composes one response element to to send back.
*usage:* inline_query_compose ID type args ....
```
ID = unique ID for this response, 1-64 byte long
type = type of answer, e.g. article, photo, video, location ...
args = mandatory arguments in the order they are described in telegram documentation
```
Currently the following types and arguments are implemented (optional arguments in parenthesis)
```
"article"|"message" title message (markup description)
"photo" photo_URL (thumb_URL title description caption)
"gif" photo_URL (thumb_URL title caption)
"mpeg4_gif" mpeg_URL (thumb_URL title caption)
"video" video_URL mime_type thumb_URL title (caption)
"audio" audio_URL title (caption)
"voice" voice_URL title (caption)
"document" title document_URL mime_type (caption description)
"location" latitude longitude title
"venue" latitude longitude title (adress foursquare)
"contact" phone first (last thumb)
"cached_photo" file (title description caption)
"cached_gif" file (title caption)
"cached_mpeg4_gif" file (title caption)
"cached_sticker" file
"cached_document" title file (description caption)
"cached_video" file title (description caption)
"cached_voice" file title (caption)
"cached_audio" file title (caption)
```
see [InlineQueryResult for more information](https://core.telegram.org/bots/api#inlinequeryresult) about response types and their arguments.
----
### Background and Interactive jobs
You must include ```source modules/background.sh``` in 'commands.sh' to have the following functions availible.
##### 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"
*alias:* startproc "script"
*example:*
```bash
startproc 'examples/calc.sh'
```
##### check_proc
Return true (0) if an interactive script is running in the chat.
*usage:* check_prog "${CHAT[ID]}"
*alias:* checkprog
*example:*
```bash
if ! check_proc "${CHAT[ID]}" ; then
startproc "examples/calc.sh"
else
send_normal_message "${CHAT[ID]}" "Calc already running ..."
fi
```
##### kill_proc
Kill the interactive script running in the chat
*usage:* kill_proc "${CHAT[ID]}"
*alias:* killproc
*example:*
```bash
if check_proc "${CHAT[ID]}" ; then
killproc && send_message "${CHAT[ID]}" "Command canceled."
else
send_message "${CHAT[ID]}" "Command is not running."
fi
```
----
##### start_back
Starts a script as a background job and attaches a jobname to it. All output from a background job is sent to the associated chat.
In contrast to interactive chats, background jobs do not recieve 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"
*alias:* background "script" "jobname"
*example:*
```bash
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"
*alias:* checkback "jobname"
*example:*
```bash
if ! checkback "notify" ; then
send_normal_message "${CHAT[ID]}" "Start notify"
background "examples/notify.sh" "notify"
else
send_normal_message "${CHAT[ID]}" "Process notify already running."
fi
```
##### kill_back
*usage:* kill_back "${CHAT[ID]}" "jobname"
*alias:* killback "jobname"
*example:*
```bash
checkback "notify"
if [ "$res" -eq 0 ] ; then
send_normal_message "${CHAT[ID]}" "Kill notify"
killback "notify"
else
send_normal_message "${CHAT[ID]}" "Process notify not run."
fi
```
----
##### send_interactive
Form version 0.80 on forward_message is used to forward messages to interactive job. It replaces the old 'inproc' commands used for TMUX.
Usually message is automatically forwarded in 'commands.sh', but you can forward messages wihle processing also or send your own messages.
*usage:* send_interactive "${CHAT[ID]}" "message"
*replaces:*' incproc
### Aliases - shortcuts for often used funtions
You must include ```source modules/aliases.sh``` in 'commands.sh' to have the following functions availible.
##### _is_botadmin
*usage:* _is_botadmin
*alias for:* user_is_botadmin "${USER[ID]}"
##### _is_admin
*usage:* _is_admin
*alias for:* user_is_admin "${CHAT[ID]}" "${USER[ID]}"
##### _is_allowed
*usage:* _is_allowed "what"
*alias for:* user_is_allowed "${USER[ID]}" "what" "${CHAT[ID]}"
----
##### _kick_user
*usage:* _kick_user "${USER[ID]}"
*alias for:* kick_chat_member "${CHAT[ID]}" "${USER[ID]}"
##### _unban
*usage:* _unban "${USER[ID]}"
*alias for:* unban_chat_member "${CHAT[ID]}" "${USER[ID]}"
##### _leave
*usage:* _leave
*alias for:* leave_chat "${CHAT[ID]}"
----
##### _message
*usage:* _message "message"
*alias for:* send_normal_message "${CHAT[ID]}" "message"
##### _normal_message
*usage:* _normal_message "message"
*alias for:* send_normal_message "${CHAT[ID]}" "message"
##### _html_message
*usage:* _html_message "message"
*alias for:* send_html_message "${CHAT[ID]}" "message"
##### _markdown_message
*usage:* _markdown_message "message"
*alias for:* send_markdown_message "${CHAT[ID]}" "message"
----
#### _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
*alias for:* send_keyboard "${CHAT[ID]}" "" '["1","2","3"],["4","5","6"],["7","8","9"],["-","0","."]' "yes"
#### _keyboard_yesno
*usage:* _keyboard_yesno
*alias for:* send_keyboard '["yes","no"]'
#### _del_keyboard
*usage:* _del_keyboard
*alias for:* remove_keyboard "${CHAT[ID]}" ""
### Helper functions
##### download
Download the fiven URL ans returns the final filename in TMPDIR. If the given filename exists,the filename is prefixed with a
random number. filename is not allowed to contain '/' or '..'.
*usage:* download URL filename
*example:*
```bash
file="$(download "https://avatars.githubusercontent.com/u/13046303" "avatar.jpg")"
echo "$file" -> ./data-bot-bash/avatar.jpg
file="$(download "https://avatars.githubusercontent.com/u/13046303" "avatar.jpg")"
echo "$file" -> ./data-bot-bash/12345-avatar.jpg
```
##### _exists
Returns true if the given function exist, can be used to check if a module is loaded.
*usage* _exists command
*example:*
```bash
_exists "curl" && _message "Command curl is not installed!"
```
##### _is_function
Returns true if the given function exist, can be used to check if a module is loaded.
*usage* _is_function function
*example:*
```bash
_is_function "background" && _message "you can run background jobs!"
```
----
### Bashbot internal functions
These functions are for internal use only and must not used in your bot commands.
##### procname
Returns PrefixBotname_Postfix
*usage:* procname postfix prefix
*example:*
```bash
# returns botname, if already set
procname
# returns unique identifier for everthing related to chat
procname "${CHAT[ID]}"
# returns unique identifier for job, regardless of chat
procname "" "back-jobname-"
# returns unique identifier for a job related to a chat
# e.g. fifo, cmd and logfile name
procname "${CHAT[ID]}" "back-jobname-"
```
##### proclist
Returns process IDs of current bot processes containing string 'pattern' in name or argument.
*usage:* proclist pattern
*example:*
```bash
# list PIDs of all background processes
proclist "back-"
# list PIDs of all processes of a job
proclist "back-jobname-"
# list PIDs of all processes for a chat
proclist "_${CHAT[ID]}"
# list PIDs of all bot processes
proclist
```
##### killallproc
kill all current bot processes containing string 'pattern' in name or argument
*usage:* killallproc pattern
*example:*
```bash
# kill all background processes
killallproc "back-"
# kill all processes for a chat
killallproc "_${CHAT[ID]}"
# kill all bot processes, including YOURSELF!
killallproc
```
##### get_file
*usage:* url="$(get_file "${CHAT[ID]}" "message")"
----
##### send_text
*usage:* send_text "${CHAT[ID]}" "message"
----
##### JsonDecode
Outputs decoded string to STDOUT
*usage:* JsonDecode "string"
##### JsonGetString
Reads JSON fro STDIN and Outputs found String to STDOUT
*usage:* JsonGetString `"path","to","string"`
##### JsonGetValue
Reads JSON fro STDIN and Outputs found Value to STDOUT
*usage:* JsonGetValue `"path","to","value"`
----
##### get_chat_member_status
*usage:* get_chat_member_status "${CHAT[ID]}" "${USER[ID]}"
this may get an official function ...
----
##### process_client
Every Message sent to your Bot is processd by this function. It parse the send JSON and assign the found Values to bash variables.
##### process_updates
If new updates are availible, this functions gets the JSON from Telegram and dispatch it.
----
##### getBotName
The name of your bot is availible as bash variable "$ME", there is no need to call this function if Bot is running.
*usage:* ME="$(getBotNiname)"
#### [Prev Best Practice](5_practice.md)
#### [Next Notes for Developers](7_develop.md)
#### $$VERSION$$ v0.90-dev2-0-gec85636

View File

@ -0,0 +1,276 @@
#### [Home](../README.md)
## Notes for bashbot developers
This section is about help and best practices for new bashbot developers. The main focus on is creating new versions of bashbot, not on develop your individual bot. Nevertheless the rules and tools described here can also help you with your bot development.
bashbot development is done on github. If you want to provide fixes or new features [fork bashbot on githup](https://help.github.com/en/articles/fork-a-repo) and provide changes as [pull request on github](https://help.github.com/en/articles/creating-a-pull-request).
### Debugging Bashbot
In normal mode of operation all bashbot output is discarded.
To get these messages (and more) you can start bashbot in the current shell ```./bashbot.sh startbot```. Now you can see all output or erros from bashbot.
In addition you can change the change the level of verbosity by adding a third argument after startbot.
```
"debug" redirects all output to "DEBUG.log", in addtion every update is logged in "MESSAGE.LOG" and "INLINE.log"
"debugterm" same as debug but output and errors are sent to terminal
"xdebug" same as debug plus set bash option '-x' to log any executed command
"xdebugterm" same as xdebug but output and errors are sent to terminal
```
### Modules and Addons
**Modules** live in ```modules/*.sh``` and are bashbot functions factored out in seperate files, gouped by functionality. Main reason for creating modules was
to keep 'bashbot.sh' small, while extending functionality. In addition not every functionality is needed by a bot, so you can
disable modules by removing them, e.g. rename the respective module files to 'module.sh.off'.
Modules must use onyl functions provided by 'bahsbot.sh' or the module itself, no depedencies to other modules or addons must exist.
If a module function is called from 'bashbot.sh', bashbot must work if the module is disabled, so it's madatory to use '_is_function'
or '_execute_if_function' if a module function is called.
**Addons** live in ```addons/*.sh.dist``` and are disabled by default. To activate an addon remove the '.dist' from filename, e.g. ```cp addons/example.sh.dist addons/example.sh```. Addons must register themself to BASHBOT_EVENTS at startup, e.g. to call a function everytime a message is recieved.
Registering to EVENTS is similar on how 'commands.sh' is ececuted, but more flexible and one major difference:
**Addons are executed in the context of the main script**, while 'commands.sh' is executed as a seperate process.
This is why event functions are time critical and must return as fast as possible. Spawn actions as a seperate process or function with '&', e.g.
send a message as respone from an addon: ```send_message "${CHAT[ID]}" "Message to send ..." &```.
#### Bashbot Events
Addons can register functions to bashbot events at startup by providing their name and a callback function.
If an event occours each registered function for the event is called.
Events run in the same context as the main bashbot loop, so variables set here are persistent as long bashbot is running.
Note: For the same reason event function MUST return imideatly! Time consuming tasks must be run in background or as a subshell, e.g. "long running &"
Availible events:
* BASHBOT_EVENT_INLINE an inline query is received
* BASHBOT_EVENT_MESSAGE any type of message is received
* BASHBOT_EVENT_TEXT a message containing text is received
* BASHBOT_EVENT_CMD a command is recieved (fist word starts with /)
* BASHBOT_EVENT_REPLYTO a reply to a message is received
* BASHBOT_EVENT_FORWARD a forwarded message is received
* BASHBOT_EVENT_CONTACT a contact is received
* BASHBOT_EVENT_LOCATION a location or a venue is received
* BASHBOT_EVENT_FILE a file is received
*usage*: BASHBOT_EVENT_xxx["uniqe-name"]="callback"
"unique-name" can be every alphanumeric string incl. '-' and '_'. Per convention it should be name of the addon followed by an internal identyfier.
*Example:* Register a function to echo to any Text send to the bot
```bash
# register callback:
BASHBOT_EVENT_TEXT["example_1"]="example_echo"
# function called if a text is recieved
example_echo() {
# all availible bashbot functions and variables can be used
send_normal_message "${CHAT[ID]}" "${MESSAGE[0]}" & # note the &!
}
```
* BAHSBOT_EVENT_TIMER is executed every minute and can be uses in variants: oneshot, every minute, every X minutes.
Registering to BASHBOT_EVENT_TIMER works a little different, you have to add a timing argument to the index name.
*usage: * BAHSBOT_EVENT_TIMER["name","time"], where time is:
* -x execute ONCE in x minutes
* 0 ignored
* 1 execute every minute
* x execute every x minutes
*Examples:*
```bash
# register callback:
BAHSBOT_EVENT_TIMER["example_every","1"]="example_everymin"
# function called every minute
example_everymin() {
# timer events has no chat id, so send to yourself
send_normal_message "$(< "${BOTADMIN})" "$(date)" & # note the &!
}
# register other callback:
BAHSBOT_EVENT_TIMER["example_10min","-10"]="example_in10min"
BAHSBOT_EVENT_TIMER["example_every5","5"]="example_every5min"
```
----
#### Create a stripped down Version of your Bot
Currently bashbot is more a bot development environment than a bot, containing examples, developer scripts, modules, documentation and more.
You don't need all these files after you're finished with your cool new bot.
Let's create a stripped down version:
- delete all modules you do not need from 'modules', e.g. 'modules/inline.sh' if you don't use inline queries
- delete not needed standard commands and messages from 'commands.sh'
- delete not needed commands and functions from 'mycommands.sh'
- run ```dev/make-standalone.sh``` to create a a stripped down version of your bo
Now have a look at the directory 'standalone', here you find the files 'bashbot.sh' and 'commands.sh' containing everything to run your bot.
[Download make-standalone.sh](https://github.com/topkecleon/telegram-bot-bash/blob/master/dev/make-standalone.sh) from github.
### Setup your develop environment
1. install git, install [shellcheck](5_practice.md#Test-your-Bot-with-shellcheck)
2. setup your [environment for UTF-8](4_expert.md#Setting-up-your-Environment)
3. clone your bashbot fork to a new directory ```git clone https://github.com/<YOURNAME>/telegram-bot-bash.git```, replace ```<YOURNAME>``` with your username on github
4. create and change to your develop branch ```git checkout -b <YOURBRANCH>```, replace ```<YOURBRANCH>``` with the name you want to name it, e.g. 'develop'
5. give your (dev) fork a new version tag: ```git tag vx.xx```(optional)
6. setup github hooks by running ```dev/install-hooks.sh``` (optional)
#### Test, Add, Push changes
A typical bashbot develop loop looks as follow:
1. start developing - *change, copy, edit bashbot files ...*
2. after changing a bash sript: ```shellcheck -x scipt.sh```
3. ```dev/all-tests.sh``` - *in case if errors back to 2.*
4. ```dev/git-add.sh``` - *check for changed files, update version string, run git add*
5. ```git commit -m "COMMIT MESSAGE"; git push```
**If you setup your dev environment with hooks and use the scripts above, versioning, addding and testing is done automatically.**
#### common commands
We state bashbot is a bash only bot, but this is not true. bashbot is a bash script using bash features PLUS external commands.
Usually bash is used in a unix/linux environment where many (GNU) commands are availible, but if commands are missing, bashbot may not work.
To avoid this and make bashbot working on as many platforms as possible - from embedded linux to mainframe - I recommed to restrict
ourself to the common commands provided by bash and coreutils/busybox/toybox.
See [Bash Builtins](https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html),
[coreutils](https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands),
[busybox](https://en.wikipedia.org/wiki/BusyBox#Commands) and [toybox](https://landley.net/toybox/help.html)
Availible commands in bash, coreutils, busybox and toybox. Do you find curl on the list?
```bash
.*, [*, [[*, basename, break, builtin*, bzcat, caller*, cat, cd*, chattr,
chgrp, chmod, chown, clear, command*, continue *, cp, cut, date, declare*,
dc, dd, df, diff, dirname, du, echo*, eval*, exec*, exit *, expr*, find,
fuser, getopt*, grep, hash*, head, hexdump, id, kill, killall, last, length,
less, let*, ln, local*, logname, ls, lsattr, lsmod, man, mapfile*, md5sum, mkdir,
mkfifo, mknod, more, mv, nice, nohup, passwd, patch, printf*, ps, pwd*, read*,
readarray*, readonly* return*, rm, rmdir, sed, seq, sha1sum, shift*, sleep,
source*, sort, split, stat, strings, su, sync, tail, tar, tee, test,
time, times*, timeout, touch, tr, trap*, true, umask*, usleep, uudecode,
uuencode, wc, wget, which, who, whoami, xargs, yes
```
commands marked with \* are bash builtins, all others are external programms. Calling an external programm is more expensive then using bulitins
or using an internal replacement. Here are some examples of internal replacement for external commands:
```bash
HOST="$(hostname)" -> HOST="$HOSTNAME"
seq 1 100 -> {0..100}
data="$(cat file)" -> data="$(<"file")"
DIR="$(dirname $0) -> DIR=""${0%/*}/""
IAM="($basename $0)" -> IAM="${0##*/}*
VAR="$(( 1 + 2 ))" -> (( var=1+2 ))
INDEX="$(( ${INDEX} + 1 ))" -> (( INDEX++ ))
```
For more examples see [Pure bash bible](https://github.com/dylanaraps/pure-bash-bible)
#### Prepare a new version
After some development it may time to create a new version for the users. a new version can be in sub version upgrade, e.g. for fixes and smaller additions or
a new release version for new features. To mark a new version use ```git tag NEWVERSION``` and run ```dev/version.sh``` to update all version strings.
Usually I start with pre versions and when everything looks good I push out a release candidate (rc) and finally the new version.
```
v0.x-devx -> v0.x-prex -> v0.x-rc -> v0.x ... 0.x+1-dev ...
```
If you release a new Version run ```dev/make-distribution.sh``` to create the zip and tar.gz archives in the dist directory and attach them to the github release. Do not forget to delete directory dist afterwards.
#### Versioning
Bashbot is tagged with version numbers. If you start a new development cycle you can tag your fork with a version higher than the current version.
E.g. if you fork 'v0.60' the next develop version should tagged as ```git tag "v0.61-dev"``` for fixes or ```git tag "v0.70-dev"``` for new features.
To get the current version name of your develepment fork run ```git describe --tags```. The output looks like ```v0.70-dev-6-g3fb7796``` where your version tag is followed by the number of commits since you tag your branch and followed by the latest commit hash. see also [comments in version.sh](../dev/version.sh)
To update the Version Number in files run ```dev/version.sh files```, it will update the line '#### $$VERSION$$ ###' in all files to the current version name.
To update version in all files run 'dev/version.sh' without parameter.
#### Shellcheck
For a shell script running as a service it's important to be paranoid about quoting, globbing and other common problems. So it's a must to run shellchek on all shell scripts before you commit a change. this is automated by a git hook activated in Setup step 6.
To run shellcheck for a single script run ```shellcheck -x script.sh```, to check all schripts run ```dev/hooks/pre-commit.sh```.
### bashbot tests
Starting with version 0.70 bashbot has a test suite. To start testsuite run ```dev/all-tests.sh```. all-tests.sh will return 'SUCCESS' only if all tests pass.
#### enabling / disabling tests
All tests are placed in the directory ```test```. To disable a test remove the execute flag from the '*-test.sh' script, to (re)enable a test make the script executable again.
#### creating new tests
To create a new test run ```test/ADD-test-new.sh``` and answer the questions, it will create the usually needed files and dirs:
Each test consists of a script script named after ```p-name-test.sh``` *(where p is test pass 'a-z' and name the name
of your test)* and an optional dir ```p-name-test/``` *(script name minus '.sh')* for additional files.
Tests with no dependency to other tests will run in pass 'a', tests which need an initialized bahsbot environment must run in pass 'd' or later.
A temporary test environment is created when 'ALL-tests.sh' starts and deleted after all tests are finished.
The file ```ALL-tests.inc.sh``` must be included from all tests and provide the test environment as shell variables:
```bash
# Test Evironment
TESTME="$(basename "$0")"
DIRME="$(pwd)"
TESTDIR="$1"
LOGFILE="${TESTDIR}/${TESTME}.log"
REFDIR="${TESTME%.sh}"
TESTNAME="${REFDIR//-/ }"
# common filenames
TOKENFILE="token"
ACLFILE="botacl"
COUNTFILE="count"
ADMINFILE="botadmin"
DATADIR="data-bot-bash"
# SUCCESS NOSUCCES -> echo "${SUCCESS}" or echo "${NOSUCCESS}"
SUCCESS=" OK"
NOSUCCESS=" FAILED!"
# default input, reference and output files
INPUTFILE="${DIRME}/${REFDIR}/${REFDIR}.input"
REFFILE="${DIRME}/${REFDIR}/${REFDIR}.result"
OUTPUTFILE="${TESTDIR}/${REFDIR}.out"
```
Example test
```bash
#!/usr/bin/env bash
# file: b-example-test.sh
# include common functions and definitions
# shellcheck source=test/ALL-tests.inc.sh
source "./ALL-tests.inc.sh"
if [ -f "${TESTDIR}/bashbot.sh" ]; then
echo "${SUCCESS} bashbot.sh exist!"
exit 0
else
echo "${NOSUCCESS} ${TESTDIR}/bashbot.sh missing!"
exit 1
fi
```
#### [Prev Function Reference](6_reference.md)
#### [Next Expert Use](8_custom.md)
#### $$VERSION$$ v0.90-dev2-19-g5779acc

View File

@ -0,0 +1,51 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - examples/README.html</title>
<style type="text/css">code{white-space: pre;}</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - examples/README.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="bashbot-examples">Bashbot examples</h2>
<h3 id="bashbot-multi">bashbot multi</h3>
<p>An example wrapper to run multiple instances of bashbot, use <code>./bashbot-multi.sh botname command</code></p>
<h3 id="bashbot.cron">bashbot.cron</h3>
<p>An example crontab is provided in <code>examples/bashbot.cron</code>, see <a href="../html/4_expert.html">Expert use</a></p>
<h3 id="interactive-chats">Interactive chats</h3>
<p>Two examples for interactive scripts are provided as <strong>calc.sh</strong> and <strong>question.sh</strong>, see <a href="../html/3_advanced.html">Advanced use</a></p>
<h3 id="background-scripts">Background scripts</h3>
<p>Background jobs are an easy way to provide sceduled messages or alerts if something happens. <strong>notify.sh</strong> is a simple example on how to send a message every x seonds, e.g. current time.</p>
<p><strong>background-scripts</strong> contains a more useful example on how to start and stop different scripts plus some example backgound scripts.</p>
<pre><code> mycommands.sh - /run_xxx and /kill-xxx wil start any script named run_xxx.sh
run_diskusage.sh - shows disk usage every 100 seconds
run_filename.sh - shown the name of new files in a named dir
run_filecontent.sh - shown the content of new files in a named dir
run_notify.sh - same as notify.sh</code></pre>
<p><strong>Note:</strong> Output of system commands often contains newlines, each newline results in a telegram message, the function send_telegram in mycommands.sh avoids this by converting each newline to mynewlinestartshere before output the string.</p>
<h3 id="system-status">System Status</h3>
<p><strong>send-system-status</strong> contains an example for commands showing status of different subsystems. This example is adapted from https://github.com/RG72/telegram-bot-bash to current bashbot commands, but not fully tested. This will show how easy you can convert existing bots.</p>
<pre><code> mycommands.sh - commands to show system status
botacl - controls who can show system status
*Availiable commands*:
/se *sensors*
/smb *smbstatus*
/free *memory status*
/md *raid status*
/lvm *lvm status*
/lvsd *Datailed lvm status*
/df *disk space*
/ifconfig *ifconfig output*
/smart *sda* _smart status for sda drive_</code></pre>
<h3 id="external-scripts">External scripts</h3>
<p><strong>external-use</strong> will contain some examples on how to send messages from external scripts to Telegram chats or users.</p>
<h4 id="version-v0.90-dev2-0-gec85636"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-0-gec85636</h4>
</body>
</html>

View File

@ -0,0 +1,60 @@
#### [Home](../README.md)
## Bashbot examples
### bashbot multi
An example wrapper to run multiple instances of bashbot, use ```./bashbot-multi.sh botname command```
### bashbot.cron
An example crontab is provided in ```examples/bashbot.cron```, see [Expert use](../doc/4_expert.md#Scedule-bashbot-from-Cron)
### Interactive chats
Two examples for interactive scripts are provided as **calc.sh** and **question.sh**, see [Advanced use](../doc/3_advanced.md#Interactive-Chats)
### Background scripts
Background jobs are an easy way to provide sceduled messages or alerts if something happens.
**notify.sh** is a simple example on how to send a message every x seonds, e.g. current time.
**background-scripts** contains a more useful example on how to start and stop different scripts plus some example backgound scripts.
```
mycommands.sh - /run_xxx and /kill-xxx wil start any script named run_xxx.sh
run_diskusage.sh - shows disk usage every 100 seconds
run_filename.sh - shown the name of new files in a named dir
run_filecontent.sh - shown the content of new files in a named dir
run_notify.sh - same as notify.sh
```
**Note:** Output of system commands often contains newlines, each newline results in a telegram message, the function 'send_telegram' in
mycommands.sh avoids this by converting each newline to ' mynewlinestartshere ' before output the string.
### System Status
**send-system-status** contains an example for commands showing status of different subsystems. This example is adapted from
https://github.com/RG72/telegram-bot-bash to current bashbot commands, but not fully tested. This will show how easy you can
convert existing bots.
```
mycommands.sh - commands to show system status
botacl - controls who can show system status
*Availiable commands*:
/se *sensors*
/smb *smbstatus*
/free *memory status*
/md *raid status*
/lvm *lvm status*
/lvsd *Datailed lvm status*
/df *disk space*
/ifconfig *ifconfig output*
/smart *sda* _smart status for sda drive_
```
### External scripts
**external-use** will contain some examples on how to send messages from external scripts to Telegram chats or users.
#### $$VERSION$$ v0.90-dev2-0-gec85636

View File

@ -0,0 +1,107 @@
#!/bin/bash
# files: mycommands.sh.dist
# copy to mycommands.sh and add all your commands an functions here ...
export res
# your additional bahsbot commands ...
mycommands() {
case "$MESSAGE" in
'/run_'*)
myback="run_${MESSAGE#*_}"
if [ -x "./${myback}.sh" ]; then
checkback "${myback}"
if [ "$res" -gt 0 ] ; then
send_normal_message "${CHAT[ID]}" "Start ${myback}, use /kill${myback} to stop it."
background "./${myback}.sh" "${myback}"
else
send_normal_message "${CHAT[ID]}" "Background job ${myback} already running."
fi
fi
;;
'/kill_'*)
myback="run_${MESSAGE#*_}"
if [ -x "./${myback}.sh" ]; then
checkback "${myback}"
if [ "$res" -eq 0 ] ; then
killback "${myback}"
send_normal_message "${CHAT[ID]}" "Stopping ${myback}, use /run_${myback} to start again."
else
send_normal_message "${CHAT[ID]}" "No background job ${myback}."
fi
fi
;;
esac
}
# place your additional processing functions here ...
# returns true if function exist
_is_function()
{
[ "$(LC_ALL=C type -t "$1")" = "function" ]
}
# inifnite loop for waching a given dir for new files
# $1 dir to wtach for new files
watch_dir_loop() {
local newfile old
[ ! -d "$1" ] && echo "ERROR: no directory $1 found!" >&2 && exit 1
# wait for new files in WATCHDIR
inotifywait -q -m "$1" -e create --format "%f" \
| while true
do
# read in newfile
read -r newfile
#skip if not match or same name as last time
[ "${newfile}" = "${old}" ] && continue
sleep 0.2
# process content and output message
echo "$(date): new file: ${newfile}" >>"$0.log"
# note: loop callback must a function in the calling script!
if _is_function loop_callback ; then
loop_callback "$1/$newfile"
else
echo "ERROR: loop_callback not found!" >&2
exit 1
fi
done
} # 2>>"$0.log"
output_telegram() {
# output to telegram
sed <<< "${1}" -e ':a;N;$!ba;s/\n/ mynewlinestartshere /g'
} # 2>>"$0.log"
# name and localtion of the tml file
# $1 string to output
# $2 file to add file to
output_html_file() {
local date
date="$(date)"
output_file "$(sed <<< "<div class=\"newdeal\">$1 <br>${date}</div>" '
s/ my[a-z]\{3,15}\(start\|ends\)here.*<br>/<br>/g
s/ *mynewlinestartshere */<br>/
s/\n/<br>/
')"
} # >>"$0.log" 2>&1
# $1 string to output
# $2 file to add file to
output_file() {
local publish="${2}"
[ ! -w "${publish}" ] && echo "ERROR: file ${publish} is not writeable or does not exist!" && exit
# output at beginnung of file, add date to message
sed <<< "${1}" '
s/ *mynewlinestartshere */\n/
s/ my[a-z]\{3,15}\(start\|ends\)here.*//g
' >"$publish$$"
cat "$publish" >>"$publish$$"
mv "${publish}$$" "${publish}"
} # >>"$0.log" 2>&1

View File

@ -0,0 +1,42 @@
#!/bin/bash
# file: run_diskcusage.sh
# example for an background job display a system value
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#### $$VERSION$$ v0.90-dev2-0-gec85636
# adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
unset IFS
# set -f # if you are paranoid use set -f to disable globbing
# discard STDIN for background jobs!
cat >/dev/null &
source "./mycommands.sh"
# check if $1 is a number
re='^[0-9]+$'
if [[ $1 =~ $re ]] ; then
SLEEP="$1"
else
SLEEP=100 # time between time notifications
fi
NEWLINE=$'\n'
# output disk usgae every $1 seconds
WAIT=0
while sleep $WAIT
do
output_telegram "Current Disk usage ${NEWLINE} $(df -h / /tmp /usr /var /home)"
# only for testing, delete echo line for production ...
echo "Current Disk usage ${NEWLINE} $(df -h / /tmp /usr /var /home)"
WAIT="$SLEEP"
done

View File

@ -0,0 +1,35 @@
#!/bin/bash
# file: run_filename
# background job to display content of all new files in WATCHDIR
#
#### $$VERSION$$ v0.90-dev2-0-gec85636
# adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
unset IFS
# set -f # if you are paranoid use set -f to disable globbing
# discard STDIN for background jobs!
cat >/dev/null &
# watch for new files created by a trusted programm
WATCHDIR="/my_trusted/dir_to_watch"
source "./mycommands.sh"
# test your script and the remove ...
WATCHDIR="/tmp/bottest"
NEWLINE='mynewlinestartshere'
# this is called by watch dir loop
# $1 is name of the new file
loop_callback() {
# output content of file, you must trust creator because content is sent as message!
output_telegram "Contents of ${1}: ${NEWLINE} $(cat "${1}")"
}
watch_dir_loop "$WATCHDIR"

View File

@ -0,0 +1,33 @@
#!/bin/bash
# file: run_filename
# background job to display all new files in WATCHDIR
#
#### $$VERSION$$ v0.90-dev2-0-gec85636
# adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
unset IFS
# set -f # if you are paranoid use set -f to disable globbing
# discard STDIN for background jobs!
cat >/dev/null &
# watch for new logfiles
WATCHDIR="/var/log"
source "./mycommands.sh"
# test your script and the remove ...
WATCHDIR="/tmp/bottest"
# this is called by watch dir loop
# $1 is name of the new file
loop_callback() {
# output one simple line ...
echo "New file ${1} created in ${WATCHDIR}!"
}
watch_dir_loop "$WATCHDIR"

View File

@ -0,0 +1,34 @@
#!/bin/bash
# file: notify.sh
# example for an background job, run with startback notify.sh
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#### $$VERSION$$ v0.90-dev2-0-gec85636
# adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
unset IFS
# set -f # if you are paranoid use set -f to disable globbing
# discard STDIN for background jobs!
cat >/dev/null &
# check if $1 is a number
re='^[0-9]+$'
if [[ $1 =~ $re ]] ; then
SLEEP="$1"
else
SLEEP=10 # time between time notifications
fi
# output current time every $1 seconds
while sleep $SLEEP
do
date "+* It's %k:%M:%S o' clock ..."
done

View File

@ -0,0 +1,44 @@
#!/bin/bash
# file. multibot.sh
# description: run multiple telegram bots from one installation
#
#### $$VERSION$$ v0.90-dev2-0-gec85636
if [ "${2}" = "" ] || [ "${2}" = "-h" ]; then
echo "Usage: $0 botname command"
exit 1
fi
BOT="${1}"
[ "${#BOT}" -lt 5 ] && echo "Botname must have a minumum lenth of 5 characters" && exit 1
# where should the bots live?
# true in one dir, false in seperate dirs
if true; then
# example for all in one bashbot dir
BINDIR="/usr/local/telegram-bot-bash"
ETC="${BINDIR}"
VAR="${BINDIR}"
else
# alternative linux like localtions
BINDIR="/usr/local/bin"
ETC="/etc/bahsbot"
VAR="/var/bahsbot"
export BASHBOT_JSONSH="/usr/local/bin/JSON.sh"
fi
# set final ENV
export BASHBOT_ETC="${ETC}/${BOT}"
export BASHBOT_VAR="${VAR}/${BOT}"
# some checks
[ ! -d "${BINDIR}" ] && echo "Dir ${BINDIR} does not exist" && exit 1
[ ! -d "${BASHBOT_ETC}" ] && echo "Dir ${BASHBOT_ETC} does not exist" && exit 1
[ ! -d "${BASHBOT_VAR}" ] && echo "Dir ${BASHBOT_VAR} does not exist" && exit 1
[ ! -x "${BINDIR}/bashbot.sh" ] && echo "${BINDIR}/bashbot.sh not executeable or does not exist" && exit 1
[ ! -r "${BASHBOT_ETC}/commands.sh" ] && echo "${BASHBOT_ETC}/commands.sh not readable or does not exist" && exit 1
[ ! -r "${BASHBOT_ETC}/mycommands.sh" ] && echo "${BASHBOT_ETC}/mycommands.sh not readable or does not exist" && exit 1
"${BINDIR}/bashbot.sh" "$2"

View File

@ -0,0 +1,36 @@
#
# this is an exmaple crontab file for telegram-bot-bash
# copy it to /etc/cron.d/bashbot
#
# (c) https://github.com/gnadelwartz
#
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#
#### $$VERSION$$ v0.90-dev2-0-gec85636
SHELL=/bin/sh
PATH=/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:
# place your mailadress here
MAILTO=root
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │ 7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * USER command to execute
# * * * * * root echo "run every minute!"
# run as www every day at 0:00
0 0 * * * nobody /usr/local/telegram-bot-bash/bashbot.sh start # (re)start bot
0 0 * * * nobody /usr/local/telegram-bot-bash/bashbot.sh resumeback # (re)start background jobs
# run as www on 24 of Dec, 12:00
0 12 24 12 * nobody /usr/local/telegram-bot-bash/bashbot.sh broadcast "X-Mas shopping is over!" # broadcast a message

View File

@ -0,0 +1,36 @@
#!/bin/bash
# file: calc.sh
# example for an interactive chat, run with startproc calc.sh
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#### $$VERSION$$ v0.90-dev2-0-gec85636
# adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
unset IFS
# set -f # if you are paranoid use set -f to disable globbing
echo 'Starting Calculator ...'
echo 'Enter first number.'
read -r A
echo 'Enter second number.'
read -r B
echo 'Select Operation: mykeyboardstartshere [ "Addition" , "Subtraction" , "Multiplication" , "Division" , "Cancel" ]'
read -r opt
echo -n 'Result: '
case $opt in
'add'* | 'Add'* ) res="$(( A + B ))" ;;
'sub'* | 'Sub'* ) res="$(( A - B ))" ;;
'mul'* | 'Mul'* ) res="$(( A * B ))" ;;
'div'* | 'Div'* ) res="$(( A / B ))" ;;
'can'* | 'Can'* ) res="abort!" ;;
* ) echo "unknown operator!";;
esac
echo "$res"
echo "Bye .."

View File

@ -0,0 +1,35 @@
#!/bin/bash
# file: notify.sh
# example for an background job, run with startback notify.sh
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#### $$VERSION$$ v0.90-dev2-0-gec85636
# adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
unset IFS
# set -f # if you are paranoid use set -f to disable globbing
# discard STDIN for background jobs!
cat >/dev/null &
# check if $1 is a number
re='^[0-9]+$'
if [[ $1 =~ $re ]] ; then
SLEEP="$1"
else
SLEEP=10 # time between time notifications
fi
# output current time every $1 seconds
date "+* It's %k:%M:%S o' clock ..."
while sleep $SLEEP
do
date "+* It's %k:%M:%S o' clock ..."
done

View File

@ -0,0 +1,33 @@
#!/bin/bash
# file: question.sh
# example for an interactive chat, run with startproc question.sh
# This file is public domain in the USA and all free countries.
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
#### $$VERSION$$ v0.90-dev2-0-gec85636
# adjust your language setting here
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
export 'LC_ALL=C.UTF-8'
export 'LANG=C.UTF-8'
export 'LANGUAGE=C.UTF-8'
unset IFS
# set -f # if you are paranoid use set -f to disable globbing
echo "Why hello there.
Would you like some tea (y/n)?"
read -r answer
[[ $answer =~ ^([yY][eE][sS]|[yY])$ ]] && echo "OK then, here you go: http://www.rivertea.com/blog/wp-content/uploads/2013/12/Green-Tea.jpg" || echo "OK then."
until [ "$SUCCESS" = "y" ] ;do
echo 'Do you like Music? mykeyboardstartshere "Yass!" , "No"'
read -r answer
case $answer in
'Yass!') echo "Goody! mykeyboardendshere";SUCCESS=y;;
'No') echo "Well that's weird. mykeyboardendshere";SUCCESS=y;;
'') echo "empty answer!" && exit;;
*) SUCCESS=n;;
esac
done
exit

View File

@ -0,0 +1,18 @@
# file: botacl
# a user not listed here, will return false from 'user_is_allowed'
#
#### $$VERSION$$ v0.90-dev2-0-gec85636
# Format:
# user:ressource:chat
# allow user 123456789 access to all resources in all chats
123456789:*:*
# allow user 12131415 to request systemstatus in all chats
12131415:systemstatus:*
# * are only allowed on the right hand side and not for user!
# the following exaples are NOT valid!
*:*:*
*:start:*
*:*:98979695

View File

@ -0,0 +1,75 @@
#!/bin/bash
# files: mycommands.sh
#
# this example is rendered after https://github.com/RG72/telegram-bot-bash
# 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$$ v0.90-dev2-0-gec85636
#
# shellcheck disable=SC2154
# shellcheck disable=SC2034
# uncomment the following lines to overwrite info and help messages
#'
# returned messages
bashbot_info='This bot allows you to request status of your system.
To begin using the bot, try with the /help command.
'
bashbot_help='*Availiable commands*:
/se *sensors*
/smb *smbstatus*
/free *memory status*
/md *raid status*
/lvm *lvm status*
/lvsd *Datailed lvm status*
/df *disk space*
/ifconfig *ifconfig output*
/smart *-d sda* _smart status for sda drive_
'
# your additional bahsbot commands
# NOTE: command can have @botname attached, you must add * in case tests...
mycommands() {
[[ "$MESSAGE" = '/'* ]] || return
set +f
# shellcheck disable=SC2206
local arg=( $MESSAGE )
set -f
local cmd="${arg[0]}"
local msg=""
if user_is_botadmin "${USER[ID]}" || user_is_allowed "${USER[ID]}" "systemstatus"; then
case "$cmd" in
'/md'*) msg="$(cat /proc/mdstat)";;
'/smb'*) msg="$(smbstatus)" ;;
'/se'*) msg="$(sensors | sed -r 's/\s|\)+//g' | sed -r 's/\(high=|\(min=/\//' | sed -r 's/\,crit=|\,max=/\//')";;
'/free'*) msg="$(free -h)";;
'/pvs'*) msg="$(pvs)";;
'/ifc'*) msg="$(ifconfig)";;
'/vgs'*) msg="$(vgs)";;
'/lvm'*) msg="$(lvs | sed -r 's/\s+/\n/g')";;
'/lvsd'*) msg="$(lvs -a -o +devices | sed -r 's/\s+/\n/g')";;
'/smart'*)
[ "${arg[0]}" == "" ] && msg="example \`/smart sda\`" && return
drive="$(echo "${arg[0]}" | cut -c 1-3)"
echo "smartctl -a /dev/$drive"
msg="$(smartctl -a "/dev/$drive")"
;;
'/df') msg="$(df -h | sed -r 's/^/\n/' | sed -r 's/\s+/\n/g')";;
esac
if [ "$msg" != "" ]; then
send_normal_message "${CHAT[ID]}" "$msg"
fi
else
send_normal_message "${USER[ID]}" "Sorry, you are not allowed to use this bot!"
fi
}
# place your processing functions here

View File

@ -0,0 +1,126 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - doc/0_install.html</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - doc/0_install.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="install-bashbot">Install bashbot</h2>
<ol style="list-style-type: decimal">
<li>Go to the directory you want to install bashbot, e.g.
<ul>
<li>your $HOME directory (install and run with your user-ID)</li>
<li>/usr/local if you want to run as service</li>
</ul></li>
<li><a href="https://github.com/topkecleon/telegram-bot-bash/releases">Download latest release zip from github</a> and extract all files.</li>
<li>Change into the directory <code>telegram-bot-bash</code></li>
<li>Acticate the bot example commands ``cp mycommands.sh.dist mycommands.sh```</li>
<li>Run <code>./bashbot.sh init</code> to setup the environment and enter your Bots token given by botfather.</li>
</ol>
<p>Edit mycommands.sh to your needs. Now your Bot is ready to start …</p>
<p><strong>If you are new to Bot development read <a href="https://core.telegram.org/bots">Bots: An introduction for developers</a></strong></p>
<h3 id="install-from-github">Install from Github</h3>
<p>As an alternative to download the zip files, you can clone the github repository to get the latest improvements/fixes.</p>
<ol style="list-style-type: decimal">
<li>Go to the directory you want to install bashbot, e.g.
<ul>
<li>your $HOME directory (install and run with your user-ID)</li>
<li>/usr/local if you want to run as service</li>
</ul></li>
<li>Run <code>git clone https://github.com/topkecleon/telegram-bot-bash.git</code></li>
<li>Change into the directory <code>telegram-bot-bash</code></li>
<li>Run <code>test/ALL-tests.sh</code> and if everthing finish OK …</li>
<li>Run <code>sudo ./bashbot.sh init</code> to setup the environment and enter your Bots token given by botfather.</li>
</ol>
<h3 id="update-bashbot">Update bashbot</h3>
<p><strong>Note: all files including mycommands.sh may overwritten, make a backup!</strong></p>
<ol style="list-style-type: decimal">
<li>Go to the directory where you had installed bashbot, e.g.
<ul>
<li>your $HOME directory</li>
<li>/usr/local</li>
</ul></li>
<li><a href="https://github.com/topkecleon/telegram-bot-bash/releases">Download latest release zip from github</a></li>
<li>Stop all running instances of bashbot</li>
<li>Extract all files to your existing bashbot dir</li>
<li>Run <code>sudo ./bashbot.sh init</code> to setup your environment after the update</li>
</ol>
<p>If you modified commands.sh move your changes to mycommands.sh, this avoids overwrrite of you changes on updates.</p>
<p>Now you can restart your bashbot instances.</p>
<h3 id="notes-on-updates">Notes on Updates</h3>
<h4 id="removal-of-tmux">removal of TMUX</h4>
<p>From version 0.80 on TMUX is no longer needed and the bachsbot command attach is deleted. Old function inproc is replaced by send_interactive. send_interactive does checks if an interactive job is running internaly. Pls check if you make use of inproc and remove it including the old checks, e.g.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">if</span> <span class="ex">tmux</span> ls <span class="kw">|</span> <span class="fu">grep</span> -v send <span class="kw">|</span> <span class="fu">grep</span> -q <span class="st">&quot;</span><span class="va">$copname</span><span class="st">&quot;</span><span class="kw">;</span> <span class="kw">then</span> <span class="ex">inproc</span><span class="kw">;</span> <span class="kw">fi</span>
<span class="co"># or</span>
<span class="bu">[</span> checkprog<span class="bu"> ]</span> <span class="kw">&amp;&amp;</span> <span class="ex">inproc</span></code></pre></div>
<p>must be replaced by <code>send_interactive &quot;${CHATD[ID]}&quot; &quot;${MESSAGE}&quot;</code></p>
<h3 id="do-not-edit-commands.sh">Do not edit commands.sh</h3>
<p>From version 0.60 on your commands must be placed in mycommands.sh. If you update from a version with your commands in commands.sh move all your commands and functions to mycommands.sh.</p>
<p>From version 0.80 on commands.sh will be overwritten on update!</p>
<h4 id="location-of-var-tmp-data-dirs">Location of var / tmp / data dirs</h4>
<p>From version 0.70 on the tmp dir is renamed to data-bot-bash to reflect the fact that not only temporary files are stored. an existing tmp-bot-bash will be automatically renamed after update.</p>
<p>From version 0.50 on the temporary files are no more placed in /tmp. instead a dedicated tmp dir is used.</p>
<h4 id="changes-to-send_keyboard-in-v0.6">Changes to send_keyboard in v0.6</h4>
<p>From Version 0.60 on keybord format for <code>send_keyboard</code> and <code>send_message &quot;mykeyboardstartshere ...&quot;</code> was changed. Keybords are now defined in JSON Array notation e.g. “[ \“yes\” , \“no\” ]”. This has the advantage that you can create any type of keyboard supported by Telegram. The old format is supported for backward compatibility, but may fail for corner cases.</p>
<p><em>Example Keyboards</em>:</p>
<ul>
<li>yes no in two rows:
<ul>
<li>OLD format: yes no <em>(two strings)</em></li>
<li>NEW format: [ “yes” ] , [ “no” ] <em>(two arrays with a string)</em></li>
</ul></li>
<li>new layouts made easy with NEW format:
<ul>
<li>Yes No in one row: [ “yes” , “no” ]</li>
<li>Yes No plus Maybe in 2.row: [ “yes” , “no” ] , [ “maybe” ]</li>
<li>numpad style keyboard: [ “1” , “2” , “3” ] , [ “4” , “5” , “6” ] , [ “7” , “8” , “9” ] , [ “0” ]</li>
</ul></li>
</ul>
<h4 id="next-create-bot"><a href="1_firstbot.html">Next Create Bot</a></h4>
<h4 id="version-v0.90-dev2-0-gec85636"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-0-gec85636</h4>
</body>
</html>

View File

@ -0,0 +1,53 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - doc/1_firstbot.html</title>
<style type="text/css">code{white-space: pre;}</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - doc/1_firstbot.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="create-a-telegram-bot-with-botfather">Create a Telegram Bot with botfather</h2>
<p><strong><a href="https://core.telegram.org/bots#3-how-do-i-create-a-bot">BotFather is the one bot to rule them all</a>. It will help you create new bots and change settings for existing ones.</strong> <a href="https://core.telegram.org/bots#generating-an-authorization-token">Commands known by Botfather</a></p>
<h3 id="creating-a-new-bot">Creating a new Bot</h3>
<ol style="list-style-type: decimal">
<li>Message <span class="citation">@botfather</span> https://telegram.me/botfather with the following text: <code>/newbot</code> If you dont know how to message by username, click the search field on your Telegram app and type <code>@botfather</code>, you should be able to initiate a conversation. Be careful not to send it to the wrong contact, because some users has similar usernames to <code>botfather</code>.</li>
</ol>
<div class="figure">
<img src="http://i.imgur.com/aI26ixR.png" alt="botfather initial conversation" />
<p class="caption">botfather initial conversation</p>
</div>
<ol start="2" style="list-style-type: decimal">
<li><p><span class="citation">@botfather</span> replies with <code>Alright, a new bot. How are we going to call it? Please choose a name for your bot.</code></p></li>
<li><p>Type whatever name you want for your bot.</p></li>
<li><p><span class="citation">@botfather</span> replies with <code>Good. Now let's choose a username for your bot. It must end in bot. Like this, for example: TetrisBot or tetris_bot.</code></p></li>
<li><p>Type whatever username you want for your bot, minimum 5 characters, and must end with <code>bot</code>. For example: <code>telesample_bot</code></p></li>
<li><p><span class="citation">@botfather</span> replies with:</p>
<p>Done! Congratulations on your new bot. You will find it at telegram.me/telesample_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands.</p>
<p>Use this token to access the HTTP API: <b>123456789:AAG90e14-0f8-40183D-18491dDE</b></p>
<p>For a description of the Bot API, see this page: https://core.telegram.org/bots/api</p></li>
<li><p>Note down the token mentioned above.</p></li>
<li><p>Type <code>/setprivacy</code> to <span class="citation">@botfather</span>.</p></li>
</ol>
<div class="figure">
<img src="http://i.imgur.com/tWDVvh4.png" alt="botfather later conversation" />
<p class="caption">botfather later conversation</p>
</div>
<ol start="9" style="list-style-type: decimal">
<li><p><span class="citation">@botfather</span> replies with <code>Choose a bot to change group messages settings.</code></p></li>
<li><p>Type <code>@telesample_bot</code> (change to the username you set at step 5 above, but start it with <code>@</code>)</p></li>
<li><p><span class="citation">@botfather</span> replies with</p>
<p>Enable - your bot will only receive messages that either start with the / symbol or mention the bot by username. Disable - your bot will receive all messages that people send to groups. Current status is: ENABLED</p></li>
<li><p>Type <code>Disable</code> to let your bot receive all messages sent to a group. This step is up to you actually.</p></li>
<li><p><span class="citation">@botfather</span> replies with <code>Success! The new status is: DISABLED. /help</code></p></li>
</ol>
<h4 id="prev-installation"><a href="0_install.html">Prev Installation</a></h4>
<h4 id="next-getting-started"><a href="2_usage.html">Next Getting started</a></h4>
<h4 id="version-v0.90-dev2-0-gec85636"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-0-gec85636</h4>
</body>
</html>

View File

@ -0,0 +1,227 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - doc/2_usage.html</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - doc/2_usage.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="gettting-started">Gettting Started</h2>
<p>The Bots standard commands are in the commands dispatcher <code>commands.sh</code>, Do not edit this file! Add your commands and functions to <code>mycommands.sh</code>. In mycommands.sh.dist you find examples how to add own commands and overwrite existing ones. See <a href="5_practice.html">Best practices</a> for more information.</p>
<p>Once youre done with editing start the Bot with <code>./bashbot.sh start</code>. To stop the Bot run <code>./bashbot.sh kill</code></p>
<p>If something doesnt work as expected, debug with <code>./bashbot.sh startbot DEBUG</code>, where DEBUG can be debug, xdebug or xdebugx. See <a href="7_develop.html">Bashbot Development</a> for more information.</p>
<p>To use the functions provided in this script in other scripts simply source bashbot: <code>source bashbot.sh source</code>. see <a href="8_expert.html">Expert Use</a></p>
<p>Have FUN!</p>
<hr />
<h3 id="files">Files</h3>
<pre><code>.
├── bashbot.sh # main bashbot script - do not edit
├── commands.sh # command dispatcher - do not edit
├── mycommands.sh # place your functions and commands here!
├── JSON.sh # bashbots JSON parser, see https://github.com/dominictarr/JSON.sh
├── modules # optional functions, sourced by commands.sh
│   ├── aliases.sh # to disable modules rename them xxx.sh.off
│   ├── answerInline.sh
│   ├── jsonDB.sh
│   ├── background.sh
│   ├── chatMember.sh
│   └── sendMessage.sh # main send message functions, do not disable
├── addons # optional addons, disbaled by default
│   ├── example.sh # to enable addons change their XXX_ENABLE to true
│   └── xxxxxage.sh
├── bashbot.rc # start/stop script if you run basbot as service
├── examples # example scripts and configs for bashbot
│   └── bashbot.cron # example crontab
├── doc # Documentation and License
├── html
├── LICENSE
├── README.html
├── README.md
└── README.txt
</code></pre>
<hr />
<h2 id="managing-your-bot">Managing your Bot</h2>
<h4 id="note-running-bashbot-as-root-is-highly-danger-and-not-recommended.-see-expert-use.">Note: running bashbot as root is highly danger and not recommended. See Expert use.</h4>
<h3 id="start-stop">Start / Stop</h3>
<p>Start or Stop your Bot use the following commands:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">./bashbot.sh</span> start</code></pre></div>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">./bashbot.sh</span> kill</code></pre></div>
<h3 id="user-count">User count</h3>
<p>To count the total number of users that ever used the bot run the following command:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">./bashbot.sh</span> count</code></pre></div>
<h3 id="sending-broadcasts-to-all-users">Sending broadcasts to all users</h3>
<p>To send a broadcast to all of users that ever used the bot run the following command:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">./bashbot.sh</span> broadcast <span class="st">&quot;Hey! I just wanted to let you know that the bot&#39;s been updated!&quot;</span></code></pre></div>
<hr />
<h2 id="recieve-data">Recieve data</h2>
<p>Evertime a Message is recieved, you can read incoming data using the following variables:</p>
<h3 id="regular-messages">Regular Messages</h3>
<ul>
<li><code>${MESSAGE}</code>: Current message</li>
<li><code>${MESSAGE[ID]}</code>: ID of current message</li>
<li><code>$CAPTION</code>: Captions</li>
<li><code>$REPLYTO</code>: Original message wich was replied to</li>
<li><code>$USER</code>: This array contains the First name, last name, username and user id of the sender of the current message.
<ul>
<li><code>${USER[ID]}</code>: User id</li>
<li><code>${USER[FIRST_NAME]}</code>: Users first name</li>
<li><code>${USER[LAST_NAME]}</code>: Users last name</li>
<li><code>${USER[USERNAME]}</code>: Username</li>
</ul></li>
<li><code>$CHAT</code>: This array contains the First name, last name, username, title and user id of the chat of the current message.
<ul>
<li><code>${CHAT[ID]}</code>: Chat id</li>
<li><code>${CHAT[FIRST_NAME]}</code>: Chats first name</li>
<li><code>${CHAT[LAST_NAME]}</code>: Chats last name</li>
<li><code>${CHAT[USERNAME]}</code>: Username</li>
<li><code>${CHAT[TITLE]}</code>: Title</li>
<li><code>${CHAT[TYPE]}</code>: Type</li>
<li><code>${CHAT[ALL_MEMBERS_ARE_ADMINISTRATORS]}</code>: All members are administrators (true if true)</li>
</ul></li>
<li><code>$REPLYTO</code>: This array contains the First name, last name, username and user id of the ORIGINAL sender of the message REPLIED to.
<ul>
<li><code>${REPLYTO[ID]}</code>: ID of message wich was replied to</li>
<li><code>${REPLYTO[UID]}</code>: Original users id</li>
<li><code>${REPLYTO[FIRST_NAME]}</code>: Original users first name</li>
<li><code>${REPLYTO[LAST_NAME]}</code>: Original users last name</li>
<li><code>${REPLYTO[USERNAME]}</code>: Original users username</li>
</ul></li>
<li><code>$FORWARD</code>: This array contains the First name, last name, username and user id of the ORIGINAL sender of the FORWARDED message.
<ul>
<li><code>${FORWARD[ID]}</code>: Same as MESSAGE[ID] if message is forwarded</li>
<li><code>${FORWARD[UID]}</code>: Original users id</li>
<li><code>${FORWARD[FIRST_NAME]}</code>: Original users first name</li>
<li><code>${FORWARD[LAST_NAME]}</code>: Original users last name</li>
<li><code>${FORWARD[USERNAME]}</code>: Original users username</li>
</ul></li>
<li><code>$URLS</code>: This array contains documents, audio files, voice recordings and stickers as URL.
<ul>
<li><code>${URLS[AUDIO]}</code>: Audio files</li>
<li><code>${URLS[VIDEO]}</code>: Videos</li>
<li><code>${URLS[PHOTO]}</code>: Photos (maximum quality)</li>
<li><code>${URLS[VOICE]}</code>: Voice recordings</li>
<li><code>${URLS[STICKER]}</code>: Stickers</li>
<li><code>${URLS[DOCUMENT]}</code>: Any other file</li>
</ul></li>
<li><code>$CONTACT</code>: This array contains info about contacts sent in a chat.
<ul>
<li><code>${CONTACT[ID]}</code>: User id</li>
<li><code>${CONTACT[NUMBER]}</code>: Phone number</li>
<li><code>${CONTACT[FIRST_NAME]}</code>: First name</li>
<li><code>${CONTACT[LAST_NAME]}</code>: Last name</li>
<li><code>${CONTACT[VCARD]}</code>: Users complete Vcard</li>
</ul></li>
<li><code>$LOCATION</code>: This array contains info about locations sent in a chat.
<ul>
<li><code>${LOCATION[LONGITUDE]}</code>: Longitude</li>
<li><code>${LOCATION[LATITUDE]}</code>: Latitude</li>
</ul></li>
<li><code>$VENUE</code>: This array contains info about venue (a place) sent in a chat.
<ul>
<li><code>${VENUE[TITLE]}</code>: Name of the place</li>
<li><code>${VENUE[ADDRESS]}</code>: Address of the place</li>
<li><code>${VENUE[LONGITUDE]}</code>: Longitude</li>
<li><code>${VENUE[LATITUDE]}</code>: Latitude</li>
<li><code>${VENUE[FOURSQUARE]}</code>: Fouresquare ID</li>
</ul></li>
</ul>
<h3 id="inline-queries">Inline queries</h3>
<p>Evertime a Message is recieved, you can read incoming data using the following variables:</p>
<ul>
<li><code>${iQUERY}</code>: Current inline query</li>
<li><code>$iQUERY</code>: This array contains the ID, First name, last name, username and user id of the sender of the current inline query.
<ul>
<li><code>${iQUERY[ID]}</code>: Inline query ID</li>
<li><code>${iQUERY[USER_ID]}</code>: Users id</li>
<li><code>${iQUERY[FIRST_NAME]}</code>: Users first name</li>
<li><code>${iQUERY[LAST_NAME]}</code>: Users last name</li>
</ul></li>
</ul>
<h2 id="usage-of-bashbot-functions">Usage of bashbot functions</h2>
<h4 id="sending-messages">sending messages</h4>
<p>To send messages use the <code>send_xxx_message</code> functions.</p>
<p>To send regular text without any markdown use:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_text_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;lol&quot;</span></code></pre></div>
<p>To send text with markdown:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;lol *bold*&quot;</span></code></pre></div>
<p>To send text with html:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_html_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;lol &lt;b&gt;bold&lt;/b&gt;&quot;</span></code></pre></div>
<p>To forward messages use the <code>forward</code> function:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">forward</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;from_chat_id&quot;</span> <span class="st">&quot;message_id&quot;</span></code></pre></div>
<p>If your Bot is Admin in a Chat you can delete every message, if not you can delete only your messages. To delete a message with a known <span class="math inline">${MESSAGE[ID]} you can simple use: ```bash delete_message &quot;$</span>{CHAT[ID]}&quot; “${MESSAGE[ID]}” ```</p>
<h4 id="send_message">send_message</h4>
<p>In addition there is a universal send_massage function which can output any type of message. This function is used to process output from external scrips like interactive chats or background jobs.<br />
<strong>For safety and performance reasons I recommend to use send_xxxx_message functions above for sending messages</strong></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;lol&quot;</span></code></pre></div>
<p>To send html or markdown put the following strings before the text, depending on the parsing mode you want to enable:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;markdown_parse_mode lol *bold*&quot;</span></code></pre></div>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;html_parse_mode lol &lt;b&gt;bold&lt;/b&gt;&quot;</span></code></pre></div>
<p>This function also allows a third parameter that disables additional function parsing (for safety use this when reprinting user input):</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;lol&quot;</span> <span class="st">&quot;safe&quot;</span></code></pre></div>
<p><strong>See also <a href="3_advanced.html">Interactive chats</a></strong></p>
<h4 id="send-files-locations-keyboards.">Send files, locations, keyboards.</h4>
<p>To send images, videos, voice files, photos etc. use the <code>send_photo</code> function (remember to change the safety Regex @ line 14 of command.sh to allow sending files only from certain directories):</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_file</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;/home/user/doge.jpg&quot;</span> <span class="st">&quot;Lool&quot;</span></code></pre></div>
<p>To send custom keyboards use the <code>send_keyboard</code> function:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_keyboard</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Text that will appear in chat?&quot;</span> <span class="st">&#39;[ &quot;Yep&quot; , &quot;No&quot; ]&#39;</span> <span class="co"># note the simgle quotes!</span>
<span class="ex">send_keyboard</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Text that will appear in chat?&quot;</span> <span class="st">&quot;[ </span><span class="dt">\\</span><span class="st">&quot;</span>Yep<span class="dt">\\</span><span class="st">&quot; , </span><span class="dt">\\</span><span class="st">&quot;</span>No<span class="dt">\\</span><span class="st">&quot; ]&quot;</span> <span class="co"># within double quotes you must excape the inside double quots</span></code></pre></div>
<p>To send locations use the <code>send_location</code> function:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_location</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Latitude&quot;</span> <span class="st">&quot;Longitude&quot;</span></code></pre></div>
<p>To send venues use the <code>send_venue</code> function:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_venue</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Latitude&quot;</span> <span class="st">&quot;Longitude&quot;</span> <span class="st">&quot;Title&quot;</span> <span class="st">&quot;Address&quot;</span> <span class="st">&quot;optional foursquare id&quot;</span></code></pre></div>
<p>To send a chat action use the <code>send_action</code> 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.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_action</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;action&quot;</span></code></pre></div>
<p><strong>See also <a href="6_reference.html">Bashbot function reference</a></strong></p>
<h4 id="prev-create-bot"><a href="1_firstbot.html">Prev Create Bot</a></h4>
<h4 id="next-advanced-usage"><a href="3_advanced.html">Next Advanced Usage</a></h4>
<h4 id="version-v0.90-dev2-0-gec85636"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-0-gec85636</h4>
</body>
</html>

View File

@ -0,0 +1,164 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - doc/3_advanced.html</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - doc/3_advanced.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="advanced-features">Advanced Features</h2>
<h3 id="access-control">Access control</h3>
<p>Bashbot offers functions to check what Telegram capabilities like chat admin or chat creator the given user has:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># return true if user is admin/owner of the bot</span>
<span class="co"># -&gt; botadmin is stored in file &#39;./botadmin&#39;</span>
<span class="ex">user_is_botadmin</span> <span class="st">&quot;user&quot;</span>
<span class="co"># return true if user is creator or admin of a chat</span>
<span class="ex">user_is_admin</span> <span class="st">&quot;chat&quot;</span> <span class="st">&quot;user&quot;</span>
<span class="co"># return true if user is creator of a chat or it&#39;s a one to one chat</span>
<span class="ex">user_is_creator</span> <span class="st">&quot;chat&quot;</span> <span class="st">&quot;user&quot;</span>
<span class="co"># examples:</span>
<span class="ex">user_is_botadmin</span> <span class="st">&quot;</span><span class="va">${USER[ID]}</span><span class="st">&quot;</span> <span class="kw">&amp;&amp;</span> <span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;You are *BOTADMIN*.&quot;</span>
<span class="ex">user_is_admin</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">${USER[ID]}</span><span class="st">&quot;</span> <span class="kw">&amp;&amp;</span> <span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;You are *CHATADMIN*.&quot;</span></code></pre></div>
<p>In addition you can check individual capabilities of users as you must define in the file <code>./botacl</code>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># file: botacl</span>
<span class="co"># a user not listed here, will return false from &#39;user_is_allowed&#39;</span>
<span class="co">#</span>
<span class="co"># Format:</span>
<span class="co"># user:ressource:chat</span>
<span class="co"># allow user 123456789 access to all resources in all chats</span>
<span class="ex">123456789</span>:*:*
<span class="co"># allow user 12131415 to start bot in all chats</span>
<span class="ex">12131415</span>:start:*
<span class="co"># allow user 987654321 only to start bot in chat 98979695</span>
<span class="ex">987654321</span>:start:98979695
<span class="co"># * are only allowed on the right hand side and not for user!</span>
<span class="co"># the following exaples are NOT valid!</span>
<span class="ex">*</span>:*:*
<span class="ex">*</span>:start:*
<span class="ex">*</span>:*:98979695</code></pre></div>
<p>You must use the function <code>user_is_allowed</code> to check if a user has the capability to do something. Example: Check if user has capability to start bot.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="kw">case</span> <span class="st">&quot;</span><span class="va">$MESSAGE</span><span class="st">&quot;</span><span class="kw"> in</span>
<span class="co">################################################</span>
<span class="co"># GLOBAL commands start here, only edit messages</span>
<span class="st">&#39;/start&#39;</span>*<span class="kw">)</span>
<span class="ex">user_is_botadmin</span> <span class="st">&quot;</span><span class="va">${USER[ID]}</span><span class="st">&quot;</span> <span class="kw">&amp;&amp;</span> <span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;You are *BOTADMIN*.&quot;</span>
<span class="kw">if</span> <span class="ex">user_is_allowed</span> <span class="st">&quot;</span><span class="va">${USER[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;start&quot;</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="kw">;</span> <span class="kw">then</span>
<span class="ex">bot_help</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span>
<span class="kw">else</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;You are not allowed to start Bot.&quot;</span>
<span class="kw">;;</span>
<span class="kw">esac</span></code></pre></div>
<p><strong>See also <a href="6_reference.html">Bashbot User Access Control functions</a></strong></p>
<h3 id="interactive-chats">Interactive Chats</h3>
<p>To create interactive chats, write <em>(or edit the exmaples/question.sh script)</em> a bash <em>(or C or python)</em> script, make it executable and then use the startproc function to start the script. The output of the script will be sent to the user and user input will be sent to the script. To stop the script use the function killprog</p>
<p>The output of the script will be processed by send_messages to enable you to not only send text, but also keyboards, files, locations and more. Each newline in the output will start an new message to the user, to have line breaks in your message you can use mynewlinestartshere.</p>
<p>To open up a keyboard in an interactive script, print out the keyboard layout in the following way:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">echo</span> <span class="st">&quot;Text that will appear in chat? mykeyboardstartshere [ </span><span class="dt">\&quot;</span><span class="st">Yep, sure</span><span class="dt">\&quot;</span><span class="st"> , </span><span class="dt">\&quot;</span><span class="st">No, highly unlikely</span><span class="dt">\&quot;</span><span class="st"> ]&quot;</span></code></pre></div>
<p>Same goes for files:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">echo</span> <span class="st">&quot;Text that will appear in chat? myfilelocationstartshere /home/user/doge.jpg&quot;</span></code></pre></div>
<p>And buttons:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">echo</span> <span class="st">&quot;Text that will appear in chat. mybtextstartshere Klick me myburlstartshere https://dealz.rrr.de&quot;</span></code></pre></div>
<p>And locations:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">echo</span> <span class="st">&quot;Text that will appear in chat. mylatstartshere 45 mylongstartshere 45&quot;</span></code></pre></div>
<p>And venues:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">echo</span> <span class="st">&quot;Text that will appear in chat. mylatstartshere 45 mylongstartshere 45 mytitlestartshere my home myaddressstartshere Diagon Alley N. 37&quot;</span></code></pre></div>
<p>You can combine them:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">echo</span> <span class="st">&quot;Text that will appear in chat? mykeyboardstartshere [ </span><span class="dt">\&quot;</span><span class="st">Yep, sure</span><span class="dt">\&quot;</span><span class="st"> , </span><span class="dt">\&quot;</span><span class="st">No, highly unlikely</span><span class="dt">\&quot;</span><span class="st"> ] myfilelocationstartshere /home/user/doge.jpg mylatstartshere 45 mylongstartshere 45&quot;</span></code></pre></div>
<p>Please note that you can either send a location or a venue, not both. To send a venue add the mytitlestartshere and the myaddressstartshere keywords.</p>
<p>New in v0.6: To insert a linebreak in your message you can insert <code>mynewlinestartshere</code> in your echo command:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">echo</span> <span class="st">&quot;Text that will appear in one message mynewlinestartshere with this text on a new line&quot;</span></code></pre></div>
<p>New in v0.7: In case you must extend a message already containing a location, a file, a keyboard etc., with additionial text simply add <code>mytextstartshere additional text</code> at the end of the string:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="va">out=</span><span class="st">&quot;Text that will appear mylatstartshere 45 mylongstartshere 45&quot;</span>
<span class="kw">[[</span> <span class="st">&quot;</span><span class="va">$out</span><span class="st">&quot;</span> <span class="ot">!=</span> *<span class="st">&#39;in chat&#39;</span>*<span class="kw"> ]]</span> <span class="kw">&amp;&amp;</span> <span class="va">out=</span><span class="st">&quot;</span><span class="va">$out</span><span class="st"> mytextstartshere in chat.&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$out</span><span class="st">&quot;</span></code></pre></div>
<p>Note: Interactive Chats run independent from main bot and continue running until your script exits or you /cancel if from your Bot.</p>
<h3 id="background-jobs">Background Jobs</h3>
<p>A background job is similar to an interactive chat, but runs in the background and does only output massages and does not get user input. In contrast to interactive chats its possible to run multiple background jobs. To create a background job write a script or edit examples/notify.sh script and use the funtion <code>background</code> to start it:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">background</span> <span class="st">&quot;examples/notify.sh&quot;</span> <span class="st">&quot;jobname&quot;</span></code></pre></div>
<p>All output of the script will be sent to the user, to stop a background job use:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">killback</span> <span class="st">&quot;jobname&quot;</span></code></pre></div>
<p>You can also suspend and resume the last running background jobs from outside bashbot, e.g. in your startup schripts:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">./bashbot.sh</span> suspendback
<span class="ex">./bashbot.sh</span> resumeback</code></pre></div>
<p>If you want to kill all background jobs permantly run:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">./bashbot.sh</span> killback</code></pre></div>
<p>Note: Background Jobs run independent from main bot and continue running until your script exits or you stop if from your Bot. Backgound Jobs will continue running if your Bot is stopeda and must be terminated, e.g. by <code>bashbot.sh killback</code></p>
<h3 id="inline-queries">Inline queries</h3>
<p><strong>Inline queries</strong> allow users to send commands to your bot from every chat without going to a private chat. An inline query is started if the user type the bots name, e.g. <span class="citation">@myBot</span>. Everything after <span class="citation">@myBot</span> is immediatly send to the bot.</p>
<p>In order to enable <strong>inline mode</strong>, send <code>/setinline</code> command to <span class="citation">[@BotFather]</span>(https://telegram.me/botfather) and provide the placeholder text that the user will see in the input field after typing your bots name.</p>
<p>The following commands allows you to send ansers to <em>inline queries</em>. To enable bashbot to process inline queries set <code>INLINE=&quot;1&quot;</code> in mycommands.sh.</p>
<p>To send messsages or links through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;article&quot;</span> <span class="st">&quot;Title of the result&quot;</span> <span class="st">&quot;Content of the message to be sent&quot;</span></code></pre></div>
<p>To send photos in jpeg format and less than 5MB, from a website through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;photo&quot;</span> <span class="st">&quot;A valid URL of the photo&quot;</span> <span class="st">&quot;URL of the thumbnail&quot;</span></code></pre></div>
<p>To send standard gifs from a website (less than 1MB) through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;gif&quot;</span> <span class="st">&quot;gif url&quot;</span></code></pre></div>
<p>To send mpeg4 gifs from a website (less than 1MB) through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;mpeg4_gif&quot;</span> <span class="st">&quot;mpeg4 gif url&quot;</span></code></pre></div>
<p>To send videos from a website through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;video&quot;</span> <span class="st">&quot;valid video url&quot;</span> <span class="st">&quot;Select one mime type: text/html or video/mp4&quot;</span> <span class="st">&quot;URL of the thumbnail&quot;</span> <span class="st">&quot;Title for the result&quot;</span></code></pre></div>
<p>To send photos stored in Telegram servers through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;cached_photo&quot;</span> <span class="st">&quot;identifier for the photo&quot;</span></code></pre></div>
<p>To send gifs stored in Telegram servers through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;cached_gif&quot;</span> <span class="st">&quot;identifier for the gif&quot;</span></code></pre></div>
<p>To send mpeg4 gifs stored in Telegram servers through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;cached_mpeg4_gif&quot;</span> <span class="st">&quot;identifier for the gif&quot;</span></code></pre></div>
<p>To send stickers through an <em>inline query</em>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">answer_inline_query</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;cached_sticker&quot;</span> <span class="st">&quot;identifier for the sticker&quot;</span></code></pre></div>
<p>See also <a href="6_reference.html">mycommands.sh</a> for more information.</p>
<h4 id="prev-getting-started"><a href="2_usage.html">Prev Getting started</a></h4>
<h4 id="next-expert-use"><a href="4_expert.html">Next Expert Use</a></h4>
<h4 id="version-v0.90-dev2-0-gec85636"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-0-gec85636</h4>
</body>
</html>

View File

@ -0,0 +1,289 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - doc/4_expert.html</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - doc/4_expert.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="expert-use">Expert Use</h2>
<h3 id="handling-utf-8-character-sets">Handling UTF-8 character sets</h3>
<p>UTF-8 is a variable length encoding of Unicode. UTF-8 is recommended as the default encoding in JSON, XML and HTML, also Telegram make use of it.</p>
<p>The first 128 characters are regular ASCII, so its a superset of and compatible with ASCII environments. The next 1,920 characters need two bytes for encoding and covers almost all <code>Latin</code> alphabets, also <code>Greek</code>, <code>Cyrillic</code>, <code>Hebrew</code>, <code>Arabic</code> and more. See <a href="https://en.wikipedia.org/wiki/UTF-8">Wikipedia</a> for more details.</p>
<h4 id="setting-up-your-environment">Setting up your Environment</h4>
<p>In general <code>bash</code> and <code>GNU</code> utitities are UTF-8 aware if you to setup your environment and your scripts accordingly:</p>
<ol style="list-style-type: decimal">
<li><p>Your Terminal and Editor must support UTF-8: Set Terminal and Editor locale to UTF-8, eg. in <code>Settings/Configuration</code> select UTF-8 (Unicode) as Charset.</p></li>
<li><p>Set <code>Shell</code> environment to UTF-8 in your <code>.profile</code> and your scripts. The usual settings are:</p></li>
</ol>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">export</span> <span class="st">&#39;LC_ALL=C.UTF-8&#39;</span>
<span class="bu">export</span> <span class="st">&#39;LANG=C.UTF-8&#39;</span>
<span class="bu">export</span> <span class="st">&#39;LANGUAGE=C.UTF-8&#39;</span></code></pre></div>
<p>If you use other languages, eg. german or US english, change the shell settings to:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">export</span> <span class="st">&#39;LC_ALL=de_DE.UTF-8&#39;</span>
<span class="bu">export</span> <span class="st">&#39;LANG=de_DE.UTF-8&#39;</span>
<span class="bu">export</span> <span class="st">&#39;LANGUAGE=de_DE.UTF-8&#39;</span></code></pre></div>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="bu">export</span> <span class="st">&#39;LC_ALL=en_US.UTF-8&#39;</span>
<span class="bu">export</span> <span class="st">&#39;LANG=de_en_US.UTF-8&#39;</span>
<span class="bu">export</span> <span class="st">&#39;LANGUAGE=den_US.UTF-8&#39;</span></code></pre></div>
<ol start="3" style="list-style-type: decimal">
<li>make shure your bot scripts use the correct settings, eg. include the lines above at the beginning of your scripts</li>
</ol>
<p>To display all availible locales on your system run <code>locale -a | more</code>. <a href="https://wiki.gentoo.org/wiki/UTF-8">Gentoo Wiki</a></p>
<h4 id="bashbot-utf-8-support">Bashbot UTF-8 Support</h4>
<p>Bashbot handles all messages transparently, regardless of the charset in use. The only exception is when converting from JSON data to strings.</p>
<p>Telegram use JSON to send / recieve data. JSON encodes strings as follow: Characters not ASCII <em>(&gt;127)</em> are escaped as sequences of <code>\uxxxx</code> to be regular ASCII. In addition multibyte characters, <em>e.g. Emoticons or Arabic characters</em>, are send in double byte UTF-16 notation. The Emoticons <code>😁 😘 ❤️ 😊 👍</code> are encoded as: <code>\uD83D\uDE01 \uD83D\uDE18 \u2764\uFE0F \uD83D\uDE0A \uD83D\uDC4D</code></p>
<p><strong>This “mixed” JSON encoding needs special handling and can not decoded from</strong> <code>echo -e</code> or <code>printf '%s\\n'</code></p>
<p>Most complete support for decoding of multibyte characters can only be provided if python is installed on your system. <strong>Without phyton bashbot falls back to an internal, pure bash implementation which may not work for some corner cases</strong>.</p>
<h3 id="run-as-other-user-or-system-service">Run as other user or system service</h3>
<p>Bashbot is desingned to run manually by the user who installed it. Nevertheless its possible to run it by an other user-ID, as a system service or sceduled from cron. This is onyl recommended for experiend linux users.</p>
<p>Setup the environment for the user you want to run bashbot and enter desired username, e.g. nobody :</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="fu">sudo</span> ./bashbot.sh init</code></pre></div>
<p>Edit the file <code>bashbot.rc</code> and edit the following lines to fit your configuration:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co">#######################</span>
<span class="co"># Configuration Section</span>
<span class="co"># edit the next line to fit the user you want to run bashbot, e.g. nobody:</span>
<span class="va">runas=</span><span class="st">&quot;nobody&quot;</span>
<span class="co"># uncomment one of the following lines </span>
<span class="co"># runcmd=&quot;su $runas -s /bin/bash -c &quot; # runasuser with su</span>
<span class="co"># runcmd=&quot;runuser $runas -s /bin/bash -c &quot; # runasuser with runuser</span>
<span class="co"># edit the values of the following lines to fit your config:</span>
<span class="va">start=</span><span class="st">&quot;/usr/local/telegram-bot-bash/bashbot.sh&quot;</span> <span class="co"># location of your bashbot.sh script</span>
<span class="va">name=</span><span class="st">&#39;&#39;</span> # <span class="ex">your</span> bot name as given to botfather, e.g. mysomething_bot
<span class="co"># </span><span class="re">END</span><span class="co"> Configuration</span>
<span class="co">#######################</span></code></pre></div>
<p>From now on use bashbot.rc to manage your bot:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="fu">sudo</span> ./bashbot.rc start</code></pre></div>
<p>Type <code>ps -ef | grep bashbot</code> to verify your Bot is running as the desired user.</p>
<p>If your Bot is started by bashbot.rc, you must use bashbot.rc also to manage your Bot! The following commands are availible:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="fu">sudo</span> ./bashbot.rc start
<span class="fu">sudo</span> ./bashbot.rc stop
<span class="fu">sudo</span> ./bashbot.rc status
<span class="fu">sudo</span> ./bashbot.rc suspendback
<span class="fu">sudo</span> ./bashbot.rc resumeback
<span class="fu">sudo</span> ./bashbot.rc killback</code></pre></div>
<p>To change back the environment to your user-ID run <code>sudo ./bashbot.sh init</code> again and enter your user name.</p>
<p>To use bashbot as a system servive include a working <code>bashbot.rc</code> in your init system (systemd, /etc/init.d).</p>
<h3 id="scedule-bashbot-from-cron">Scedule bashbot from Cron</h3>
<p>An example crontab is provided in <code>examples/bashbot.cron</code>.</p>
<ul>
<li>If you are running bashbot with your user-ID, copy the examples lines to your crontab and remove username <code>nobody</code>.</li>
<li>if you run bashbot as an other user or a system service edit <code>examples/bashbot.cron</code> to fit your needs and replace username<code>nobody</code> with the username you want to run bashbot. copy the modified file to <code>/etc/cron.d/bashbot</code></li>
</ul>
<h3 id="use-bashbot-from-cli-and-scripts">Use bashbot from CLI and scripts</h3>
<p>You can use bashbot to send <em>messages</em>, <em>locations</em>, <em>venues</em>, <em>pictures</em> etc. from command line and scripts by sourcing it:</p>
<p><em>usage:</em> . bashbot.sh source</p>
<p>Before sourcing bahsbot.sh for interactive and script use, you should export and set BASHBOT_HOME to bashbots installation dir, e.g. /usr/local/telegram-bot-bash. see <a href="#Bashbot-environment">Bashbot Environemt</a></p>
<p><strong>Note:</strong> <em>If you dont set BASHBOT_HOME bashbot will use the actual directory as NEW home directory which means it will create all needed files and ask for bot token and botadmin if you are not in the real bot home!</em></p>
<p><em>Examples:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># if you are in the bashbot directory</span>
<span class="bu">.</span> <span class="ex">bashbot.sh</span> source
<span class="co"># same, but more readable in scripts</span>
<span class="bu">source</span> ./bashbot.sh source
<span class="co"># use bashbot config in BASHBOT_HOME from any directory</span>
<span class="bu">export</span> <span class="va">BASHBOT_HOME=</span>/usr/local/telegram-bot-bash
<span class="bu">source</span> <span class="va">${BASHBOT_HOME}</span>/bashbot.sh source
<span class="co"># use / create new config in current directory</span>
<span class="bu">unset</span> <span class="va">BASHBOT_HOME</span>
<span class="bu">source</span> /path/to/bashbot.sh source</code></pre></div>
<h4 id="environment-variable-exported-from-bashbot">Environment variable exported from bashbot</h4>
<p>If you have sourced bashbot.sh you have the following bashot internal variables availible:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">COMMANDS</span> # default: ./commands.sh<span class="st">&quot;</span>
<span class="st">MODULEDIR # default: ./modules&quot;</span>
<span class="ex">TOKENFILE</span> # default: ./token<span class="st">&quot;</span>
<span class="st">BOTADMIN # default: ./botadmin&quot;</span>
<span class="ex">BOTACL</span> # default: ./botacl<span class="st">&quot;</span>
<span class="st">TMPDIR # default: ./data-bot-bash&quot;</span>
<span class="ex">COUNTFILE</span> # default: ./count<span class="st">&quot;</span>
<span class="st">BOTTOKEN # default: content of </span><span class="va">${TOKENFILE}</span>
<span class="st">URL # telegram api URL - default: https://api.telegram.org/bot</span><span class="va">${BOTTOKEN}</span><span class="st">&quot;</span></code></pre></div>
<h4 id="interacctive-use">Interacctive use</h4>
<p>For testing your setup or sending messages yoursel you can use bashbot functions from bash command line:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># are we running bash?</span>
<span class="bu">echo</span> <span class="va">$SHELL</span>
<span class="ex">/bin/bash</span>
<span class="co"># source bashbot.sh WITHOUT BASHBOT_HOME set</span>
<span class="ex">./bashbot.sh</span> source
<span class="co"># output bashbot internal variables</span>
<span class="bu">echo</span> <span class="va">$COMMANDS</span> <span class="va">$MODULEDIR</span> <span class="va">$TOKENFILE</span> <span class="va">$BOTADMIN</span> <span class="va">$BOTACL</span> <span class="va">$TMPDIR</span> <span class="va">$COUNTFILE</span>
<span class="ex">./commands.sh</span> ./modules ./token ./botadmin ./botacl ./data-bot-bash ./count
<span class="co"># source bashbot.sh WITH BASHBOT_HOME set</span>
<span class="bu">export</span> <span class="va">BASHBOT_HOME=</span>/usr/local/telegram-bot-bash
<span class="bu">source</span> ./bashbot.sh source
<span class="co"># output bashbot internal variables</span>
<span class="bu">echo</span> <span class="va">$COMMANDS</span> <span class="va">$MODULEDIR</span> <span class="va">$TOKENFILE</span> <span class="va">$BOTADMIN</span> <span class="va">$BOTACL</span> <span class="va">$TMPDIR</span> <span class="va">$COUNTFILE</span>
<span class="ex">/usr/local/telegram-bot-bash/commands.sh</span> /usr/local/telegram-bot-bash/modules /usr/local/telegram-bot-bash/token
<span class="ex">/usr/local/telegram-bot-bash/botadmin</span> /usr/local/telegram-bot-bash/botacl /usr/local/telegram-bot-bash/data-bot-bash
<span class="ex">/usr/local/telegram-bot-bash/count</span></code></pre></div>
<p>After sourcing you can use bashbot functions to send Messages, Locations, Pictures etc. to any Telegram User or Chat you are in. See <a href="2_usage.html">Send Messages</a>.</p>
<p><em>Examples:</em> You can test this by sending messages to yourself:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># fist Hello World</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="va">$BOTADMIN</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&quot;Hello World! This is my first message&quot;</span>
<span class="co"># now with some markdown and HTML</span>
<span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="va">$BOTADMIN</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&#39;*Hello World!* _This is my first markdown message_&#39;</span>
<span class="ex">send_html_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="va">$BOTADMIN</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&#39;&lt;b&gt;Hello World!&lt;/b&gt; &lt;em&gt;This is my first HTML message&lt;/em&gt;&#39;</span>
<span class="ex">send_keyboard</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="va">$BOTADMIN</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&#39;Do you like it?&#39;</span> <span class="st">&#39;[ &quot;Yep&quot; , &quot;No&quot; ]&#39;</span></code></pre></div>
<p>Now something more useful …</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># sending output from system commands:</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="va">$BOTADMIN</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">&quot;</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="va">$BOTADMIN</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$(</span><span class="fu">uptime</span><span class="va">)</span><span class="st">&quot;</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="va">$BOTADMIN</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&#39;`&#39;</span><span class="va">$(</span><span class="fu">free</span><span class="va">)</span><span class="st">&#39;`&#39;</span>
<span class="co"># same but markdown style &#39;code&#39; (monospaced)</span>
<span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="va">$BOTADMIN</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="dt">\`</span><span class="va">$(</span><span class="fu">free</span><span class="va">)</span><span class="dt">\`</span><span class="st">&quot;</span></code></pre></div>
<h3 id="bashbot-environment">Bashbot environment</h3>
<p>This section describe how you can customize bashbot to your needs by setting environment variables.</p>
<h4 id="change-file-locations">Change file locations</h4>
<p>In standard setup bashbot is self containing, this means you can place telegram-bot-bash any location and run it from there. All files - programm, config, data etc - will reside in telegram-bot-bash.</p>
<p>If you want to have other locations for config, data etc, define and export the following environment variables. <strong>Note: all specified directories and files must exist or running bashbot.sh will fail.</strong></p>
<h5 id="bashbot_etc">BASHBOT_ETC</h5>
<p>Location of the files <code>commands.sh</code>, <code>mycommands.sh</code>, <code>token</code>, <code>botadmin</code>, <code>botacl</code></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="bu">unset</span> <span class="va">BASHBOT_ETC</span> <span class="co"># keep in telegram-bot-bash (default)</span>
<span class="bu">export</span> <span class="va">BASHBOT_ETC</span> <span class="st">&quot;&quot;</span> <span class="co"># keep in telegram-bot-bash</span>
<span class="bu">export</span> <span class="va">BASHBOT_ETC</span> <span class="st">&quot;/etc/bashbot&quot;</span> <span class="co"># unix like config location</span>
<span class="bu">export</span> <span class="va">BASHBOT_ETC</span> <span class="st">&quot;/etc/bashbot/bot1&quot;</span> <span class="co"># multibot configuration bot 1</span>
<span class="bu">export</span> <span class="va">BASHBOT_ETC</span> <span class="st">&quot;/etc/bashbot/bot2&quot;</span> <span class="co"># multibot configuration bot 2</span></code></pre></div>
<p>e.g. /etc/bashbot</p>
<h5 id="bashbot_var">BASHBOT_VAR</h5>
<p>Location of runtime data <code>data-bot-bash</code>, <code>count</code></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="bu">unset</span> <span class="va">BASHBOT_VAR</span> <span class="co"># keep in telegram-bot-bash (default)</span>
<span class="bu">export</span> <span class="va">BASHBOT_VAR</span> <span class="st">&quot;&quot;</span> <span class="co"># keep in telegram-bot-bash</span>
<span class="bu">export</span> <span class="va">BASHBOT_VAR</span> <span class="st">&quot;/var/spool/bashbot&quot;</span> <span class="co"># unix like config location</span>
<span class="bu">export</span> <span class="va">BASHBOT_VAR</span> <span class="st">&quot;/var/spool/bashbot/bot1&quot;</span> <span class="co"># multibot configuration bot 1</span>
<span class="bu">export</span> <span class="va">BASHBOT_VAR</span> <span class="st">&quot;/var/spool/bashbot/bot2&quot;</span> <span class="co"># multibot configuration bot 2</span></code></pre></div>
<h5 id="bashbot_jsonsh">BASHBOT_JSONSH</h5>
<p>Full path to JSON.sh script, default: ./JSON.sh/JSON.sh, must end with /JSON.sh.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="bu">unset</span> <span class="va">BASHBOT_JSONSH</span> <span class="co"># telegram-bot-bash/JSON.sh/JSON.sh (default)</span>
<span class="bu">export</span> <span class="va">BASHBOT_JSONSH</span> <span class="st">&quot;&quot;</span> <span class="co"># telegram-bot-bash/JSON.sh/JSON.sh</span>
<span class="bu">export</span> <span class="va">BASHBOT_JSONSH</span> <span class="st">&quot;/usr/local/bin/JSON.sh&quot;</span> <span class="co"># installed in /usr/local/bin</span></code></pre></div>
<h5 id="bashbot_home">BASHBOT_HOME</h5>
<p>Set bashbot home directory, where bashot will look for additional files. If BASHBOT_ETC, BASHBOT_VAR or BASHBOT_JSONSH are set the have precedence over BASHBOT_HOME.</p>
<p>This is also usefull if you want to force bashbot to always use full pathnames instead of relative ones.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="bu">unset</span> <span class="va">BASHBOT_HOME</span> <span class="co"># autodetection (default)</span>
<span class="bu">export</span> <span class="va">BASHBOT_HOME</span> <span class="st">&quot;&quot;</span> <span class="co"># autodetection</span>
<span class="bu">export</span> <span class="va">BASHBOT_HOME</span> <span class="st">&quot;/usr/local/telegram-bot-bash&quot;</span> <span class="co"># unix like location</span>
<span class="bu">export</span> <span class="va">BASHBOT_HOME</span> <span class="st">&quot;/usr/local/bin&quot;</span> <span class="co"># Note: you MUST set ETC, VAR and JSONSH to other locations to make this work!</span></code></pre></div>
<hr />
<h4 id="change-config-values">Change config values</h4>
<h5 id="bashbot_url">BASHBOT_URL</h5>
<p>Uses given URL instead of offical telegram API URL, useful if you have your own telegram server or for testing.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="bu">unset</span> <span class="va">BASHBOT_URL</span> <span class="co"># use Telegram URL https://api.telegram.org/bot&lt;token&gt; (default)</span>
<span class="bu">export</span> <span class="va">BASHBOT_URL</span> <span class="st">&quot;&quot;</span> <span class="co"># use use Telegram https://api.telegram.org/bot&lt;token&gt;</span>
<span class="bu">export</span> <span class="va">BASHBOT_URL</span> <span class="st">&quot;https://my.url.com/bot&quot;</span> <span class="co"># use your URL https://my.url.com/bot&lt;token&gt;</span></code></pre></div>
<h5 id="bashbot_token">BASHBOT_TOKEN</h5>
<h5 id="bashbot_wget">BASHBOT_WGET</h5>
<p>Bashbot uses <code>curl</code> to communicate with telegram server. if <code>curl</code> is not availible <code>wget</code> is used. If BASHBOT_WGET is set to any value (not undefined or not empty) wget is used even is curl is availible.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="bu">unset</span> <span class="va">BASHBOT_WGET</span> <span class="co"># use curl (default)</span>
<span class="bu">export</span> <span class="va">BASHBOT_WGET</span> <span class="st">&quot;&quot;</span> <span class="co"># use curl </span>
<span class="bu">export</span> <span class="va">BASHBOT_WGET</span> <span class="st">&quot;yes&quot;</span> <span class="co"># use wget</span>
<span class="bu">export</span> <span class="va">BASHBOT_WGET</span> <span class="st">&quot;no&quot;</span> <span class="co"># use wget!</span></code></pre></div>
<h5 id="bashbot_sleep">BASHBOT_SLEEP</h5>
<p>Instead of polling permanently or with a fixed delay, bashbot offers a simple adaptive polling. If messages are recieved bashbot polls with no dealy. If no messages are availible bashbot add 100ms delay for every poll until the maximum of BASHBOT_SLEEP ms.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="bu">unset</span> <span class="va">BASHBOT_SLEEP</span> <span class="co"># 5000ms (default)</span>
<span class="bu">export</span> <span class="va">BASHBOT_SLEEP</span> <span class="st">&quot;&quot;</span> <span class="co"># 5000ms </span>
<span class="bu">export</span> <span class="va">BASHBOT_SLEEP</span> <span class="st">&quot;1000&quot;</span> <span class="co"># 1s maximum sleep </span>
<span class="bu">export</span> <span class="va">BASHBOT_SLEEP</span> <span class="st">&quot;10000&quot;</span> <span class="co"># 10s maximum sleep</span>
<span class="bu">export</span> <span class="va">BASHBOT_SLEEP</span> <span class="st">&quot;1&quot;</span> <span class="co"># values &lt; 1000 disables sleep (not recommended) </span>
</code></pre></div>
<h4 id="testet-configs-as-of-v0.90-release">Testet configs as of v0.90 release</h4>
<p><strong>Note: Environment variables are not stored, you must setup them before every call to bashbot.sh, e.g. from a script.</strong></p>
<h5 id="simple-unix-like-config-for-one-bot.-bashbot-is-installed-in-usrlocaltelegram-bot-bash">simple Unix like config, for one bot. bashbot is installed in /usr/local/telegram-bot-bash</h5>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="co"># Note: all dirs and files must exist!</span>
<span class="bu">export</span> <span class="va">BASHBOT_ETC</span> <span class="st">&quot;/etc/bashbot&quot;</span>
<span class="bu">export</span> <span class="va">BASHBOT_VAR</span> <span class="st">&quot;/var/spool/bashbot&quot;</span>
<span class="ex">/usr/local/telegram-bot-bash/bashbot.sh</span> start</code></pre></div>
<h5 id="unix-like-config-for-one-bot.-bashbot.sh-is-installed-in-usrbin">Unix like config for one bot. bashbot.sh is installed in /usr/bin</h5>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="co"># Note: all dirs and files must exist!</span>
<span class="bu">export</span> <span class="va">BASHBOT_ETC</span> <span class="st">&quot;/etc/bashbot&quot;</span>
<span class="bu">export</span> <span class="va">BASHBOT_VAR</span> <span class="st">&quot;/var/spool/bashbot&quot;</span>
<span class="bu">export</span> <span class="va">BASHBOT_JSONSH</span> <span class="st">&quot;/var/spool/bashbot&quot;</span>
<span class="ex">/usr/local/bin/bashbot.sh</span> start</code></pre></div>
<h5 id="simple-multibot-config-everything-is-keept-inside-telegram-bot-bash-dir">simple multibot config, everything is keept inside telegram-bot-bash dir</h5>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="co"># config for running Bot 1</span>
<span class="co"># Note: all dirs and files must exist!</span>
<span class="bu">export</span> <span class="va">BASHBOT_ETC</span> <span class="st">&quot;./mybot1&quot;</span>
<span class="bu">export</span> <span class="va">BASHBOT_VAR</span> <span class="st">&quot;./mybot1&quot;</span>
<span class="ex">/usr/local/telegram-bot-bash/bashbot.sh</span> start</code></pre></div>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="co"># config for running Bot 2</span>
<span class="co"># Note: all dirs and files must exist!</span>
<span class="bu">export</span> <span class="va">BASHBOT_ETC</span> <span class="st">&quot;./mybot2&quot;</span>
<span class="bu">export</span> <span class="va">BASHBOT_VAR</span> <span class="st">&quot;./mybot2&quot;</span>
<span class="ex">/usr/local/telegram-bot-bash/bashbot.sh</span> start</code></pre></div>
<h4 id="prev-advanced-use"><a href="3_advanced.html">Prev Advanced Use</a></h4>
<h4 id="next-best-practice"><a href="5_practice.html">Next Best Practice</a></h4>
<h4 id="version-v0.90-dev2-19-g5779acc"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-19-g5779acc</h4>
</body>
</html>

View File

@ -0,0 +1,175 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - doc/5_practice.html</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - doc/5_practice.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="best-practices">Best Practices</h2>
<h3 id="new-to-bot-development">New to bot development?</h3>
<p>If you are new to Bot development read <a href="https://core.telegram.org/bots">Bots: An introduction for developers</a> and consult <a href="https://core.telegram.org/bots/api/">Telegram Bot API Documentation</a>.</p>
<p>In addition you should know about <a href="https://core.telegram.org/bots#3-how-do-i-create-a-bot">BotFather, the one bot to rule them all</a>. It will help you create new bots and change settings for existing ones. <a href="https://core.telegram.org/bots#generating-an-authorization-token">Commands known by Botfather</a></p>
<p>If you dontt have a github account, it may time to <a href="https://github.com/pricing">sepup a free account now</a></p>
<h3 id="add-commands-to-mycommands.sh-only">Add commands to mycommands.sh only</h3>
<p>To ease updates never change <code>bashbot.sh</code>, instead your commands and functions must go to <code>mycommands.sh</code> . Insert your Bot commands in the <code>case ... esac</code> block of the mycommands() function:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># file: mycommands.sh</span>
<span class="co"># your additional bahsbot commands</span>
<span class="co"># uncomment the following lines to overwrite info and help messages</span>
<span class="va">bashbot_info=</span><span class="st">&#39;This is *MY* variant of _bashbot_, the Telegram bot written entirely in bash.</span>
<span class="st">&#39;</span>
<span class="va">bashbot_help=</span><span class="st">&#39;*Available commands*:</span>
<span class="st">/echo message - _echo the given messsage_</span>
<span class="st">&#39;</span>
<span class="co"># </span><span class="al">NOTE</span><span class="co">: command can have @botname attached, you must add * in case tests... </span>
<span class="fu">mycommands()</span> <span class="kw">{</span>
<span class="kw">case</span> <span class="st">&quot;</span><span class="va">$MESSAGE</span><span class="st">&quot;</span><span class="kw"> in</span>
<span class="st">&#39;/echo&#39;</span>*<span class="kw">)</span> <span class="co"># example echo command</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$MESSAGE</span><span class="st">&quot;</span>
<span class="kw">;;</span>
<span class="co"># .....</span>
<span class="kw">esac</span>
<span class="kw">}</span></code></pre></div>
<h3 id="overwrite-extend-and-disable-global-commands">Overwrite, extend and disable global commands</h3>
<p>You can overwrite a global bashbot command by placing the same commands in <code>mycommands.sh</code> and add <code>return 1</code> ad the end of your command, see /kickme below.</p>
<p>To disable a global bashbot command place create a command simply containing return 1, see /leave below.</p>
<p>In case you want to add some processing to the global bashbot command add <code>return 0</code>, then both command will be executed.</p>
<p><strong>Learn more about <a href="https://core.telegram.org/bots#commands">Bot commands</a>.</strong></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># file: commands.sh</span>
<span class="kw">case</span> <span class="st">&quot;</span><span class="va">$MESSAGE</span><span class="st">&quot;</span><span class="kw"> in</span>
<span class="co">##########</span>
<span class="co"># command overwrite examples</span>
<span class="st">&#39;info&#39;</span>*<span class="kw">)</span> <span class="co"># output date in front of regular info</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">&quot;</span>
<span class="bu">return</span> 0
<span class="kw">;;</span>
<span class="st">&#39;/kickme&#39;</span>*<span class="kw">)</span> <span class="co"># this will replace the /kickme command</span>
<span class="ex">send_markdown_mesage</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;*This bot will not kick you!*&quot;</span>
<span class="bu">return</span> 1
<span class="kw">;;</span>
<span class="st">&#39;/leave&#39;</span>*<span class="kw">)</span> <span class="co"># disable all commands starting with leave</span>
<span class="bu">return</span> 1
<span class="kw">;;</span>
<span class="kw">esac</span></code></pre></div>
<h3 id="seperate-logic-from-commands">Seperate logic from commands</h3>
<p>If a command need more than 2-3 lines of code, you should use a function to seperate logic from command. Place your functions in <code>mycommands.sh</code> and call the from your command. Example:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># file: mycommands.sh</span>
<span class="co"># your additional bahsbot commands</span>
<span class="fu">mycommands()</span> <span class="kw">{</span>
<span class="kw">case</span> <span class="st">&quot;</span><span class="va">$MESSAGE</span><span class="st">&quot;</span><span class="kw"> in</span>
<span class="st">&#39;/process&#39;</span>*<span class="kw">)</span> <span class="co"># logic for /process is done in process_message </span>
<span class="va">result=</span><span class="st">&quot;</span><span class="va">$(</span><span class="ex">process_message</span> <span class="st">&quot;</span><span class="va">$MESSAGE</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$result</span><span class="st">&quot;</span>
<span class="kw">;;</span>
<span class="kw">esac</span>
<span class="kw">}</span>
<span class="co"># place your functions here</span>
<span class="fu">process_message()</span> <span class="kw">{</span>
<span class="bu">local</span> <span class="va">ARGS=</span><span class="st">&quot;</span><span class="va">${1#</span>/* <span class="va">}</span><span class="st">&quot;</span> <span class="co"># remove command </span>
<span class="bu">local</span> <span class="va">TEXT</span> <span class="va">OUTPUT=</span><span class="st">&quot;&quot;</span>
<span class="co"># process every word in MESSAGE, avoid globbing</span>
<span class="kw">set</span> <span class="ex">-f</span>
<span class="kw">for</span> <span class="ex">WORD</span> in <span class="va">$ARGS</span>
<span class="kw">do</span>
<span class="co"># process links </span>
<span class="kw">if [[</span> <span class="st">&quot;</span><span class="va">$WORD</span><span class="st">&quot;</span> <span class="ot">==</span> <span class="st">&quot;https://&quot;</span>*<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="va">REPORT=</span><span class="st">&quot;</span><span class="va">$(</span><span class="ex">dosomething_with_link</span> <span class="st">&quot;</span><span class="va">$WORD</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span>
<span class="co"># no link, add as text</span>
<span class="kw">else</span>
<span class="va">TEXT=</span><span class="st">&quot;</span><span class="va">$(</span><span class="bu">echo</span> <span class="st">&quot;</span><span class="va">${TEXT}</span><span class="st"> </span><span class="va">$WORD</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span>
<span class="bu">continue</span>
<span class="kw">fi</span>
<span class="co"># compose result</span>
<span class="va">OUTPUT=</span><span class="st">&quot;* </span><span class="va">${REPORT}</span><span class="st"> </span><span class="va">${WORD}</span><span class="st"> </span><span class="va">${TEXT}</span><span class="st">&quot;</span>
<span class="va">TEXT=</span><span class="st">&quot;&quot;</span>
<span class="kw">done</span>
<span class="co"># return result, reset globbing in case we had no ARGS</span>
<span class="bu">echo</span> <span class="st">&quot;</span><span class="va">${OUTPUT}${TEXT}</span><span class="st">&quot;</span>
<span class="kw">}</span></code></pre></div>
<h3 id="test-your-bot-with-shellcheck">Test your Bot with shellcheck</h3>
<p>Shellcheck is a static linter for shell scripts providing excellent tips and hints for shell coding pittfalls. You can <a href="https://www.shellcheck.net/">use it online</a> or <a href="https://github.com/koalaman/shellcheck#installing">install it on your system</a>. All bashbot scripts are linted by shellcheck.</p>
<p>Shellcheck examples:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">$ <span class="ex">shellcheck</span> -x mybotcommands.inc.sh
<span class="ex">Line</span> 17:
<span class="va">TEXT=</span><span class="st">&quot;</span><span class="va">$(</span><span class="bu">echo</span> <span class="st">&quot;</span><span class="va">${TEXT}</span><span class="st"> </span><span class="va">$WORD</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span>
^<span class="ex">--</span> SC2116: Useless echo? Instead of <span class="st">&#39;cmd $(echo foo)&#39;</span>, just use <span class="st">&#39;cmd foo&#39;</span>.
</code></pre></div>
<p>As you can see my <code>mybotcommands.inc.sh</code> contains an useless echo command in TEXT= assigment and can be replaced by <code>TEXT=&quot;${TEXT}${WORD}&quot;</code></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">$ <span class="ex">shellcheck</span> -x examples/notify
<span class="ex">OK</span>
$ <span class="ex">shellcheck</span> -x examples/question
<span class="ex">OK</span>
$ <span class="ex">shellcheck</span> -x commands.sh
<span class="ex">OK</span>
$ <span class="ex">shellcheck</span> -x bashbot.sh
<span class="ex">In</span> bashbot.sh line 123:
<span class="va">text=</span><span class="st">&quot;</span><span class="va">$(</span><span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$text</span><span class="st">&quot;</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">&#39;s/ mynewlinestartshere /\r\n/g&#39;</span><span class="va">)</span><span class="st">&quot;</span> <span class="co"># hack for linebreaks in startproc scripts</span>
^<span class="ex">--</span> SC2001: See if you can use <span class="va">${variable//</span>search<span class="va">/</span>replace<span class="va">}</span> instead.
<span class="ex">In</span> bashbot.sh line 490:
<span class="va">CONTACT[USER_ID]=</span><span class="st">&quot;</span><span class="va">$(</span><span class="fu">sed</span> -n -e <span class="st">&#39;/\[&quot;result&quot;,&#39;</span><span class="va">$PROCESS_NUMBER</span><span class="st">&#39;,&quot;message&quot;,&quot;contact&quot;,&quot;user_id&quot;\]/ s/.*\][ \t]&quot;\(.*\)&quot;$/\1/p&#39;</span> <span class="op">&lt;</span><span class="st">&quot;</span><span class="va">$TMP</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span>
^<span class="ex">--</span> SC2034: CONTACT appears unused. Verify it or export it.</code></pre></div>
<p>The example show two warnings in bashbots scripts. The first is a hint you may use shell substitions instead of sed, this is fixed and much faster as the “echo | sed” solution. The second warning is about an unused variable, this is true because in our examples CONTACT is not used but assigned in case you want to use it :-)</p>
<h4 id="prev-best-practice"><a href="5_practice.html">Prev Best Practice</a></h4>
<h4 id="next-functions-reference"><a href="6_reference.html">Next Functions Reference</a></h4>
<h4 id="version-v0.90-dev2-0-gec85636"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-0-gec85636</h4>
</body>
</html>

View File

@ -0,0 +1,453 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - doc/6_reference.html</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - doc/6_reference.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="bashbot-function-reference">Bashbot function reference</h2>
<h3 id="send-forward-delete-messages">Send, forward, delete messages</h3>
<h5 id="send_action">send_action</h5>
<p><code>send_action</code> shows users what your bot is currently doing.</p>
<p><em>usage:</em> send_action “${CHAT[ID]}” “action”</p>
<p><em>“action”:</em> <code>typing</code>, <code>upload_photo</code>, <code>record_video</code>, <code>upload_video</code>, <code>record_audio</code>, <code>upload_audio</code>, <code>upload_document</code>, <code>find_location</code>.</p>
<p><em>alias:</em> _action “action”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_action</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;typing&quot;</span>
<span class="ex">send_action</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;record_audio&quot;</span></code></pre></div>
<h5 id="send_normal_message">send_normal_message</h5>
<p><code>send_normal_message</code> sends text only messages to the given chat.</p>
<p><em>usage:</em> send_normal_message “${CHAT[ID]}” “message”</p>
<p><em>alias:</em> _normal_message “message”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;this is a text message&quot;</span></code></pre></div>
<h5 id="send_markdown_message">send_markdown_message</h5>
<p><code>send_markdown_message</code> sends markdown style messages to the given chat. Telegram supports a <a href="https://core.telegram.org/bots/api#markdown-style">reduced set of Markdown</a> only</p>
<p><em>usage:</em> send_markdown_message “${CHAT[ID]}” “markdown message”</p>
<p><em>alias:</em> _markdown “message”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;this is a markdown message, next word is *bold*&quot;</span>
<span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;*bold* _italic_ [text](link)&quot;</span></code></pre></div>
<h5 id="send_html_message">send_html_message</h5>
<p><code>send_html_message</code> sends HTML style messages to the given chat. Telegram supports a <a href="https://core.telegram.org/bots/api#html-style">reduced set of HTML</a> only</p>
<p><em>usage:</em> send_html_message “${CHAT[ID]}” “html message”</p>
<p><em>alias:</em> _html_message “message”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;this is a markdown message, next word is &lt;b&gt;bold&lt;/b&gt;&quot;</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;&lt;b&gt;bold&lt;/b&gt; &lt;i&gt;italic&gt;&lt;i&gt; &lt;em&gt;italic&gt;/em&gt; &lt;a href=&quot;</span>link<span class="st">&quot;&gt;Text&lt;/a&gt;&quot;</span></code></pre></div>
<h5 id="forward_message">forward_message</h5>
<p><code>forward_mesage</code> forwards a messsage to the given chat.</p>
<p><em>usage:</em> forward_message “chat_to” “chat_from” “${MESSAGE[ID]}”</p>
<p><em>old call:</em> forward “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>FROMCHAT” “${MESSAGE[ID]}”</p>
<p><em>alias:</em> _forward “<span class="math inline">$FROMCHAT&quot; &quot;$</span>{MESSAGE[ID]}”</p>
<p>See also <a href="https://core.telegram.org/bots/api#formatting-options">Text formating options</a></p>
<hr />
<h5 id="delete_message">delete_message</h5>
<p>If your Bot is admin of a Chat he can delete every message, if not he can delete only his messages.</p>
<p><em>usage:</em> delete_message “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{MESSAGE[ID]}”</p>
<p><em>alias:</em> _del_message “${MESSAGE[ID]}”</p>
<p>See also <a href="https://core.telegram.org/bots/api#deletemessage">deleteMessage limitations</a></p>
<hr />
<h5 id="send_message">send_message</h5>
<p><code>send_message</code> sends any type of message to the given chat. Type of output is steered by keywords within the message.</p>
<p>The main use case for send_message is to process the output of interactive chats and background jobs. <strong>For regular Bot commands I recommend using of the dedicated send_xxx_message() functions from above.</strong></p>
<p><em>usage:</em> send_message “${CHAT[ID]}” “message”</p>
<p><em>example:</em> - see <a href="2_usage.md#send_message">Usage</a> and <a href="3_advanced.html">Advanced Usage</a></p>
<hr />
<h3 id="file-location-venue-keyboard">File, Location, Venue, Keyboard</h3>
<h5 id="send_file">send_file</h5>
<p>send_file allows you to send different types of files, e.g. photos, stickers, audio, media, etc. <a href="https://core.telegram.org/bots/api#sending-files">see more</a></p>
<p>Starting with version 0.80 send_file implements the following rules:</p>
<ul>
<li>file names must not contain “..”</li>
<li>file names must not start with “.”</li>
<li>file names not starting wit “/” are realtive to $TMPDIR, e.g. ./data-bot-bash</li>
<li>abolute filenames must match $FILE_REGEX</li>
</ul>
<p><em>usage:</em> send_file “${CHAT[ID]}” “file” “caption”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_file</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;/home/user/doge.jpg&quot;</span> <span class="st">&quot;Lool&quot;</span>
<span class="ex">send_file</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;https://www.domain,com/something.gif&quot;</span> <span class="st">&quot;Something&quot;</span></code></pre></div>
<h5 id="send_location">send_location</h5>
<p><em>usage:</em> send_location “${CHAT[ID]}” “Latitude” “Longitude”</p>
<h5 id="send_venue">send_venue</h5>
<p><em>usage:</em> send_venue “${CHAT[ID]}” “Latitude” “Longitude” “Title” “Address” “foursquare id (optional)”</p>
<hr />
<h5 id="send_keyboard">send_keyboard</h5>
<p>Note: since version 0.6 send_keyboard was changed to use native “JSON Array” notation as used from Telegram. Example Keybord Array definitions:</p>
<ul>
<li>yes no in two rows:
<ul>
<li>OLD format: yes no (two strings)</li>
<li>NEW format: [ “yes” ] , [ “no” ] (two arrays with a string)</li>
</ul></li>
<li>new layouts made easy with NEW format:
<ul>
<li>Yes No in one row: [ “yes” , “no” ]</li>
<li>Yes No plus Maybe in 2.row: [ “yes” , “no” ] , [ “maybe” ]</li>
<li>numpad style keyboard: [ “1” , “2” , “3” ] , [ “4” , “5” , “6” ] , [ “7” , “8” , “9” ] , [ “0” ]</li>
</ul></li>
</ul>
<p><em>usage:</em> send_keyboard “chat-id” “message” “keyboard”</p>
<p><em>alias:</em> _keyboard “message” “keyboard”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_keyboard</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Say yes or no&quot;</span> <span class="st">&quot;[ </span><span class="dt">\\</span><span class="st">&quot;</span>yes<span class="dt">\&quot;</span> , <span class="dt">\\</span><span class="st">&quot;no</span><span class="dt">\&quot;</span><span class="st"> ]&quot;&quot;</span>
<span class="st">send_keyboard &quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot; &quot;</span>Say yes or no<span class="st">&quot; &quot;</span>[ <span class="dt">\\</span><span class="st">&quot;yes</span><span class="dt">\\</span><span class="st">&quot;</span> ] , [ <span class="dt">\\</span><span class="st">&quot;no</span><span class="dt">\\</span><span class="st">&quot;</span> ]<span class="st">&quot;</span>
<span class="st">send_keyboard &quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot; &quot;</span>Enter digit<span class="st">&quot; &quot;</span>[ <span class="dt">\\</span><span class="st">&quot;1</span><span class="dt">\\</span><span class="st">&quot;</span> , <span class="dt">\\</span><span class="st">&quot;2</span><span class="dt">\\</span><span class="st">&quot;</span> , <span class="dt">\\</span><span class="st">&quot;3</span><span class="dt">\\</span><span class="st">&quot;</span> ] , [ <span class="dt">\\</span><span class="st">&quot;4</span><span class="dt">\\</span><span class="st">&quot;</span> , <span class="dt">\\</span><span class="st">&quot;5</span><span class="dt">\\</span><span class="st">&quot;</span> , <span class="dt">\\</span><span class="st">&quot;6</span><span class="dt">\\</span><span class="st">&quot;</span> ] , [ <span class="dt">\\</span><span class="st">&quot;7</span><span class="dt">\\</span><span class="st">&quot;</span> , <span class="dt">\\</span><span class="st">&quot;8</span><span class="dt">\\</span><span class="st">&quot;</span> , <span class="dt">\\</span><span class="st">&quot;9</span><span class="dt">\\</span><span class="st">&quot;</span> ] , [ <span class="dt">\\</span><span class="st">&quot;0</span><span class="dt">\\</span><span class="st">&quot;</span> ]<span class="st">&quot;</span></code></pre></div>
<h5 id="remove_keyboard">remove_keyboard</h5>
<p><em>usage:</em> remove_keybord “$CHAT[ID]” “message”</p>
<p><em>alias:</em> _del_keyboard “message”</p>
<p><em>See also: <a href="https://core.telegram.org/bots/api/#replykeyboardmarkup">Keyboard Markup</a></em></p>
<hr />
<h5 id="send_button">send_button</h5>
<p><em>usage:</em> send_button “chat-id” “message” “text” “URL”</p>
<p><em>alias:</em> _button “text” “URL”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_button</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;MAKE MONEY FAST!!!&quot;</span> <span class="st">&quot;Visit my Shop&quot;</span> <span class="st">&quot;https://dealz.rrr.de&quot;</span></code></pre></div>
<h5 id="send_inline_keyboard">send_inline_keyboard</h5>
<p>This allows to place multiple inline buttons in a row. The inline buttons must specified as a JSON array in the following format:</p>
<p><code>[ {&quot;text&quot;:&quot;text1&quot;, &quot;url&quot;:&quot;url1&quot;}, ... {&quot;text&quot;:&quot;textN&quot;, &quot;url&quot;:&quot;urlN&quot;} ]</code></p>
<p>Each button consists of a pair of text and URL values, sourrounded by { }, multiple buttons are seperated by <strong>,</strong> and everthing is wrapped in [ ].</p>
<p><em>usage:</em> send_inline_keyboard “chat-id” “message” “[ {“text”:“text”, “url”:“url”} …]”</p>
<p><em>alias:</em> _inline_keyboard “[{“text”:“text”, “url”:“url”} …]”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">send_inline_keyboard</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;MAKE MONEY FAST!!!&quot;</span> <span class="st">&#39;[{&quot;text&quot;:&quot;Visit my Shop&quot;, url&quot;&quot;:&quot;https://dealz.rrr.de&quot;}]&#39;</span>
<span class="ex">send_inline_keyboard</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;&quot;</span> <span class="st">&#39;[{&quot;text&quot;:&quot;button 1&quot;, url&quot;&quot;:&quot;url 1&quot;}, {&quot;text&quot;:&quot;button 2&quot;, url&quot;&quot;:&quot;url 2&quot;} ]&#39;</span>
<span class="ex">send_inline_keyboard</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;&quot;</span> <span class="st">&#39;[{&quot;text&quot;:&quot;b 1&quot;, url&quot;&quot;:&quot;u 1&quot;}, {&quot;text&quot;:&quot;b 2&quot;, url&quot;&quot;:&quot;u 2&quot;}, {&quot;text&quot;:&quot;b 2&quot;, url&quot;&quot;:&quot;u 2&quot;} ]&#39;</span></code></pre></div>
<p><em>See also <a href="https://core.telegram.org/bots/api/#inlinekeyboardmarkup">Inline keyboard markup</a></em></p>
<hr />
<h3 id="user-access-control">User Access Control</h3>
<h5 id="kick_chat_member">kick_chat_member</h5>
<p>If your Bot is a chat admin he can kick and ban a user.</p>
<p><em>usage:</em> kick_chat_member “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{USER[ID]}”</p>
<p><em>alias:</em> _kick_user “${USER[ID]}”</p>
<h5 id="unban_chat_member">unban_chat_member</h5>
<p>If your Bot is a chat admine can unban a kicked user.</p>
<p><em>usage:</em> unban_chat_member “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{USER[ID]}”</p>
<p><em>alias:</em> _unban “${USER[ID]}”</p>
<h5 id="leave_chat">leave_chat</h5>
<p>Your Bot will leave the chat.</p>
<p><em>usage:</em> leave_chat “${CHAT[ID]}”</p>
<p><em>alias:</em> _leave</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">if</span> <span class="ex">_is_admin</span> <span class="kw">;</span> <span class="kw">then</span>
<span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;*LEAVING CHAT...*&quot;</span>
<span class="ex">leave_chat</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span>
<span class="kw">fi</span></code></pre></div>
<p>See also <a href="https://core.telegram.org/bots/api/#kickchatmember">kick Chat Member</a>*</p>
<hr />
<h5 id="user_is_botadmin">user_is_botadmin</h5>
<p>Return true (0) if user is admin of bot, user id if botadmin is read from file ./botadmin.</p>
<p><em>usage:</em> user_is_botadmin “${USER[ID]}”</p>
<p><em>alias:</em> _is_botadmin</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="ex">_is_botadmin</span> <span class="kw">&amp;&amp;</span> <span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;You are *BOTADMIN*.&quot;</span></code></pre></div>
<h5 id="user_is_creator">user_is_creator</h5>
<p>Return true (0) if user is creator of given chat or chat is a private chat.</p>
<p><em>usage:</em> user_is_creator “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{USER[ID]}”</p>
<p><em>alias:</em> _is_creator</p>
<h5 id="user_is_admin">user_is_admin</h5>
<p>Return true (0) if user is admin or creator of given chat.</p>
<p><em>usage:</em> user_is_admin “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{USER[ID]}”</p>
<p><em>alias:</em> _is_admin</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">if</span> <span class="ex">_is_admin</span> <span class="kw">;</span> <span class="kw">then</span>
<span class="ex">send_markdown_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;*LEAVING CHAT...*&quot;</span>
<span class="ex">leave_chat</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span>
<span class="kw">fi</span></code></pre></div>
<p><em>See also <a href="https://core.telegram.org/bots/api/#chatmember">Chat Member</a></em></p>
<h5 id="user_is_allowed">user_is_allowed</h5>
<p>Bahsbot supports User Access Control, see <a href="3_advanced.html">Advanced Usage</a></p>
<p><em>usage:</em> user_is_allowed “<span class="math inline">${USER[ID]}&quot; &quot;what&quot; &quot;$</span>{CHAT[ID]}”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">if</span> ! <span class="ex">user_is_allowed</span> <span class="st">&quot;</span><span class="va">${USER[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;start&quot;</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="kw">;</span> <span class="kw">then</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;You are not allowed to start Bot.&quot;</span>
<span class="kw">fi</span></code></pre></div>
<hr />
<h3 id="inline-queries---answer-direct-queries-to-bot">Inline Queries - answer direct queries to bot</h3>
<p>You must include <code>source modules/inline.sh</code> in commands.sh to have the following functions availible.</p>
<p>Inline Queries allows users to interact with your bot directly without sending extra commands. As an answer to an inline query you can send back one or more results to the Telegram client. The Telegram client will then show the results to the user and let him select one.</p>
<h5 id="answer_inline_query">answer_inline_query</h5>
<p>answer_inline_query is provided for backward compatibility with older versions of bashbot. It send back only one response to an inline query.</p>
<p><em>usage:</em> answer_inline_query “$i{QUERY[ID]}” “type” “type arg 1” … “type arg n”</p>
<p><em>example:</em> - see <a href="3_advanced.html">Advanced Usage</a></p>
<h5 id="answer_inline_multi">answer_inline_multi</h5>
<p>anser_inline_multi allows you to send back a list of responses. responses must be seperated by ,.</p>
<p><em>usage:</em> answer_inline_multi “${iQUERY[ID]}” “res, res, … res”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># note the starting &quot; and ending &quot; !!</span>
<span class="ex">answer_inline_multi</span> <span class="st">&quot;</span><span class="va">${iQUERY[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;</span>
<span class="st"> </span><span class="va">$(</span><span class="ex">inline_query_compose</span> <span class="st">&quot;1&quot;</span> <span class="st">&quot;photo&quot;</span> <span class="st">&quot;https://avatars0.githubusercontent.com/u/13046303&quot;</span><span class="va">)</span><span class="st"> ,</span>
<span class="st"> ...</span>
<span class="st"> </span><span class="va">$(</span><span class="ex">inline_query_compose</span> <span class="st">&quot;n&quot;</span> <span class="st">&quot;photo&quot;</span> <span class="st">&quot;https://avatars1.githubusercontent.com/u/4593242&quot;</span><span class="va">)</span>
<span class="st"> &quot;</span></code></pre></div>
<h4 id="inline_query_compose">inline_query_compose</h4>
<p>inline_query_compose composes one response element to to send back.</p>
<p><em>usage:</em> inline_query_compose ID type args ….</p>
<pre><code> ID = unique ID for this response, 1-64 byte long
type = type of answer, e.g. article, photo, video, location ...
args = mandatory arguments in the order they are described in telegram documentation</code></pre>
<p>Currently the following types and arguments are implemented (optional arguments in parenthesis)</p>
<pre><code> &quot;article&quot;|&quot;message&quot; title message (markup description)
&quot;photo&quot; photo_URL (thumb_URL title description caption)
&quot;gif&quot; photo_URL (thumb_URL title caption)
&quot;mpeg4_gif&quot; mpeg_URL (thumb_URL title caption)
&quot;video&quot; video_URL mime_type thumb_URL title (caption)
&quot;audio&quot; audio_URL title (caption)
&quot;voice&quot; voice_URL title (caption)
&quot;document&quot; title document_URL mime_type (caption description)
&quot;location&quot; latitude longitude title
&quot;venue&quot; latitude longitude title (adress foursquare)
&quot;contact&quot; phone first (last thumb)
&quot;cached_photo&quot; file (title description caption)
&quot;cached_gif&quot; file (title caption)
&quot;cached_mpeg4_gif&quot; file (title caption)
&quot;cached_sticker&quot; file
&quot;cached_document&quot; title file (description caption)
&quot;cached_video&quot; file title (description caption)
&quot;cached_voice&quot; file title (caption)
&quot;cached_audio&quot; file title (caption)</code></pre>
<p>see <a href="https://core.telegram.org/bots/api#inlinequeryresult">InlineQueryResult for more information</a> about response types and their arguments.</p>
<hr />
<h3 id="background-and-interactive-jobs">Background and Interactive jobs</h3>
<p>You must include <code>source modules/background.sh</code> in commands.sh to have the following functions availible.</p>
<h5 id="start_proc">start_proc</h5>
<p><code>startproc</code> 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 <a href="3_advanced.html">Advanced Usage</a></p>
<p><em>usage:</em> start_proc “${CHAT[ID]}” “script”</p>
<p><em>alias:</em> startproc “script”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">startproc</span> <span class="st">&#39;examples/calc.sh&#39;</span></code></pre></div>
<h5 id="check_proc">check_proc</h5>
<p>Return true (0) if an interactive script is running in the chat.</p>
<p><em>usage:</em> check_prog “${CHAT[ID]}”</p>
<p><em>alias:</em> checkprog</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">if</span> ! <span class="ex">check_proc</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="kw">;</span> <span class="kw">then</span>
<span class="ex">startproc</span> <span class="st">&quot;examples/calc.sh&quot;</span>
<span class="kw">else</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Calc already running ...&quot;</span>
<span class="kw">fi</span></code></pre></div>
<h5 id="kill_proc">kill_proc</h5>
<p>Kill the interactive script running in the chat</p>
<p><em>usage:</em> kill_proc “${CHAT[ID]}”</p>
<p><em>alias:</em> killproc</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">if</span> <span class="ex">check_proc</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="kw">;</span> <span class="kw">then</span>
<span class="ex">killproc</span> <span class="kw">&amp;&amp;</span> <span class="ex">send_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Command canceled.&quot;</span>
<span class="kw">else</span>
<span class="ex">send_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Command is not running.&quot;</span>
<span class="kw">fi</span></code></pre></div>
<hr />
<h5 id="start_back">start_back</h5>
<p>Starts a script as a background job and attaches a jobname to it. All output from a background job is sent to the associated chat.</p>
<p>In contrast to interactive chats, background jobs do not recieve user input and can run forever. In addition you can suspend and restart running jobs, e.g. after reboot.</p>
<p><em>usage:</em> start_back “${CHAT[ID]}” “script” “jobname”</p>
<p><em>alias:</em> background “script” “jobname”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">background</span> <span class="st">&quot;examples/notify.sh&quot;</span> <span class="st">&quot;notify&quot;</span></code></pre></div>
<h5 id="check_back">check_back</h5>
<p>Return true (0) if an background job is active in the given chat.</p>
<p><em>usage:</em> check_back “${CHAT[ID]}” “jobname”</p>
<p><em>alias:</em> checkback “jobname”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">if</span> ! <span class="ex">checkback</span> <span class="st">&quot;notify&quot;</span> <span class="kw">;</span> <span class="kw">then</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Start notify&quot;</span>
<span class="ex">background</span> <span class="st">&quot;examples/notify.sh&quot;</span> <span class="st">&quot;notify&quot;</span>
<span class="kw">else</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Process notify already running.&quot;</span>
<span class="kw">fi</span></code></pre></div>
<h5 id="kill_back">kill_back</h5>
<p><em>usage:</em> kill_back “${CHAT[ID]}” “jobname”</p>
<p><em>alias:</em> killback “jobname”</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">checkback</span> <span class="st">&quot;notify&quot;</span>
<span class="kw">if</span><span class="bu"> [</span> <span class="st">&quot;</span><span class="va">$res</span><span class="st">&quot;</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span> ; <span class="kw">then</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Kill notify&quot;</span>
<span class="ex">killback</span> <span class="st">&quot;notify&quot;</span>
<span class="kw">else</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;Process notify not run.&quot;</span>
<span class="kw">fi</span></code></pre></div>
<hr />
<h5 id="send_interactive">send_interactive</h5>
<p>Form version 0.80 on forward_message is used to forward messages to interactive job. It replaces the old inproc commands used for TMUX. Usually message is automatically forwarded in commands.sh, but you can forward messages wihle processing also or send your own messages.</p>
<p><em>usage:</em> send_interactive “${CHAT[ID]}” “message”</p>
<p><em>replaces:</em> incproc</p>
<h3 id="aliases---shortcuts-for-often-used-funtions">Aliases - shortcuts for often used funtions</h3>
<p>You must include <code>source modules/aliases.sh</code> in commands.sh to have the following functions availible.</p>
<h5 id="is_botadmin">_is_botadmin</h5>
<p><em>usage:</em> _is_botadmin</p>
<p><em>alias for:</em> user_is_botadmin “${USER[ID]}”</p>
<h5 id="is_admin">_is_admin</h5>
<p><em>usage:</em> _is_admin</p>
<p><em>alias for:</em> user_is_admin “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{USER[ID]}”</p>
<h5 id="is_allowed">_is_allowed</h5>
<p><em>usage:</em> _is_allowed “what”</p>
<p><em>alias for:</em> user_is_allowed “<span class="math inline">${USER[ID]}&quot; &quot;what&quot; &quot;$</span>{CHAT[ID]}”</p>
<hr />
<h5 id="kick_user">_kick_user</h5>
<p><em>usage:</em> _kick_user “${USER[ID]}”</p>
<p><em>alias for:</em> kick_chat_member “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{USER[ID]}”</p>
<h5 id="unban">_unban</h5>
<p><em>usage:</em> _unban “${USER[ID]}”</p>
<p><em>alias for:</em> unban_chat_member “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{USER[ID]}”</p>
<h5 id="leave">_leave</h5>
<p><em>usage:</em> _leave</p>
<p><em>alias for:</em> leave_chat “${CHAT[ID]}”</p>
<hr />
<h5 id="message">_message</h5>
<p><em>usage:</em> _message “message”</p>
<p><em>alias for:</em> send_normal_message “${CHAT[ID]}” “message”</p>
<h5 id="normal_message">_normal_message</h5>
<p><em>usage:</em> _normal_message “message”</p>
<p><em>alias for:</em> send_normal_message “${CHAT[ID]}” “message”</p>
<h5 id="html_message">_html_message</h5>
<p><em>usage:</em> _html_message “message”</p>
<p><em>alias for:</em> send_html_message “${CHAT[ID]}” “message”</p>
<h5 id="markdown_message">_markdown_message</h5>
<p><em>usage:</em> _markdown_message “message”</p>
<p><em>alias for:</em> send_markdown_message “${CHAT[ID]}” “message”</p>
<hr />
<h4 id="inline_button-usage-_inline_button-1-2">_inline_button <em>usage:</em> _inline_button “<span class="math inline">${1}&quot; &quot;$</span>{2}”</h4>
<p><em>alias for:</em> send_inline_button “<span class="math inline">${CHAT[ID]}&quot; &quot;&quot; &quot;$</span>{1}” “${2}”</p>
<h4 id="inline_keyboard-usage-_inline_keyboard-1">_inline_keyboard <em>usage:</em> _inline_keyboard “${1}”</h4>
<p><em>alias for:</em> _inline_keyboard “<span class="math inline">${CHAT[ID]}&quot; &quot;&quot; &quot;$</span>{1}”</p>
<h4 id="keyboard_numpad-usage-_keyboard_numpad">_keyboard_numpad <em>usage:</em> _keyboard_numpad</h4>
<p><em>alias for:</em> send_keyboard “${CHAT[ID]}” “” [“1”,“2”,“3”],[“4”,“5”,“6”],[“7”,“8”,“9”],[“-”,“0”,“.”] “yes”</p>
<h4 id="keyboard_yesno-usage-_keyboard_yesno">_keyboard_yesno <em>usage:</em> _keyboard_yesno</h4>
<p><em>alias for:</em> send_keyboard [“yes”,“no”]</p>
<h4 id="del_keyboard-usage-_del_keyboard">_del_keyboard <em>usage:</em> _del_keyboard</h4>
<p><em>alias for:</em> remove_keyboard “${CHAT[ID]}” “”</p>
<h3 id="helper-functions">Helper functions</h3>
<h5 id="download">download</h5>
<p>Download the fiven URL ans returns the final filename in TMPDIR. If the given filename exists,the filename is prefixed with a random number. filename is not allowed to contain / or ...</p>
<p><em>usage:</em> download URL filename</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="va">file=</span><span class="st">&quot;</span><span class="va">$(</span><span class="ex">download</span> <span class="st">&quot;https://avatars.githubusercontent.com/u/13046303&quot;</span> <span class="st">&quot;avatar.jpg&quot;</span><span class="va">)</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$file</span><span class="st">&quot;</span> -<span class="op">&gt;</span> ./data-bot-bash/avatar.jpg
<span class="va">file=</span><span class="st">&quot;</span><span class="va">$(</span><span class="ex">download</span> <span class="st">&quot;https://avatars.githubusercontent.com/u/13046303&quot;</span> <span class="st">&quot;avatar.jpg&quot;</span><span class="va">)</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;</span><span class="va">$file</span><span class="st">&quot;</span> -<span class="op">&gt;</span> ./data-bot-bash/12345-avatar.jpg</code></pre></div>
<h5 id="exists-returns-true-if-the-given-function-exist-can-be-used-to-check-if-a-module-is-loaded.">_exists Returns true if the given function exist, can be used to check if a module is loaded.</h5>
<p><em>usage</em> _exists command</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">_exists</span> <span class="st">&quot;curl&quot;</span> <span class="kw">&amp;&amp;</span> <span class="ex">_message</span> <span class="st">&quot;Command curl is not installed!&quot;</span></code></pre></div>
<h5 id="is_function-returns-true-if-the-given-function-exist-can-be-used-to-check-if-a-module-is-loaded.">_is_function Returns true if the given function exist, can be used to check if a module is loaded.</h5>
<p><em>usage</em> _is_function function</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">_is_function</span> <span class="st">&quot;background&quot;</span> <span class="kw">&amp;&amp;</span> <span class="ex">_message</span> <span class="st">&quot;you can run background jobs!&quot;</span></code></pre></div>
<hr />
<h3 id="bashbot-internal-functions">Bashbot internal functions</h3>
<p>These functions are for internal use only and must not used in your bot commands.</p>
<h5 id="procname">procname</h5>
<p>Returns PrefixBotname_Postfix</p>
<p><em>usage:</em> procname postfix prefix</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># returns botname, if already set</span>
<span class="ex">procname</span>
<span class="co"># returns unique identifier for everthing related to chat</span>
<span class="ex">procname</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span>
<span class="co"># returns unique identifier for job, regardless of chat</span>
<span class="ex">procname</span> <span class="st">&quot;&quot;</span> <span class="st">&quot;back-jobname-&quot;</span>
<span class="co"># returns unique identifier for a job related to a chat</span>
<span class="co"># e.g. fifo, cmd and logfile name</span>
<span class="ex">procname</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;back-jobname-&quot;</span></code></pre></div>
<h5 id="proclist">proclist</h5>
<p>Returns process IDs of current bot processes containing string pattern in name or argument.</p>
<p><em>usage:</em> proclist pattern</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># list PIDs of all background processes</span>
<span class="ex">proclist</span> <span class="st">&quot;back-&quot;</span>
<span class="co"># list PIDs of all processes of a job</span>
<span class="ex">proclist</span> <span class="st">&quot;back-jobname-&quot;</span>
<span class="co"># list PIDs of all processes for a chat</span>
<span class="ex">proclist</span> <span class="st">&quot;_</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span>
<span class="co"># list PIDs of all bot processes</span>
<span class="ex">proclist</span> </code></pre></div>
<h5 id="killallproc">killallproc</h5>
<p>kill all current bot processes containing string pattern in name or argument</p>
<p><em>usage:</em> killallproc pattern</p>
<p><em>example:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># kill all background processes</span>
<span class="ex">killallproc</span> <span class="st">&quot;back-&quot;</span>
<span class="co"># kill all processes for a chat</span>
<span class="ex">killallproc</span> <span class="st">&quot;_</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span>
<span class="co"># kill all bot processes, including YOURSELF!</span>
<span class="ex">killallproc</span> </code></pre></div>
<h5 id="get_file">get_file</h5>
<p><em>usage:</em> url=“<span class="math inline">$(get_file &quot;$</span>{CHAT[ID]}” “message”)&quot;</p>
<hr />
<h5 id="send_text">send_text</h5>
<p><em>usage:</em> send_text “${CHAT[ID]}” “message”</p>
<hr />
<h5 id="jsondecode">JsonDecode</h5>
<p>Outputs decoded string to STDOUT</p>
<p><em>usage:</em> JsonDecode “string”</p>
<h5 id="jsongetstring">JsonGetString</h5>
<p>Reads JSON fro STDIN and Outputs found String to STDOUT</p>
<p><em>usage:</em> JsonGetString <code>&quot;path&quot;,&quot;to&quot;,&quot;string&quot;</code></p>
<h5 id="jsongetvalue">JsonGetValue</h5>
<p>Reads JSON fro STDIN and Outputs found Value to STDOUT</p>
<p><em>usage:</em> JsonGetValue <code>&quot;path&quot;,&quot;to&quot;,&quot;value&quot;</code></p>
<hr />
<h5 id="get_chat_member_status">get_chat_member_status</h5>
<p><em>usage:</em> get_chat_member_status “<span class="math inline">${CHAT[ID]}&quot; &quot;$</span>{USER[ID]}”</p>
<p>this may get an official function …</p>
<hr />
<h5 id="process_client">process_client</h5>
<p>Every Message sent to your Bot is processd by this function. It parse the send JSON and assign the found Values to bash variables.</p>
<h5 id="process_updates">process_updates</h5>
<p>If new updates are availible, this functions gets the JSON from Telegram and dispatch it.</p>
<hr />
<h5 id="getbotname">getBotName</h5>
<p>The name of your bot is availible as bash variable “$ME”, there is no need to call this function if Bot is running.</p>
<p><em>usage:</em> ME=“$(getBotNiname)”</p>
<h4 id="prev-best-practice"><a href="5_practice.html">Prev Best Practice</a></h4>
<h4 id="next-notes-for-developers"><a href="7_develop.html">Next Notes for Developers</a></h4>
<h4 id="version-v0.90-dev2-0-gec85636"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-0-gec85636</h4>
</body>
</html>

View File

@ -0,0 +1,242 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashobot Documentation - doc/7_develop.html</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashobot Documentation - doc/7_develop.html</h1>
</div>
<h4 id="home"><a href="../README.html">Home</a></h4>
<h2 id="notes-for-bashbot-developers">Notes for bashbot developers</h2>
<p>This section is about help and best practices for new bashbot developers. The main focus on is creating new versions of bashbot, not on develop your individual bot. Nevertheless the rules and tools described here can also help you with your bot development.</p>
<p>bashbot development is done on github. If you want to provide fixes or new features <a href="https://help.github.com/en/articles/fork-a-repo">fork bashbot on githup</a> and provide changes as <a href="https://help.github.com/en/articles/creating-a-pull-request">pull request on github</a>.</p>
<h3 id="debugging-bashbot">Debugging Bashbot</h3>
<p>In normal mode of operation all bashbot output is discarded. To get these messages (and more) you can start bashbot in the current shell <code>./bashbot.sh startbot</code>. Now you can see all output or erros from bashbot. In addition you can change the change the level of verbosity by adding a third argument after startbot.</p>
<pre><code> &quot;debug&quot; redirects all output to &quot;DEBUG.log&quot;, in addtion every update is logged in &quot;MESSAGE.LOG&quot; and &quot;INLINE.log&quot;
&quot;debugterm&quot; same as debug but output and errors are sent to terminal
&quot;xdebug&quot; same as debug plus set bash option &#39;-x&#39; to log any executed command
&quot;xdebugterm&quot; same as xdebug but output and errors are sent to terminal</code></pre>
<h3 id="modules-and-addons">Modules and Addons</h3>
<p><strong>Modules</strong> live in <code>modules/*.sh</code> and are bashbot functions factored out in seperate files, gouped by functionality. Main reason for creating modules was to keep bashbot.sh small, while extending functionality. In addition not every functionality is needed by a bot, so you can disable modules by removing them, e.g. rename the respective module files to module.sh.off.</p>
<p>Modules must use onyl functions provided by bahsbot.sh or the module itself, no depedencies to other modules or addons must exist. If a module function is called from bashbot.sh, bashbot must work if the module is disabled, so its madatory to use _is_function or _execute_if_function if a module function is called.</p>
<p><strong>Addons</strong> live in <code>addons/*.sh.dist</code> and are disabled by default. To activate an addon remove the .dist from filename, e.g. <code>cp addons/example.sh.dist addons/example.sh</code>. Addons must register themself to BASHBOT_EVENTS at startup, e.g. to call a function everytime a message is recieved. Registering to EVENTS is similar on how commands.sh is ececuted, but more flexible and one major difference: <strong>Addons are executed in the context of the main script</strong>, while commands.sh is executed as a seperate process.</p>
<p>This is why event functions are time critical and must return as fast as possible. Spawn actions as a seperate process or function with &amp;, e.g. send a message as respone from an addon: <code>send_message &quot;${CHAT[ID]}&quot; &quot;Message to send ...&quot; &amp;</code>.</p>
<h4 id="bashbot-events">Bashbot Events</h4>
<p>Addons can register functions to bashbot events at startup by providing their name and a callback function. If an event occours each registered function for the event is called.</p>
<p>Events run in the same context as the main bashbot loop, so variables set here are persistent as long bashbot is running.</p>
<p>Note: For the same reason event function MUST return imideatly! Time consuming tasks must be run in background or as a subshell, e.g. “long running &amp;</p>
<p>Availible events:</p>
<ul>
<li>BASHBOT_EVENT_INLINE an inline query is received</li>
<li>BASHBOT_EVENT_MESSAGE any type of message is received</li>
<li>BASHBOT_EVENT_TEXT a message containing text is received</li>
<li>BASHBOT_EVENT_CMD a command is recieved (fist word starts with /)</li>
<li>BASHBOT_EVENT_REPLYTO a reply to a message is received</li>
<li>BASHBOT_EVENT_FORWARD a forwarded message is received</li>
<li>BASHBOT_EVENT_CONTACT a contact is received</li>
<li>BASHBOT_EVENT_LOCATION a location or a venue is received</li>
<li>BASHBOT_EVENT_FILE a file is received</li>
</ul>
<p><em>usage</em>: BASHBOT_EVENT_xxx[“uniqe-name”]=“callback”</p>
<p>“unique-name” can be every alphanumeric string incl. - and _. Per convention it should be name of the addon followed by an internal identyfier.</p>
<p><em>Example:</em> Register a function to echo to any Text send to the bot</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># register callback:</span>
<span class="va">BASHBOT_EVENT_TEXT[</span><span class="st">&quot;example_1&quot;</span><span class="va">]=</span><span class="st">&quot;example_echo&quot;</span>
<span class="co"># function called if a text is recieved</span>
<span class="fu">example_echo()</span> <span class="kw">{</span>
<span class="co"># all availible bashbot functions and variables can be used</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="va">${CHAT[ID]}</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">${MESSAGE[0]}</span><span class="st">&quot;</span> <span class="kw">&amp;</span> <span class="co"># note the &amp;!</span>
<span class="kw">}</span></code></pre></div>
<ul>
<li>BAHSBOT_EVENT_TIMER is executed every minute and can be uses in variants: oneshot, every minute, every X minutes.</li>
</ul>
<p>Registering to BASHBOT_EVENT_TIMER works a little different, you have to add a timing argument to the index name.</p>
<p><em>usage: </em> BAHSBOT_EVENT_TIMER[“name”,“time”], where time is:</p>
<ul>
<li>-x execute ONCE in x minutes</li>
<li>0 ignored</li>
<li>1 execute every minute</li>
<li>x execute every x minutes</li>
</ul>
<p><em>Examples:</em></p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># register callback:</span>
<span class="va">BAHSBOT_EVENT_TIMER[</span><span class="st">&quot;example_every&quot;</span><span class="va">,</span><span class="st">&quot;1&quot;</span><span class="va">]=</span><span class="st">&quot;example_everymin&quot;</span>
<span class="co"># function called every minute</span>
<span class="fu">example_everymin()</span> <span class="kw">{</span>
<span class="co"># timer events has no chat id, so send to yourself</span>
<span class="ex">send_normal_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span> <span class="st">&quot;</span><span class="va">${BOTADMIN}</span><span class="st">)&quot;</span> <span class="st">&quot;</span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">&quot;</span> &amp; <span class="co"># note the &amp;!</span>
}
<span class="co"># register other callback:</span>
BAHSBOT_EVENT_TIMER[<span class="st">&quot;example_10min&quot;</span>,<span class="st">&quot;-10&quot;</span>]=<span class="st">&quot;example_in10min&quot;</span>
BAHSBOT_EVENT_TIMER[<span class="st">&quot;example_every5&quot;</span>,<span class="st">&quot;5&quot;</span>]=<span class="st">&quot;example_every5min&quot;</span>
</code></pre></div>
<hr />
<h4 id="create-a-stripped-down-version-of-your-bot">Create a stripped down Version of your Bot</h4>
<p>Currently bashbot is more a bot development environment than a bot, containing examples, developer scripts, modules, documentation and more. You dont need all these files after youre finished with your cool new bot.</p>
<p>Lets create a stripped down version:</p>
<ul>
<li>delete all modules you do not need from modules, e.g. modules/inline.sh if you dont use inline queries</li>
<li>delete not needed standard commands and messages from commands.sh</li>
<li>delete not needed commands and functions from mycommands.sh</li>
<li>run <code>dev/make-standalone.sh</code> to create a a stripped down version of your bo</li>
</ul>
<p>Now have a look at the directory standalone, here you find the files bashbot.sh and commands.sh containing everything to run your bot. <a href="https://github.com/topkecleon/telegram-bot-bash/blob/master/dev/make-standalone.sh">Download make-standalone.sh</a> from github.</p>
<h3 id="setup-your-develop-environment">Setup your develop environment</h3>
<ol style="list-style-type: decimal">
<li>install git, install <a href="5_practice.html">shellcheck</a></li>
<li>setup your <a href="4_expert.html">environment for UTF-8</a></li>
<li>clone your bashbot fork to a new directory <code>git clone https://github.com/&lt;YOURNAME&gt;/telegram-bot-bash.git</code>, replace <code>&lt;YOURNAME&gt;</code> with your username on github</li>
<li>create and change to your develop branch <code>git checkout -b &lt;YOURBRANCH&gt;</code>, replace <code>&lt;YOURBRANCH&gt;</code> with the name you want to name it, e.g. develop</li>
<li>give your (dev) fork a new version tag: <code>git tag vx.xx</code>(optional)</li>
<li>setup github hooks by running <code>dev/install-hooks.sh</code> (optional)</li>
</ol>
<h4 id="test-add-push-changes">Test, Add, Push changes</h4>
<p>A typical bashbot develop loop looks as follow:</p>
<ol style="list-style-type: decimal">
<li>start developing - <em>change, copy, edit bashbot files …</em></li>
<li>after changing a bash sript: <code>shellcheck -x scipt.sh</code></li>
<li><code>dev/all-tests.sh</code> - <em>in case if errors back to 2.</em></li>
<li><code>dev/git-add.sh</code> - <em>check for changed files, update version string, run git add</em></li>
<li><code>git commit -m &quot;COMMIT MESSAGE&quot;; git push</code></li>
</ol>
<p><strong>If you setup your dev environment with hooks and use the scripts above, versioning, addding and testing is done automatically.</strong></p>
<h4 id="common-commands">common commands</h4>
<p>We state bashbot is a bash only bot, but this is not true. bashbot is a bash script using bash features PLUS external commands. Usually bash is used in a unix/linux environment where many (GNU) commands are availible, but if commands are missing, bashbot may not work.</p>
<p>To avoid this and make bashbot working on as many platforms as possible - from embedded linux to mainframe - I recommed to restrict ourself to the common commands provided by bash and coreutils/busybox/toybox. See <a href="https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html">Bash Builtins</a>, <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> and <a href="https://landley.net/toybox/help.html">toybox</a></p>
<p>Availible commands in bash, coreutils, busybox and toybox. Do you find curl on the list?</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="ex">.*</span>, [*, [[*, basename, break, builtin*, bzcat, caller*, cat, cd*, chattr,
<span class="fu">chgrp</span>, chmod, chown, clear, command*, continue *, cp, cut, date, declare*,
<span class="fu">dc</span>, dd, df, diff, dirname, du, echo*, eval*, exec*, exit *, expr*, find,
<span class="fu">fuser</span>, getopt*, grep, hash*, head, hexdump, id, kill, killall, last, length,
<span class="fu">less</span>, let*, ln, local*, logname, ls, lsattr, lsmod, man, mapfile*, md5sum, mkdir,
<span class="fu">mkfifo</span>, mknod, more, mv, nice, nohup, passwd, patch, printf*, ps, pwd*, read*,
<span class="ex">readarray*</span>, readonly* return*, rm, rmdir, sed, seq, sha1sum, shift*, sleep,
<span class="bu">source</span>*, sort, split, stat, strings, su, sync, tail, tar, tee, test,
<span class="bu">time</span>, times*, timeout, touch, tr, trap*, true, umask*, usleep, uudecode,
<span class="ex">uuencode</span>, wc, wget, which, who, whoami, xargs, yes</code></pre></div>
<p>commands marked with * are bash builtins, all others are external programms. Calling an external programm is more expensive then using bulitins or using an internal replacement. Here are some examples of internal replacement for external commands:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="va">HOST=</span><span class="st">&quot;</span><span class="va">$(</span><span class="fu">hostname</span><span class="va">)</span><span class="st">&quot;</span> <span class="ex">-</span><span class="op">&gt;</span> HOST=<span class="st">&quot;</span><span class="va">$HOSTNAME</span><span class="st">&quot;</span>
<span class="fu">seq</span> 1 100 -<span class="op">&gt;</span> <span class="dt">{0..100}</span>
<span class="va">data=</span><span class="st">&quot;</span><span class="va">$(</span><span class="fu">cat</span> file<span class="va">)</span><span class="st">&quot;</span> <span class="ex">-</span><span class="op">&gt;</span> data=<span class="st">&quot;</span><span class="op">$(&lt;</span><span class="st">&quot;file&quot;</span><span class="op">)</span><span class="st">&quot;</span>
<span class="va">DIR=</span><span class="st">&quot;</span><span class="va">$(</span><span class="fu">dirname</span> <span class="va">$0)</span><span class="st"> -&gt; DIR=&quot;&quot;</span><span class="va">${0%</span>/*<span class="va">}</span><span class="st">/&quot;&quot;</span>
<span class="st">IAM=&quot;</span><span class="va">($basename</span> <span class="va">$0)</span><span class="st">&quot; -&gt; IAM=&quot;</span><span class="va">${0##</span>*/<span class="va">}</span><span class="ex">*</span>
<span class="va">VAR=</span><span class="st">&quot;</span><span class="va">$((</span> 1 + 2 <span class="va">))</span><span class="st">&quot;</span> <span class="ex">-</span><span class="op">&gt;</span> (( var=1+2 ))
<span class="va">INDEX=</span><span class="st">&quot;</span><span class="va">$((</span> <span class="va">${INDEX}</span> + 1 <span class="va">))</span><span class="st">&quot;</span> <span class="ex">-</span><span class="op">&gt;</span> (( INDEX++ ))</code></pre></div>
<p>For more examples see <a href="https://github.com/dylanaraps/pure-bash-bible">Pure bash bible</a></p>
<h4 id="prepare-a-new-version">Prepare a new version</h4>
<p>After some development it may time to create a new version for the users. a new version can be in sub version upgrade, e.g. for fixes and smaller additions or a new release version for new features. To mark a new version use <code>git tag NEWVERSION</code> and run <code>dev/version.sh</code> to update all version strings.</p>
<p>Usually I start with pre versions and when everything looks good I push out a release candidate (rc) and finally the new version.</p>
<pre><code> v0.x-devx -&gt; v0.x-prex -&gt; v0.x-rc -&gt; v0.x ... 0.x+1-dev ...</code></pre>
<p>If you release a new Version run <code>dev/make-distribution.sh</code> to create the zip and tar.gz archives in the dist directory and attach them to the github release. Do not forget to delete directory dist afterwards.</p>
<h4 id="versioning">Versioning</h4>
<p>Bashbot is tagged with version numbers. If you start a new development cycle you can tag your fork with a version higher than the current version. E.g. if you fork v0.60 the next develop version should tagged as <code>git tag &quot;v0.61-dev&quot;</code> for fixes or <code>git tag &quot;v0.70-dev&quot;</code> for new features.</p>
<p>To get the current version name of your develepment fork run <code>git describe --tags</code>. The output looks like <code>v0.70-dev-6-g3fb7796</code> where your version tag is followed by the number of commits since you tag your branch and followed by the latest commit hash. see also <a href="../dev/version.sh">comments in version.sh</a></p>
<p>To update the Version Number in files run <code>dev/version.sh files</code>, it will update the line #### <br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> ### in all files to the current version name. To update version in all files run dev/version.sh without parameter.</p>
<h4 id="shellcheck">Shellcheck</h4>
<p>For a shell script running as a service its important to be paranoid about quoting, globbing and other common problems. So its a must to run shellchek on all shell scripts before you commit a change. this is automated by a git hook activated in Setup step 6.</p>
<p>To run shellcheck for a single script run <code>shellcheck -x script.sh</code>, to check all schripts run <code>dev/hooks/pre-commit.sh</code>.</p>
<h3 id="bashbot-tests">bashbot tests</h3>
<p>Starting with version 0.70 bashbot has a test suite. To start testsuite run <code>dev/all-tests.sh</code>. all-tests.sh will return SUCCESS only if all tests pass.</p>
<h4 id="enabling-disabling-tests">enabling / disabling tests</h4>
<p>All tests are placed in the directory <code>test</code>. To disable a test remove the execute flag from the *-test.sh script, to (re)enable a test make the script executable again.</p>
<h4 id="creating-new-tests">creating new tests</h4>
<p>To create a new test run <code>test/ADD-test-new.sh</code> and answer the questions, it will create the usually needed files and dirs:</p>
<p>Each test consists of a script script named after <code>p-name-test.sh</code> <em>(where p is test pass a-z and name the name of your test)</em> and an optional dir <code>p-name-test/</code> <em>(script name minus .sh)</em> for additional files.</p>
<p>Tests with no dependency to other tests will run in pass a, tests which need an initialized bahsbot environment must run in pass d or later. A temporary test environment is created when ALL-tests.sh starts and deleted after all tests are finished.</p>
<p>The file <code>ALL-tests.inc.sh</code> must be included from all tests and provide the test environment as shell variables:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># Test Evironment</span>
<span class="va">TESTME=</span><span class="st">&quot;</span><span class="va">$(</span><span class="fu">basename</span> <span class="st">&quot;</span><span class="va">$0</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span>
<span class="va">DIRME=</span><span class="st">&quot;</span><span class="va">$(</span><span class="bu">pwd</span><span class="va">)</span><span class="st">&quot;</span>
<span class="va">TESTDIR=</span><span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span>
<span class="va">LOGFILE=</span><span class="st">&quot;</span><span class="va">${TESTDIR}</span><span class="st">/</span><span class="va">${TESTME}</span><span class="st">.log&quot;</span>
<span class="va">REFDIR=</span><span class="st">&quot;</span><span class="va">${TESTME%</span>.sh<span class="va">}</span><span class="st">&quot;</span>
<span class="va">TESTNAME=</span><span class="st">&quot;</span><span class="va">${REFDIR//</span>-<span class="va">/</span> <span class="va">}</span><span class="st">&quot;</span>
<span class="co"># common filenames</span>
<span class="va">TOKENFILE=</span><span class="st">&quot;token&quot;</span>
<span class="va">ACLFILE=</span><span class="st">&quot;botacl&quot;</span>
<span class="va">COUNTFILE=</span><span class="st">&quot;count&quot;</span>
<span class="va">ADMINFILE=</span><span class="st">&quot;botadmin&quot;</span>
<span class="va">DATADIR=</span><span class="st">&quot;data-bot-bash&quot;</span>
<span class="co"># SUCCESS NOSUCCES -&gt; echo &quot;${SUCCESS}&quot; or echo &quot;${NOSUCCESS}&quot; </span>
<span class="va">SUCCESS=</span><span class="st">&quot; OK&quot;</span>
<span class="va">NOSUCCESS=</span><span class="st">&quot; FAILED!&quot;</span>
<span class="co"># default input, reference and output files</span>
<span class="va">INPUTFILE=</span><span class="st">&quot;</span><span class="va">${DIRME}</span><span class="st">/</span><span class="va">${REFDIR}</span><span class="st">/</span><span class="va">${REFDIR}</span><span class="st">.input&quot;</span>
<span class="va">REFFILE=</span><span class="st">&quot;</span><span class="va">${DIRME}</span><span class="st">/</span><span class="va">${REFDIR}</span><span class="st">/</span><span class="va">${REFDIR}</span><span class="st">.result&quot;</span>
<span class="va">OUTPUTFILE=</span><span class="st">&quot;</span><span class="va">${TESTDIR}</span><span class="st">/</span><span class="va">${REFDIR}</span><span class="st">.out&quot;</span></code></pre></div>
<p>Example test</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co">#!/usr/bin/env bash</span>
<span class="co"># file: b-example-test.sh</span>
<span class="co"># include common functions and definitions</span>
<span class="co"># shellcheck source=test/ALL-tests.inc.sh</span>
<span class="bu">source</span> <span class="st">&quot;./ALL-tests.inc.sh&quot;</span>
<span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> <span class="st">&quot;</span><span class="va">${TESTDIR}</span><span class="st">/bashbot.sh&quot;</span><span class="bu"> ]</span>; <span class="kw">then</span>
<span class="bu">echo</span> <span class="st">&quot;</span><span class="va">${SUCCESS}</span><span class="st"> bashbot.sh exist!&quot;</span>
<span class="bu">exit</span> 0
<span class="kw">else</span>
<span class="bu">echo</span> <span class="st">&quot;</span><span class="va">${NOSUCCESS}</span><span class="st"> </span><span class="va">${TESTDIR}</span><span class="st">/bashbot.sh missing!&quot;</span>
<span class="bu">exit</span> 1
<span class="kw">fi</span></code></pre></div>
<h4 id="prev-function-reference"><a href="6_reference.html">Prev Function Reference</a></h4>
<h4 id="next-expert-use"><a href="8_custom.html">Next Expert Use</a></h4>
<h4 id="version-v0.90-dev2-19-g5779acc"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-19-g5779acc</h4>
</body>
</html>

View File

@ -0,0 +1,195 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title>Bashbot README</title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<div id="header">
<h1 class="title">Bashbot README</h1>
</div>
<h2>
<img align="middle" src="https://raw.githubusercontent.com/odb/official-bash-logo/master/assets/Logos/Icons/PNG/64x64.png" > Bashbot - A Telegram bot written in bash.
</h2>
<p>Written by Drew (<span class="citation">@topkecleon</span>), Daniil Gentili (<span class="citation">@danogentili</span>), and Kay M (<span class="citation">@gnadelwartz</span>).</p>
<p>Contributions by JuanPotato, BigNerd95, TiagoDanin, and iicc1.</p>
<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>
<h2 id="prerequisites">Prerequisites</h2>
<p>Uses <a href="http://github.com/dominictarr/JSON.sh">JSON.sh</a>, but no more TMUX.</p>
<p>Even bashbot is written in bash, it depends on commands typically availible in a Unix/Linux Environment. More concret on the common commands provided by <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="html/7_develop.html">Developer Notes</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 availible on www.github.com</p>
<h2 id="documentation">Documentation</h2>
<ul>
<li><a href="https://core.telegram.org/bots">Introdution to Telegram Bots</a>
<ul>
<li><a href="https://core.telegram.org/bots#3-how-do-i-create-a-bot">One Bot to rule them all</a></li>
<li><a href="https://core.telegram.org/bots#commands">Bot commands</a></li>
</ul></li>
<li><a href="html/0_install.html">Install Bashbot</a>
<ul>
<li>Install release</li>
<li>Install from githup</li>
<li>Update Bashbot</li>
<li>Notes on Updates</li>
</ul></li>
<li><a href="html/1_firstbot.html">Create a new Telegram Bot with botfather</a></li>
<li><a href="html/2_usage.html">Getting Started</a>
<ul>
<li>Managing your Bot</li>
<li>Recieve data</li>
<li>Send messages</li>
<li>Send files, locations, keyboards</li>
</ul></li>
<li><a href="html/3_advanced.html">Advanced Features</a>
<ul>
<li>Access Control</li>
<li>Interactive Chats</li>
<li>Background Jobs</li>
<li>Inline queries</li>
</ul></li>
<li><a href="html/4_expert.html">Expert Use</a>
<ul>
<li>Handling UTF-8 character sets</li>
<li>Run as other user or system service</li>
<li>Scedule bashbot from Cron</li>
<li>Use from CLI and Scripts</li>
<li>Customize Bashbot Environment</li>
</ul></li>
<li><a href="html/5_practice.html">Best Practices</a>
<ul>
<li>Customize commands.sh</li>
<li>Seperate logic from commands</li>
<li>Test your Bot with shellcheck</li>
</ul></li>
<li><a href="html/6_reference.html">Function Reference</a>
<ul>
<li>Sending Messages, Files, Keyboards</li>
<li>User Access Control</li>
<li>Inline Queries</li>
<li>Background and Interactive Jobs</li>
</ul></li>
<li><a href="html/7_develop.html">Deveoper Notess</a>
<ul>
<li>Debug bashbot</li>
<li>Modules, addons, events</li>
<li>Setup your environment</li>
<li>Bashbot testsuite</li>
</ul></li>
<li><a href="examples/README.html">Examples Dir</a></li>
</ul>
<h3 id="your-really-first-bashbot-in-a-nutshell">Your really first bashbot in a nutshell</h3>
<p>To install and run bashbot you need acess to a linux/unix/bsd command line. If you dont know how to get accces to a linux/unix/bsd like command line you should stop reading here :-(</p>
<p>In addition you need a <a href="https://telegram.org">Telegram client</a> and a mobile phone to <a href="https://telegramguide.com/create-a-telegram-account/">register an account</a>. If you dont want to register for Telegram you should stop reading here ;-)</p>
<p>After youre registered to Telegram send a message to <span class="citation">[@botfather]</span>(https://telegram.me/botfather), <a href="html/1_firstbot.html">create a new Telegram Bot token</a> and write it down. You need the token to install the bot.</p>
<p>Now open a linux/unix/bsd terminal and check if bash is installed: <code>which bash &amp;&amp; echo &quot;bash installed!&quot;</code>. If you get an error message bash is not installed.</p>
<p>Create a new directory and change to it: <code>mkdir tbb; cd tbb</code> and download the latest *.tar.gz file from <a href="https://github.com/topkecleon/telegram-bot-bash/releases" class="uri">https://github.com/topkecleon/telegram-bot-bash/releases</a>. This can be done with the commands:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="fu">wget</span> -q https://github.com/<span class="va">$(</span><span class="fu">wget</span> -q https://github.com/topkecleon/telegram-bot-bash/releases/latest -O - <span class="kw">|</span> <span class="fu">egrep</span> <span class="st">&#39;/.*/.*/.*tar.gz&#39;</span> -o<span class="va">)</span></code></pre></div>
<p>Extract the *.tar.gz file and change to bashbot directory: <code>tar -xzf *.tar.gz; cd telegram-bot-bash</code>, install bashbot: <code>./bashbot.sh init</code> and enter your bot token when asked. All other questions can be answered by hitting the &lt;Return&gt; key.</p>
<p>Thats all, now you can start your bot with <code>./bashbot.sh start</code> and send him messages:</p>
<pre><code>/start
You are Botadmin
*Available commands*:
*• /start*: _Start bot and get this message_.
*• /help*: _Get this message_.
*• /info*: _Get shorter info message about this bot_....
/info
his is bashbot, the Telegram bot written entirely in bash.
It features background tasks and interactive chats, and can serve as an interface for CLI programs.</code></pre>
<p>For more Information on how to install, customize and use your new bot, read the <a href="#Documentation">Documentation</a></p>
<hr />
<h2 id="security-considerations">Security Considerations</h2>
<p>Running a Telegram Bot means it is connected to the public and you never know whats send to your Bot.</p>
<p>Bash scripts in general are not designed to be bullet proof, 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 from untrusted sources (messages, files, network) you must be as carefull as possible, e.g. set IFS appropriate, disable globbing (set -f) and quote everthing. In addition delete unused scripts and examples from your Bot, e.g. scripts notify, calc, question, and disable all not used commands.</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 extensive in bashbot development to enshure a high code quality, e.g. its not allowed to push changes without passing all shellcheck tests. In addition bashbot has a <a href="html/7_develop.html">test suite</a> to check if important functionality is working as expected.</p>
<h3 id="run-your-bot-as-a-restricted-user">Run your Bot as a restricted user</h3>
<p><strong>I recommend to run your bot as a user, with almost no access rights.</strong> All files your Bot have write access to are in danger to be overwritten/deleted if your bot is hacked. For the same reason ervery file your Bot can read is in danger to be disclosed. Restict your Bots access rigths to the absolute minimum.</p>
<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 Unix/Linux systems. See <a href="html/4_expert.html">Expert use</a> on how to run your Bot as an other user.</p>
<h3 id="secure-your-bot-installation">Secure your Bot installation</h3>
<p><strong>Your Bot configuration must no be readable from other users.</strong> Everyone who can read your Bots token can act as your Bot and has access to all chats your Bot is in!</p>
<p>Everyone with read access to your Bot files can extract your Bots data. Especially your Bot Token in <code>token</code> must be protected against other users. No one exept you must have write access to the Bot files. The Bot must be restricted to have write access to <code>count</code> and <code>tmp-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>
<h2 id="faq">FAQ</h2>
<h3 id="is-this-bot-insecure">Is this Bot insecure?</h3>
<p>Bashbot is not more (in)secure as any other Bot written in any other 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>
<h3 id="why-bash-and-not-the-much-better-xyz">Why Bash and not the much better xyz?</h3>
<p>Well, thats a damn good question … may be because Im an Unix/Linux admin from stone age. Nevertheless there are more reasons from my side:</p>
<ul>
<li>bashbot will run everywhere where bash is availible, from ebedded linux to mainframe</li>
<li>easy to integrate with other shell script, e.g. for sending system message / health status</li>
<li>no need to install or learn a new programming language, library or framework</li>
<li>no database, not event driven, not OO …</li>
</ul>
<h3 id="can-i-have-the-single-bashbot.sh-file-back">Can I have the single bashbot.sh file back?</h3>
<p>At the beginning bashbot was simply the file <code>bashbot.sh</code> you can 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="html/7_develop.html">Create a stripped down Version of your Bot</a></p>
<h3 id="can-i-send-messages-from-cli-and-scripts">Can I send messages from CLI and scripts?</h3>
<p>Of course, you can send messages from CLI and scripts, simply install bashbot as <a href="#Your-really-first-bashbot-in-a-nutshell">described here</a>, send the messsage /start to set yourself as botadmin and stop the bot with <code>./bashbot.sh kill</code>.</p>
<p>Run the following commands in your bash shell or script while you are in the installation directory:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co"># prepare bash / script to send commands</span>
<span class="bu">export</span> <span class="va">BASHBOT_HOME=</span><span class="st">&quot;</span><span class="va">$(</span><span class="bu">pwd</span><span class="va">)</span><span class="st">&quot;</span>
<span class="bu">source</span> ./bashbot.sh source
<span class="co"># send me a test message</span>
<span class="ex">send_message</span> <span class="st">&quot;</span><span class="va">$(</span><span class="fu">cat</span> <span class="st">&quot;</span><span class="va">$BOTADMIN</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span> <span class="st">&quot;test&quot;</span>
<span class="co"># send me output of a system command</span>
<span class="ex">send_message</span> <span class="st">&quot;</span><span class="op">$(&lt;</span><span class="st">&quot;</span><span class="va">$BOTADMIN</span><span class="st">&quot;</span><span class="op">)</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$(</span><span class="fu">df</span> -h<span class="va">)</span><span class="st">&quot;</span></code></pre></div>
<p>For more information see <a href="html/8_custom.html">Expert Use</a></p>
<h3 id="why-do-i-get-expected-value-got-eof-on-start">Why do I get “EXPECTED value GOT EOF” on start?</h3>
<p>May be your IP is blocked by telegram. You can test this by running curl or wget manually:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="ex">curl</span> -m 10 https://api.telegram.org/bot
<span class="co">#curl: (28) Connection timed out after 10001 milliseconds</span>
<span class="fu">wget</span> -t 1 -T 10 https://api.telegram.org/bot
<span class="co">#Connecting to api.telegram.org (api.telegram.org)|46.38.243.234|:443... failed: Connection timed out.</span></code></pre></div>
<p>This may happen if to many wrong requests are sent to api.telegram.org, e.g. using a wrong token or not existing API calls. If you have a fixed IP you can ask telegram service to unblock your ip or change your IP. If you are running a tor proxy on your server you may uncomment the <code>BASHBOT_CURL_ARGS</code> line in mycommands.sh</p>
<p><span class="citation">@Gnadelwartz</span></p>
<h2 id="thats-it">Thats it!</h2>
<p>If you feel that theres something missing or if you found a bug, feel free to submit a pull request!</p>
<h4 id="version-v0.90-dev2-19-g5779acc"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.90-dev2-19-g5779acc</h4>
</body>
</html>

View File

@ -0,0 +1,62 @@
#!/bin/bash
# file: modules/alaises.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$$ v0.90-dev2-0-gec85636
#
# source from commands.sh to use the aliases
# easy handling of users:
_is_botadmin() {
user_is_botadmin "${USER[ID]}"
}
_is_admin() {
user_is_admin "${CHAT[ID]}" "${USER[ID]}"
}
_is_creator() {
user_is_creator "${CHAT[ID]}" "${USER[ID]}"
}
_is_allowed() {
user_is_allowed "${USER[ID]}" "${1}" "${CHAT[ID]}"
}
_leave() {
leave_chat "${CHAT[ID]}"
}
_kick_user() {
kick_chat_member "${CHAT[ID]}" "${1}"
}
_unban_user() {
unban_chat_member "${CHAT[ID]}" "${1}"
}
# easy sending of messages of messages
_message() {
send_normal_message "${CHAT[ID]}" "${1}"
}
_normal_message() {
send_normal_message "${CHAT[ID]}" "${1}"
}
_html_message() {
send_html_message "${CHAT[ID]}" "${1}"
}
_markdown_message() {
send_markdown_message "${CHAT[ID]}" "${1}"
}
# easy handling of keyboards
_inline_button() {
send_inline_button "${CHAT[ID]}" "" "${1}" "${2}"
}
_inline_keyboard() {
send_inline_keyboard "${CHAT[ID]}" "" "${1}"
}
_keyboard_numpad() {
send_keyboard "${CHAT[ID]}" "" '["1","2","3"],["4","5","6"],["7","8","9"],["-","0","."]' "yes"
}
_keyboard_yesno() {
send_keyboard "${CHAT[ID]}" "" '["yes","no"]'
}
_del_keyboard() {
remove_keyboard "${CHAT[ID]}" ""
}

View File

@ -0,0 +1,102 @@
#!/bin/bash
# file: modules/inline.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$$ v0.90-dev2-13-gcb3f3e3
# source from commands.sh to use the inline functions
INLINE_QUERY=$URL'/answerInlineQuery'
answer_inline_query() {
answer_inline_multi "${1}" "$(shift; inline_query_compose "$RANDOM" "$@")"
}
answer_inline_multi() {
sendJson "" '"inline_query_id": '"${1}"', "results": ['"${2}"']' "${INLINE_QUERY}"
}
# $1 unique ID for answer
# $2 type of answer
# remaining arguments are the "must have" arguments in the order as in telegram doc
# followed by the optional arguments: https://core.telegram.org/bots/api#inlinequeryresult
inline_query_compose(){
local JSON="{}"
local ID="${1}"
local fours last
# title2Json title caption description markup inlinekeyboard
case "${2}" in
# user provided media
"article"|"message") # article ID title message (markup decription)
JSON='{"type":"article","id":"'$ID'","input_message_content": {"message_text":"'$4'"} '$(title2Json "$3" "" "$5" "$6")'}'
;;
"photo") # photo ID photoURL (thumbURL title description caption)
[ "$4" = "" ] && tumb="$3"
JSON='{"type":"photo","id":"'$ID'","photo_url":"'$3'","thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$7" "$6")'}'
;;
"gif") # gif ID photoURL (thumbURL title caption)
[ "$4" = "" ] && tumb="$3"
JSON='{"type":"gif","id":"'$ID'","gif_url":"'$3'", "thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$6")'}'
;;
"mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption)
[ "$4" != "" ] && tumb='","thumb_url":"'$4'"'
JSON='{"type":"mpeg4_gif","id":"'$ID'","mpeg4_url":"'$3'"'${tumb}$(title2Json "$5" "$6")'}'
;;
"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")'}'
;;
"audio") # audio ID audioURL title (caption)
JSON='{"type":"audio","id":"'$ID'","audio_url":"'$3'"'$(title2Json "$4" "$5")'}'
;;
"voice") # voice ID voiceURL title (caption)
JSON='{"type":"voice","id":"'$ID'","voice_url":"'$3'"'$(title2Json "$4" "$5")'}'
;;
"document") # document ID title documentURL mimetype (caption description)
JSON='{"type":"document","id":"'$ID'","document_url":"'$4'","mime_type":"'$5'"'$(title2Json "$3" "$6" "$7")'}'
;;
"location") # location ID lat long title
JSON='{"type":"location","id":"'$ID'","latitude":"'$3'","longitude":"'$4'","title":"'$5'"}'
;;
"venue") # venue ID lat long title (adress forsquare)
[ "$6" = "" ] && addr="$5"
[ "$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)
[ "$5" != "" ] && last=',"last_name":"'$5'"'
[ "$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)
JSON='{"type":"photo","id":"'$ID'","photo_file_id":"'$3'"'$(title2Json "$4" "$6" "$5")'}'
;;
"cached_gif") # gif ID file (title caption)
JSON='{"type":"gif","id":"'$ID'","gif_file_id":"'$3'"'$(title2Json "$4" "$5")'}'
;;
"cached_mpeg4_gif") # mpeg ID file (title caption)
JSON='{"type":"mpeg4_gif","id":"'$ID'","mpeg4_file_id":"'$3'"'$(title2Json "$4" "$5")'}'
;;
"cached_sticker") # sticker ID file
JSON='{"type":"sticker","id":"'$ID'","sticker_file_id":"'$3'"}'
;;
"cached_document") # document ID title file (description caption)
JSON='{"type":"document","id":"'$ID'","document_file_id":"'$4'"'$(title2Json "$3" "$6" "$5")'}'
;;
"cached_video") # video ID file title (description caption)
JSON='{"type":"video","id":"'$ID'","video_file_id":"'$3'"'$(title2Json "$4" "$6" "$5")'}'
;;
"cached_voice") # voice ID file title (caption)
JSON='{"type":"voice","id":"'$ID'","voice_file_id":"'$3'"'$(title2Json "$4" "$5")'}'
;;
"cached_audio") # audio ID file title (caption)
JSON='{"type":"audio","id":"'$ID'","audio_file_id":"'$3'"'$(title2Json "$4" "$5")'}'
;;
esac
printf '%s\n' "${JSON}"
}

View File

@ -0,0 +1,142 @@
#!/bin/bash
# file: modules/background.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$$ v0.90-dev2-11-g59aa9fc
# source from commands.sh if you want ro use interactive or background jobs
######
# interactive and background functions
# old syntax as aliases
background() {
start_back "${CHAT[ID]}" "$1" "$2"
}
startproc() {
start_proc "${CHAT[ID]}" "$1" "$2"
}
checkback() {
check_back "${CHAT[ID]}" "$1"
}
checkproc() {
check_proc "${CHAT[ID]}" "$1"
}
killback() {
kill_back "${CHAT[ID]}" "$1"
}
killproc() {
kill_proc "${CHAT[ID]}" "$1"
}
# inline and backgound functions
# $1 chatid
# $2 program
# $3 jobname
start_back() {
local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
printf '%s\n' "$1:$3:$2" >"${fifo}$3-back.cmd"
start_proc "$1" "$2" "back-$3-"
}
# $1 chatid
# $2 program
# $3 prefix
start_proc() {
[ "$2" = "" ] && return
[ -x "${2%% *}" ] || return 1
local fifo; fifo="${DATADIR:-.}/$(procname "$1" "$3")"
kill_proc "$1" "$3"
mkfifo "${fifo}"
nohup bash -c "{ tail -f < \"${fifo}\" | $2 \"\" \"\" \"$fifo\" | \"${SCRIPT}\" outproc \"${1}\" \"${fifo}\"
rm \"${fifo}\"; [ -s \"${fifo}.log\" ] || rm -f \"${fifo}.log\"; }" &>>"${fifo}.log" &
}
# $1 chatid
# $2 jobname
check_back() {
check_proc "$1" "back-$2-"
}
# $1 chatid
# $2 prefix
check_proc() {
[ "$(proclist "$(procname "$1" "$2")")" != "" ]
# shellcheck disable=SC2034
res=$?; return $?
}
# $1 chatid
# $2 jobname
kill_back() {
kill_proc "$1" "back-$2-"
rm -f "${DATADIR:-.}/$(procname "$1")$2-back.cmd"
}
# $1 chatid
# $2 prefix
kill_proc() {
local fifo prid
fifo="$(procname "$1" "$2")"
prid="$(proclist "${fifo}")"
fifo="${DATADIR:-.}/${fifo}"
# shellcheck disable=SC2086
[ "${prid}" != "" ] && kill ${prid}
[ -s "${fifo}.log" ] || rm -f "${fifo}.log"
[ -p "${fifo}" ] && rm -f "${fifo}";
}
# $1 chat
# $2 message
send_interactive() {
local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
[ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking!
}
# old style but may not work because of local checks
inproc() {
send_interactive "${CHAT[ID]}" "${MESSAGE}"
}
# start stopp all jobs
# $1 command
# killb*
# suspendb*
# resumeb*
job_control() {
local content proc CHAT job fifo killall=""
for FILE in "${DATADIR:-.}/"*-back.cmd; do
[ "${FILE}" = "${DATADIR:-.}/*-back.cmd" ] && echo -e "${RED}No background processes.${NC}" && break
content="$(< "${FILE}")"
CHAT="${content%%:*}"
job="${content#*:}"
proc="${job#*:}"
job="back-${job%:*}-"
fifo="$(procname "${CHAT}" "${job}")"
case "$1" in
"resumeb"*|"backgr"*)
echo "Restart Job: ${proc} ${fifo}"
start_proc "${CHAT}" "${proc}" "${job}"
;;
"suspendb"*)
echo "Suspend Job: ${proc} ${fifo}"
kill_proc "${CHAT}" "${job}"
killall="y"
;;
"killb"*)
echo "Kill Job: ${proc} ${fifo}"
kill_proc "${CHAT}" "${job}"
rm -f "${FILE}" # remove job
killall="y"
;;
esac
done
# kill all requestet. kill ALL background jobs, even not listed in data-bot-bash
[ "${killall}" = "y" ] && killallproc "back-"
}

View File

@ -0,0 +1,63 @@
#!/bin/bash
# file: modules/chatMember.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$$ v0.90-dev2-13-gcb3f3e3
# source from commands.sh to use the member functions
LEAVE_URL=$URL'/leaveChat'
KICK_URL=$URL'/kickChatMember'
UNBAN_URL=$URL'/unbanChatMember'
GETMEMBER_URL=$URL'/getChatMember'
# usage: status="$(get_chat_member_status "chat" "user")"
get_chat_member_status() {
sendJson "$1" 'user_id: '"$2"'' "$GETMEMBER_URL"
# shellcheck disable=SC2154
JsonGetString '"result","status"' <<< "$res"
}
kick_chat_member() {
sendJson "$1" 'user_id: '"$2"'' "$KICK_URL"
}
unban_chat_member() {
sendJson "$1" 'user_id: '"$2"'' "$UNBAN_URL"
}
leave_chat() {
sendJson "$1" "" "$LEAVE_URL"
}
user_is_creator() {
if [ "${1:--}" = "${2:-+}" ] || [ "$(get_chat_member_status "$1" "$2")" = "creator" ]; then return 0; fi
return 1
}
user_is_admin() {
local me; me="$(get_chat_member_status "$1" "$2")"
if [ "${me}" = "creator" ] || [ "${me}" = "administrator" ]; then return 0; fi
return 1
}
user_is_botadmin() {
local admin; admin="$(head -n 1 "${BOTADMIN}")"
[ "${admin}" = "${1}" ] && return 0
[[ "${admin}" = "@*" ]] && [[ "${admin}" = "${2}" ]] && return 0
if [ "${admin}" = "?" ]; then printf '%s\n' "${1:-?}" >"${BOTADMIN}"; return 0; fi
return 1
}
user_is_allowed() {
local acl="$1"
[ "$1" = "" ] && return 1
grep -F -xq "${acl}:*:*" <"${BOTACL}" && return 0
[ "$2" != "" ] && acl="${acl}:$2"
grep -F -xq "${acl}:*" <"${BOTACL}" && return 0
[ "$3" != "" ] && acl="${acl}:$3"
grep -F -xq "${acl}" <"${BOTACL}"
}

View File

@ -0,0 +1,44 @@
#!/bin/bash
# file: modules/jsshDB.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$$ v0.90-dev2-9-gbbbc8ae
#
# source from commands.sh to use jsonDB functions
#
# jsonDB rovides simple functions to read and store bash Arrays
# from to file in JSON.sh output format
# read content of a file in JSON.sh format into given ARRAY
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
# $2 filename, must be relative to BASHBOT_ETC, and not contain '..'
jssh_readDB() {
local DB="${BASHBOT_ETC:-.}/$2.jssh"
[ "$2" = "" ] && return 1
[[ "$2" = *'..'* ]] && return 1
[ ! -f "${DB}" ] && return 1
Json2Array "$1" <"${DB}"
}
# write ARRAY content to a file in JSON.sh format
# $1 ARRAY name, must be delared with "declare -A ARRAY" upfront
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_writeDB() {
local DB="${BASHBOT_ETC:-.}/$2.jssh"
[ "$2" = "" ] && return 1
[[ "$2" = *'..'* ]] && return 1
[ ! -f "${DB}" ] && return 1
Array2Json "$1" >"${DB}"
}
# $1 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
jssh_newDB() {
local DB="${BASHBOT_ETC:-.}/$1.jssh"
[ "$1" = "" ] && return 1
[[ "$2" = *'..'* ]] && return 1
[ -f "${DB}" ] && return 1 # already exist, do not zero out
printf '\n' >"${DB}"
}

View File

@ -0,0 +1,237 @@
#!/bin/bash
# file: modules/message.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$$ v0.90-dev2-13-gcb3f3e3
# source from commands.sh to use the sendMessage functions
MSG_URL=$URL'/sendMessage'
PHO_URL=$URL'/sendPhoto'
AUDIO_URL=$URL'/sendAudio'
DOCUMENT_URL=$URL'/sendDocument'
STICKER_URL=$URL'/sendSticker'
VIDEO_URL=$URL'/sendVideo'
VOICE_URL=$URL'/sendVoice'
LOCATION_URL=$URL'/sendLocation'
VENUE_URL=$URL'/sendVenue'
ACTION_URL=$URL'/sendChatAction'
FORWARD_URL=$URL'/forwardMessage'
send_normal_message() {
local text="${2}"
until [ -z "${text}" ]; do
sendJson "${1}" '"text":"'"${text:0:4096}"'"' "${MSG_URL}"
text="${text:4096}"
done
}
send_markdown_message() {
local text="${2}"
until [ -z "${text}" ]; do
sendJson "${1}" '"text":"'"${text:0:4096}"'","parse_mode":"markdown"' "${MSG_URL}"
text="${text:4096}"
done
}
send_html_message() {
local text="${2}"
until [ -z "${text}" ]; do
sendJson "${1}" '"text":"'"${text:0:4096}"'","parse_mode":"html"' "${MSG_URL}"
text="${text:4096}"
done
}
old_send_keyboard() {
local text='"text":"'"${2}"'"'
shift 2
local keyboard="init"
OLDIFS="$IFS"
IFS="\""
for f in "$@" ;do [ "$f" != " " ] && keyboard="$keyboard, [\"$f\"]";done
IFS="$OLDIFS"
keyboard="${keyboard/init, /}"
sendJson "${1}" "${text}"', "reply_markup": {"keyboard": [ '"${keyboard}"' ],"one_time_keyboard": true}' "$MSG_URL"
}
ISEMPTY="ThisTextIsEmptyAndWillBeDeleted"
sendEmpty() {
sendJson "${@}"
[[ "${2}" = *"${ISEMPTY}"* ]] && delete_message "${1}" "${BOTSENT[ID]}"
}
send_keyboard() {
if [[ "$3" != *'['* ]]; then old_send_keyboard "${@}"; return; fi
local text='"text":"'"${2}"'"'; [ "${2}" = "" ] && text='"text":"'"${ISEMPTY}"'"'
local one_time=', "one_time_keyboard":true' && [ "$4" != "" ] && one_time=""
sendEmpty "${1}" "${text}"', "reply_markup": {"keyboard": [ '"${3}"' ] '"${one_time}"'}' "$MSG_URL"
# '"text":"$2", "reply_markup": {"keyboard": [ ${3} ], "one_time_keyboard": true}'
}
remove_keyboard() {
local text='"text":"'"${2}"'"'; [ "${2}" = "" ] && text='"text":"'"${ISEMPTY}"'"'
sendEmpty "${1}" "${text}"', "reply_markup": {"remove_keyboard":true}' "$MSG_URL"
#JSON='"text":"$2", "reply_markup": {"remove_keyboard":true}'
}
send_inline_keyboard() {
local text='"text":"'"${2}"'"'; [ "${2}" = "" ] && text='"text":"'"${ISEMPTY}"'"'
sendEmpty "${1}" "${text}"', "reply_markup": {"inline_keyboard": [ '"${3}"' ]}' "$MSG_URL"
# JSON='"text":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}'
}
send_button() {
send_inline_keyboard "${1}" "${2}" '[ {"text":"'"${3}"'", "url":"'"${4}"'"}]'
}
UPLOADDIR="${BASHBOT_UPLOAD:-${DATADIR}/upload}"
# for now this can only send local files with curl!
# extend to allow send files by URL or telegram ID
send_file() {
[ "$2" = "" ] && return
[[ "$2" = "http"* ]] && return # currently we do not support URL
upload_file "${@}"
}
upload_file(){
local CUR_URL WHAT STATUS file="$2"
# file access checks ...
[[ "$file" = *'..'* ]] && return # no directory traversal
[[ "$file" = '.'* ]] && return # no hidden or relative files
if [[ "$file" = '/'* ]] ; then
[[ ! "$file" =~ $FILE_REGEX ]] && return # absulute must match REGEX
else
file="${UPLOADDIR:-NOUPLOADDIR}/${file}" # othiers must be in UPLOADDIR
fi
[ ! -r "$file" ] && return # and file must exits of course
local ext="${file##*.}"
case $ext in
mp3|flac)
CUR_URL="$AUDIO_URL"
WHAT="audio"
STATUS="upload_audio"
;;
png|jpg|jpeg|gif)
CUR_URL="$PHO_URL"
WHAT="photo"
STATUS="upload_photo"
;;
webp)
CUR_URL="$STICKER_URL"
WHAT="sticker"
STATUS="upload_photo"
;;
mp4)
CUR_URL="$VIDEO_URL"
WHAT="video"
STATUS="upload_video"
;;
ogg)
CUR_URL="$VOICE_URL"
WHAT="voice"
STATUS="upload_audio"
;;
*)
CUR_URL="$DOCUMENT_URL"
WHAT="document"
STATUS="upload_document"
;;
esac
send_action "${1}" "$STATUS"
sendUpload "$1" "${WHAT}" "${file}" "${CUR_URL}" "$3"
}
# 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 location
send_action() {
[ "$2" = "" ] && return
sendJson "${1}" '"action": "'"${2}"'"' "$ACTION_URL"
}
send_location() {
[ "$3" = "" ] && return
sendJson "${1}" '"latitude": '"${2}"', "longitude": '"${3}"'' "$LOCATION_URL"
}
send_venue() {
local add=""
[ "$5" = "" ] && return
[ "$6" != "" ] && add=', "foursquare_id": '"$6"''
sendJson "${1}" '"latitude": '"${2}"', "longitude": '"${3}"', "address": "'"${5}"'", "title": "'"${4}"'"'"${add}" "$VENUE_URL"
}
forward_message() {
[ "$3" = "" ] && return
sendJson "${1}" '"from_chat_id": '"${2}"', "message_id": '"${3}"'' "$FORWARD_URL"
}
forward() { # backward compatibility
forward_message "$@" || return
}
send_message() {
[ "$2" = "" ] && return
local text keyboard btext burl no_keyboard file lat long title address sent
text="$(sed <<< "${2}" 's/ mykeyboardend.*//;s/ *my[kfltab][a-z]\{2,13\}startshere.*//')$(sed <<< "${2}" -n '/mytextstartshere/ s/.*mytextstartshere//p')"
text="$(sed <<< "${text}" 's/ *mynewlinestartshere */\r\n/g')"
[ "$3" != "safe" ] && {
no_keyboard="$(sed <<< "${2}" '/mykeyboardendshere/!d;s/.*mykeyboardendshere.*/mykeyboardendshere/')"
keyboard="$(sed <<< "${2}" '/mykeyboardstartshere /!d;s/.*mykeyboardstartshere *//;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
btext="$(sed <<< "${2}" '/mybtextstartshere /!d;s/.*mybtextstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
burl="$(sed <<< "${2}" '/myburlstartshere /!d;s/.*myburlstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//g;s/ *mykeyboardendshere.*//g')"
file="$(sed <<< "${2}" '/myfilelocationstartshere /!d;s/.*myfilelocationstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
lat="$(sed <<< "${2}" '/mylatstartshere /!d;s/.*mylatstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
long="$(sed <<< "${2}" '/mylongstartshere /!d;s/.*mylongstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
title="$(sed <<< "${2}" '/mytitlestartshere /!d;s/.*mytitlestartshere //;s/ *my[kfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
address="$(sed <<< "${2}" '/myaddressstartshere /!d;s/.*myaddressstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
}
if [ "$no_keyboard" != "" ]; then
remove_keyboard "$1" "$text"
sent=y
fi
if [ "$keyboard" != "" ]; then
if [[ "$keyboard" != *"["* ]]; then # pre 0.60 style
keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]"
fi
send_keyboard "$1" "$text" "$keyboard"
sent=y
fi
if [ "$btext" != "" ] && [ "$burl" != "" ]; then
send_button "$1" "$text" "$btext" "$burl"
sent=y
fi
if [ "$file" != "" ]; then
send_file "$1" "$file" "$text"
sent=y
fi
if [ "$lat" != "" ] && [ "$long" != "" ]; then
if [ "$address" != "" ] && [ "$title" != "" ]; then
send_venue "$1" "$lat" "$long" "$title" "$address"
else
send_location "$1" "$lat" "$long"
fi
sent=y
fi
if [ "$sent" != "y" ];then
send_text "$1" "$text"
fi
}
send_text() {
case "$2" in
html_parse_mode*)
send_html_message "$1" "${2//html_parse_mode}"
;;
markdown_parse_mode*)
send_markdown_message "$1" "${2//markdown_parse_mode}"
;;
*)
send_normal_message "$1" "$2"
;;
esac
}

View File

@ -0,0 +1,140 @@
#!/bin/bash
# files: mycommands.sh.dist
# copy to mycommands.sh and add all your commands and functions here ...
#
#### $$VERSION$$ v0.90-dev2-0-gec85636
#
# uncomment the following lines to overwrite info and help messages
# bashbot_info='This is bashbot, the Telegram bot written entirely in bash.
#'
# bashbot_help='*Available commands*:
#'
res=""
# Set INLINE to 1 in order to receive inline queries.
# To enable this option in your bot, send the /setinline command to @BotFather.
export INLINE="0"
# Set to .* to allow sending files from all locations
export FILE_REGEX='/home/user/allowed/.*'
# example: run bashbot over TOR
# export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1:9050"
if [ "$1" != "source" ];then
# your additional bahsbot commands
# NOTE: command can have @botname attached, you must add * in case tests...
mycommands() {
case "${MESSAGE}" in
##################
# example commands, replace thm by your own
'/echo'*) # example echo command
send_normal_message "${CHAT[ID]}" "$MESSAGE"
;;
'/question'*) # start interactive questions
checkproc
if [ "$res" -gt 0 ] ; then
startproc "examples/question.sh" || _message "Can't start question."
else
send_normal_message "${CHAT[ID]}" "$MESSAGE already running ..."
fi
;;
'/run_notify'*) # start notify background job
myback="notify"; checkback "$myback"
if [ "$res" -gt 0 ] ; then
background "examples/notify.sh 60" "$myback" || _message "Can't start notify."
else
send_normal_message "${CHAT[ID]}" "Background command $myback already running ..."
fi
;;
'/stop_notify'*) # kill notify background job
myback="notify"; checkback "$myback"
if [ "$res" -eq 0 ] ; then
killback "$myback"
send_normal_message "${CHAT[ID]}" "Background command $myback canceled."
else
send_normal_message "${CHAT[ID]}" "No background command $myback is currently running.."
fi
;;
##########
# command overwrite examples
'info'*) # output date in front of regular info
send_normal_message "${CHAT[ID]}" "$(date)"
return 0
;;
'/kickme'*) # this will replace the /kickme command
send_markdown_mesage "${CHAT[ID]}" "*This bot will not kick you!*"
return 1
;;
esac
}
myinlines() {
#######################
# Inline query examples, do not use them in production (exept image search ;-)
# shellcheck disable=SC2128
iQUERY="${iQUERY,,}" # all lowercase
case "${iQUERY}" in
"image "*) # search images with yahoo
local search="${iQUERY#* }"
answer_inline_multi "${iQUERY[ID]}" "$(my_image_search "${search}")"
;;
"0"*) # a single message with title
answer_inline_query "${iQUERY[ID]}" "message" "Title of the result" "Content of the message to be sent"
;;
"1"*) # a single photo
answer_inline_query "${iQUERY[ID]}" "photo" "https://avatars.githubusercontent.com/u/13046303" "https://avatars.githubusercontent.com/u/13046303"
;;
"2"*) # two photos
answer_inline_multi "${iQUERY[ID]}" "
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/13046303"),
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/4593242")
"
;;
"3"*) # three photos
answer_inline_multi "${iQUERY[ID]}" "
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/13046303"),
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/4593242")
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/102707")
"
;;
"4") # four photo from array
local sep=""
local avatar=("https://avatars.githubusercontent.com/u/13046303" "https://avatars.githubusercontent.com/u/4593242" "https://avatars.githubusercontent.com/u/102707" "https://avatars.githubusercontent.com/u/6460407")
answer_inline_multi "${iQUERY[ID]}" "
$(for photo in ${avatar[*]} ; do
echo "${sep}"; inline_query_compose "$RANDOM" "photo" "${photo}" "${photo}"; sep=","
done)
"
;;
"sticker") # example chaecd telegram sticker
answer_inline_query "${iQUERY[ID]}" "cached_sticker" "BQADBAAD_QEAAiSFLwABWSYyiuj-g4AC"
;;
"gif") # exmaple chaehed gif
answer_inline_query "${iQUERY[ID]}" "cached_gif" "BQADBAADIwYAAmwsDAABlIia56QGP0YC"
;;
esac
set +x
}
# place your processing functions here
# $1 search parameter
my_image_search(){
local image result sep="" count="1"
result="$(wget --user-agent 'Mozilla/5.0' -qO - "https://images.search.yahoo.com/search/images?p=$1" | sed 's/</\n</g' | grep "<img src=")"
while read -r image; do
[ "$count" -gt "20" ] && break
image="${image#* src=\'}"; image="${image%%&pid=*}"
[[ "${image}" = *"src="* ]] && continue
echo "${sep}"; inline_query_compose "$RANDOM" "photo" "${image}"; sep=","
count=$(( count + 1 ))
done <<<"${result}"
}
fi

View File

@ -52,7 +52,7 @@ Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and [Do
* User Access Control * User Access Control
* Inline Queries * Inline Queries
* Background and Interactive Jobs * Background and Interactive Jobs
* [Deveoper Notess](doc/7_develop.md) * [Deveoper Notes](doc/7_develop.md)
* Debug bashbot * Debug bashbot
* Modules, addons, events * Modules, addons, events
* Setup your environment * Setup your environment

View File

@ -27,7 +27,7 @@ If a module function is called from 'bashbot.sh', bashbot must work if the modul
or '_execute_if_function' if a module function is called. or '_execute_if_function' if a module function is called.
**Addons** live in ```addons/*.sh.dist``` and are disabled by default. To activate an addon remove the '.dist' from filename, e.g. ```cp addons/example.sh.dist addons/example.sh```. Addons must register themself to BASHBOT_EVENTS at startup, e.g. to call a function everytime a message is recieved. **Addons** live in ```addons/*.sh.dist``` and are disabled by default. To activate an addon remove the '.dist' from filename, e.g. ```cp addons/example.sh.dist addons/example.sh```. Addons must register themself to BASHBOT_EVENTS at startup, e.g. to call a function everytime a message is recieved.
Registering to EVENTS is similar on how 'commands.sh' is ececuted, but more flexible and one major difference: Registering to EVENTS is similar on how 'commands.sh' is executed, but more flexible and one major difference:
**Addons are executed in the context of the main script**, while 'commands.sh' is executed as a seperate process. **Addons are executed in the context of the main script**, while 'commands.sh' is executed as a seperate process.
This is why event functions are time critical and must return as fast as possible. Spawn actions as a seperate process or function with '&', e.g. This is why event functions are time critical and must return as fast as possible. Spawn actions as a seperate process or function with '&', e.g.
@ -45,7 +45,7 @@ Availible events:
* BASHBOT_EVENT_INLINE an inline query is received * BASHBOT_EVENT_INLINE an inline query is received
* BASHBOT_EVENT_MESSAGE any type of message is received * BASHBOT_EVENT_MESSAGE any type of message is received
* BASHBOT_EVENT_TEXT a message containing text is received * BASHBOT_EVENT_TEXT a message containing text is recieved
* BASHBOT_EVENT_CMD a command is recieved (fist word starts with /) * BASHBOT_EVENT_CMD a command is recieved (fist word starts with /)
* BASHBOT_EVENT_REPLYTO a reply to a message is received * BASHBOT_EVENT_REPLYTO a reply to a message is received
* BASHBOT_EVENT_FORWARD a forwarded message is received * BASHBOT_EVENT_FORWARD a forwarded message is received
@ -53,31 +53,31 @@ Availible events:
* BASHBOT_EVENT_LOCATION a location or a venue is received * BASHBOT_EVENT_LOCATION a location or a venue is received
* BASHBOT_EVENT_FILE a file is received * BASHBOT_EVENT_FILE a file is received
*usage*: BASHBOT_EVENT_xxx["uniqe-name"]="callback" *usage*: BASHBOT_EVENT_xxx[ "uniqe-name" ]="callback"
"unique-name" can be every alphanumeric string incl. '-' and '_'. Per convention it should be name of the addon followed by an internal identyfier. "unique-name" can be every alphanumeric string incl. '-' and '_'. Per convention it is the name of the addon followed by an internal identyfier.
*Example:* Register a function to echo to any Text send to the bot *Example:* Register a function to echo to any Text send to the bot
```bash ```bash
# register callback: # register callback:
BASHBOT_EVENT_TEXT["example_1"]="example_echo" BASHBOT_EVENT_TEXT["example_1"]="example_echo"
# function called if a text is recieved # function called if a text is received
example_echo() { example_echo() {
# all availible bashbot functions and variables can be used # all availible bashbot functions and variables can be used
send_normal_message "${CHAT[ID]}" "${MESSAGE[0]}" & # note the &! send_normal_message "${CHAT[ID]}" "${MESSAGE[0]}" & # note the &!
} }
``` ```
* BAHSBOT_EVENT_TIMER is executed every minute and can be uses in variants: oneshot, every minute, every X minutes. * BAHSBOT_EVENT_TIMER is executed every minute and can be used in 3 variants: oneshot, every minute, every X minutes.
Registering to BASHBOT_EVENT_TIMER works a little different, you have to add a timing argument to the index name. Registering to BASHBOT_EVENT_TIMER works isimilar as for message events, but you must add a timing argument to the index name.
*usage: * BAHSBOT_EVENT_TIMER["name","time"], where time is: *usage:* BAHSBOT_EVENT_TIMER[ "name" , "time" ], where time is:
* -x execute ONCE in x minutes * -x execute ONCE in x minutes
* 0 ignored * 0 ignored
* 1 execute every minute * 1 execute every minute
* x execute every x minutes * x execute every x minutes
*Examples:* *Examples:*
```bash ```bash