Hier habe beschrieben, wie ich mit einem Telegram Bot (im folgenden nur Bot) Messages mit Hilfe von Textdateien auf meinem Pi austausche.
Es können also Textdateien angelegt werden, die vom Pi ausgelesen werden und dann wird eine Message in den Chat mit dem Bot gestellt. Diese Richtung habe ich Outbound genannt.
Wird im Chat eine Antwort an den Bot gesendet, so kann diese Antwort als Textdatei abgelegt werden. Diese Richtung habe ich Inbound genannt.
Om folgenden wird vorausgesetzt, dass ein Bot bereits eingerichtet wurde und dass die Chat-ID des Chats mit dem Bot genauso bekannt ist wie der Token zum Bot.
Inbound (eine Nachricht wird im Chat an den Bot gesendet):
Als erstes habe ich mir zunächst ein Verzeichnis /home/pi/telegram angelegt. Hier werden alle Messages als Textdateien abgelegt, die im Chat an den Bot gesendet werden.
Danach habe ich mir dann ein Python-Script gebaut, das mittels telepot den Chat "beobachtet" und Messages, die an den Bot gehen, auslesen kann. Nach dem Auslesen werden die Messages als Textdatei gespeichert. In dem Python-Script ist der Token abzuspeichern.
Das Python-Script habe ich als Attachement angehngt und sieht so aus:
#coder
# https://www.hackster.io/Salmanfarisvp/telegram-bot-with-raspberry-pi-f373da
import sys
import time
import telepot
import os
from pathlib import Path
def handle(msg):
chat_id = msg['chat']['id']
command = msg['text']
# print 'Got command from chat: %s' % command
if command == 'ping':
bot.sendMessage(chat_id, 'ping ist angekommen.')
os.system("/home/pi/message2action/telegram/telegramparser.sh message_from_chat " + str(chat_id) + " \"" + command + "\"")
bot = telepot.Bot('397796956:AAGxGlaePKbUV_fWZFG2RT9u6MhWRPxLwpk')
bot.message_loop(handle)
print 'I am listening...'
stopfile = Path("/home/pi/TelegramBot/stopfile")
if stopfile.is_file():
os.remove("/home/pi/TelegramBot/stopfile")
print 'stopfile was deleted.'
while 1:
stopfile = Path("/home/pi/TelegramBot/stopfile")
if stopfile.is_file():
# print "Stopdatei ist vorhanden."
break
# else:
# print "Stopdatei ist nicht vorhanden."
time.sleep(2)
Alles anzeigen
In dem Python-script wird ein Parser aufgerufen, der einen eindeutigen Dateinamen für die Textdatei erzeugt. Der Parser sieht dann so aus:
#!/bin/bash
# Parserscript for creating text files when Telegram messages are received, date: 10.06.2017
FilenameUniqueId=$(date +"%Y%m%d_%H%M%S_%N")
OutputFileText="/home/pi/telegram/"$FilenameUniqueId".txt"
echo "Name: "$1 > $OutputFileText
echo "ID: "$2 >> $OutputFileText
echo "Message: "$3 >> $OutputFileText
chmod a+wr $OutputFileText
Alles anzeigen
In der Praxis sieht das nun wie folgt aus. Hier ein Screenshot des Telegram-Clients auf meinem Windows-PC (den Namen des Bot habe ich verdeckt):
Und hier die Textdatei, die auf dem Pi dazu angelegt wurde (die Chat-ID habe ich verfälscht):
Damit nun auch beim Starten des Pi das Ablegen der Textdateien automatisch erfolgt, habe ich mir eine Service-Datei für systemd angelegt, diese sieht so aus:
[Unit]
Description=Telegram Bot, receiving messages from a Telegram bot
[Service]
User=pi
Group=pi
Type=simple
# We should wait some seconds to get all operating-system related services ready:
ExecStartPre=/bin/sleep 15
#we start with python skript for processing incoming Telegram messages:
ExecStart=/usr/bin/python /home/pi/telegrambot.py
ExecStop=/usr/bin/touch /home/pi/TelegramBot/stopfile
[Install]
WantedBy=multi-user.target
Alles anzeigen
Es hat sich herausgestellt, dass (leider) eine gewisse Wartezeit nach dem Start des Pi bis zum eigentlichen Start des Pollings vergehen muss, damit telepot eine saubere Verbindung zum Telegram-Server aufbauen kann. Diese Wartezeit ist mit ExecStartPre=15 angegeben. Vielleicht kann man diese auch verkürzen, aber ich habe keine Lust, das Herauszufummeln.
Outbound (Versand vom Pi aus an den Chat des Bots):
Will man nun eine Message vom Pi aus in den Chat mit dem Bot stellen, geht das bei mir wie folgt. Zunächst wird ein Unterverzeichnis angelegt, um die Textdatei zu speichern. Ich habe es /home/pi/telegram/outgoing_to_bot genannt.
In dem Verzeichnis wird nun eine Textdatei abgelegt, die den folgenden Aufbau haben muss (den Token in Zeile 1 und die Chat-ID in Zeile 2 habe ich ebenso verfälscht):
Anhand des Tokens und der Chat-ID ist eindeutig festgelegt, wo die Message hingehen soll.
Mit einem Bash-Script wird nun in dem Verzeichnis in einer Schleife nach Dateien gesucht. Wird eine Datei gefunden, wird mit einem Aufruf von curl die Message an den Chat gesendet. Das Bash-Script sieht so aus:
# send_message_to_bot.sh : script for sending out all message to a Telegram bot. Release 0.1 from 17.06.2017
#!/bin/bash
commandlineparameter=$1
stopfile=/tmp/sendmessagetobot.stop # This is the file which will be created when this script is called with parameter "stop". The existence of the file is used as a signal to tell the script that it has to stop
processingflag=1 # 0 = false, we have to stop; 1 = true, we have to continue (this is default)
path_to_transport_program=/usr/bin/curl # the path to the program which is used to transfer messages (mail, curl, telegram-client ...)
path_to_messages=/home/pi/telegram/outgoing_to_bot # the path were the files are saved; they contain the mails, messages for Telegram.
send_to_Telegrambot() {
$path_to_transport_program \
-X POST \
https://api.telegram.org/bot$token/sendMessage \
-d text="$message" \
-d chat_id=$messagerecipient
}
if [ "$commandlineparameter" = "" ]
then
echo "No parameter given, allowed parameters:"
echo "start : starts sending out all messages to a Telegram bot"
echo "stop: stops the other instance of this script"
echo "We stop now."
fi
if [ "$commandlineparameter" = "stop" ] # we have to stop and we will create a file for sending a signal to stop:
then
echo "stop" > $stopfile
echo "We created stopfile and we stop now."
fi
if [ "$commandlineparameter" = "start" ]
then # we have to start processing.
# set -x # this helps for debugging
while [ $processingflag = 1 ] # we will continue with processing as long as this flag is true
do
if [ -f $stopfile ] # if the stopfile does exist we have to stop
then
echo "We are stopping now."
processingflag=0 # we set processingflag to false
rm $stopfile # the stopfile has to be deleted in order to clear the flag
else
for file in $path_to_messages/*.* ; do # we step through all files in the mentioned directory
full_path_to_messages=$path_to_messages/*.*
#echo Path to messages: $full_path_to_messages
if [ "$file" != "$full_path_to_messages" ] # if directory is not empty
then # now we extract from the file the content:
completeline=$(grep To: $file)
#echo $completeline
messagerecipient=${completeline:4}
#echo $messagerecipient
completeline=$(grep Token: $file)
token=${completeline:7}
completeline=$(grep Message: $file)
message=${completeline:8}
send_to_Telegrambot
rm -f $file # we delete the file
fi
done # for all files in outgoing directory
fi
sleep 1 # we sleep 1 second in order to save processor-time before we search next time for files
done # while [ $processingflag = 1 ]
fi
# END OF SCRIPT
Alles anzeigen
Das Script ist so gebaut, dass es mit Parameter start beginnt. Wenn man in einem anderen Terminal das gleiche Script mit Parameter stop aufruft, so beendet es sich.
Hier ein weiterer Screenshot vom Telegram-Client, nachdem die Textdatei in dem Verzeichnis abgelegt wurde und rausgesendet wurde:
Um das Versenden von Messages an den Chat mit dem Bot nach dem Start des Pi automatisch beginnen zu lassen, habe ich mir diese Service-Datei für systemd aufgebaut:
[Unit]
Description=Send messages to a Telegram bot
[Service]
Type=simple
User=pi
Group=pi
# We should wait until all services of the operating system are ready:
ExecStartPre=/bin/sleep 15
ExecStart=/bin/bash /home/pi/send_telegram_to_bot.sh start
#ExecStop=/bin/bash /home/pi/send_telegram_to_bot.sh stop
ExecStop=/bin/echo stop > /tmp/sendmessagetobot.stop
[Install]
WantedBy=multi-user.target
Alles anzeigen
Mit diesem Konstrukt ist es nun möglich, dass aus Programmen auf dem Pi heraus die Textdateien erzeugt werden um Messages per Telgram zu versenden. Andererseits kann ein Progamm nun die Inhalte der Textdateien auswerten und darauf reagieren. Für mich stellt dies eine Basis dar, um mein Programm message2action entsprechend erweitern zu können.
Abschließend sei erwähnt, dass auch mit dem Telegram-CLI eine solche Verarbeitung von Textdateien möglich ist. Das stelle ich auf Wunsch in einem anderem Beitrag gerne vor.
Anregungen und Feedback sind natürlich willkommen.