Mein Weg zu einem Telegrambot mit Python

  • Der Weg zum eigenen Telegram Bot mit Python

    Vorwort

    Vor längerer Zeit schon wurde ich von einem User gebeten, ob ich nicht meine Gedankengänge niederschreiben möchte, wie ich bei der Erstellung von meinen Telegram Bots vorgehe. Dieser Zusage möchte ich hiermit endlich nachkommen.

    Als Programmiersprache kommt Python zum Einsatz. Grundverständnis der Sprache wird vorausgesetzt.

    Es gibt viele Module zum erstellen eines Telegrambot für Python, jedoch habe ich mir selbst eine kleine API erstellt. Eines der verfügbaren Module im Internet habe ich bisher noch nie verwendet.

    Anhand von 2 Beispielen möchte ich meine Gedankengänge aufzeigen, wie ich bei der Erstellung der Bots vorgehe.


    Die telegram_bot_api

    Zu finden gibt es das Pythonmodul hier: https://github.com/Hofei90/telegram_api

    Es steht nicht auf PyPi zur Verfügung, dennoch lässt es sich mit folgenden Befehl installieren und für eigene Projekte verfügbar machen:

    pip3 install git+https://github.com/Hofei90/telegram_api


    Die offizielle Telegram API ist hier zu finden.


    Mein Modul stellt das ganze in Python zur Verfügung, dass mit requests die gewünschte Methode an den Telegram Server gesendet wird. Jedoch sind nicht alle verfügbaren Methoden integriert, sondern nur die, die ich bisher selbst benötigt habe. Es lassen sich nicht vorhandene Methode leicht integrieren.


    Hier die Erklärung, wie die Funktion (Methode) in dem Modul aufgebaut ist anhand von der Funktion send_message.


    https://core.telegram.org/bots/api#sendmessage

    Die Methode definiert unseren Funktionsname und wird noch angepasst, dass es PEP8 konform ist. Aus sendMessage von der Website wird also send_message().

    Alle aufgelisteten Parameter in der Tabelle von der Webseite werden als Methodenparameter definiert. Beachte, da es sich hier um eine Methode innerhalb einer Klasse handelt, muss der erste Parameter immer self sein.

    Anschließend gefolgt von allen Parametern, mit Typeannotation habe ich die verfügbaren erlaubten Types hinterlegt. Ist ein Parameter optional so erhält er noch ein None als Ausgangsdefinition.


    Innerhalb der Funktion werden mit Hilfe von isinstance() die Parameter auf ihren Typ überprüft, ist dieser passend so wird der Wert des Parameter in das Dictionary params aufgenommen. Der Key muss dem Name des Parameter entsprechen, wie auf der Webseite.

    Eine sinnvolle Ergänzung des Moduls wäre es, wenn Pflichtparameter einen nicht den geforderten Typen enthalten, eine Exception zu werfen. Dies ist aber noch nicht integriert.

    Wurden alle Parameter überprüft, wird die URL für den Request zusammengesetzt.

    Die URL beginnt mit dem statischen Teil der Telegram API "https://api.telegram.org/bot" gefolgt von dem Bottoken (später dazu mehr). Das Dictonary params wird dem Parameter params von request.get() übergeben, hier wird es passend zum Senden der Anfrage umgewandelt. Das Resultat von der Anfrage wird von der Methode zurückgegeben. Schon hat man eine Methode in die API integriert.



    Bot erstellen bei Botfather (Token erhalten)

    Wie erwähnt, benötigt man einen Token, dieser Token ist für jeden Bot einmalig. Um einen Bot erstellen zu können, muss man im Telegram Chat mit den Bot Botfather Kontakt aufnehmen. Bei diesem erstellt man neue Bots und erhält den benötigten Token, hinterlegt Botkommandos, editiert bestehende Bots und kann diese auch löschen. Auch sind dort Sicherheitseinstellungen vorzunehmen.

    Im Chat mit Botfather /newbot eingeben und den Fragen folgen. Der Rest sollte selbsterkärend sein.

    Teile mit niemanden deinen Bottoken

    Ebenso würde ich die Telegramid nicht veröffentlichen.

    Die Programmbeispiele

    Beispiel 1

    Bei Beispiel 1 handelt es sich um einen Bot, der auf einem virtuellen Server den dedizierten Gameserver von dem Spiel Empyrion - Galactic Survival steuert.

    Zum aktuellen Funktionsumfang gehört, den Server

    • starten
    • stoppen
    • updaten
    • status prüfen

    zusätzlich ist noch geplant aber noch nicht integriert, dass die IP Adresse des Servers mitgeteilt wird.


    Beispiel 2

    Dieses Beispiel ist deutlich Forennäher. Vor einiger Zeit wurde der Tutorialbereich mit Hilfe von einigen Usern und diesem Botskript hier "aufgeräumt". In einem anderen Skript wurden alle Threads des Tutorialbereiches erfasst und die URLs in einer Datenbank abgespeichert.

    Der Bot kümmerte sich um die Zuteilung der Threads der einzelnen helfenden User. Sodass die Threads nicht doppelt bearbeitet worden sind.

    Der Thread wurde dann von dem User geprüft und er gab an dem Bot Rückmeldung ob der Thread ok ist, oder von einem Moderator geprüft und / oder verschoben werden muss. Der Moderator wiederrum sah mit Hilfe des Bots alle gemeldeten Threads und konnte dann den Status auf erledigt setzen.

    Außerdem konnte man sich ein Bild zur Statistik über den Fortschritt der Aktion senden lassen

    Die beiden Beispiele unterscheiden sich zum einen natürlich in ihrer Funktion, den verwendeten Funktionen der API und Beispiel 1 erbt von der Klasse aus der API, welches in Beispiel 2 nicht der Fall ist.


    Erste Schritte

    Bevor näher auf die Beispiele eingegangen wird, senden wir uns eine Nachricht mit den neu erstellten Bot.

    Wer das Beispiel ausführen will, muss die Telegram API für Python und ebenso toml installiert haben.

    Grundsätzlich empfiehlt es sich, Daten von Code zu trennen. Gerade sensible Daten wie der Token hat in dem Code auf keinem Fall etwas verloren. Zu schnell ist der Code geteilt bei einem Problem und man hat es versäumt den Token unkenntlich zu machen.

    Aus diesem Grund wird auch das Beispiel aus 2 Teilen bestehen. Die Daten kommen in ein seperates Toml File, der Code in das Skript (auch zu finden im Examples Ordner auf Github).

    Die Daten in den <> sind anzupassen.

    Die eigene Telegramid lässt sich einfach mit dem Raw Data Bot herausfinden.

    Der Bot kann immer nur mit einem User kommunizieren, wenn der User zunächst selbst Kontakt mit dem Bot aufnahm indem er auf starten klickte oder ihm eine eine gesendet hat. Zuvor kann der Bot keine Nachricht an den User senden.


    Code: example_cfg.toml
    text = "Hello World"
    
    [telegram]
    token = "<bottoken>"
    user = <telegramid>

    Bei der Einführung zur Gestaltung der API hieß es zuletzt, dass die Funktion das Resultat zurückgibt, würde man nun also die send_message Zeile wie folgt abändern, kommt man an die Rückmeldung des Telegram Servers

    Code
    r = bot.send_message(user, CONFIG["text"])
    print(r)

    Die Ausgabe davon:

    Code
    {'ok': True, 'result': {'message_id': ***, 'from': {'id': ***, 'is_bot': True, 'first_name': '***', 'username': '***'}, 'chat': {'id': ***, 'first_name': 'Hofei', 'username': 'Hofei', 'type': 'private'}, 'date': 1613917215, 'text': 'Hello World'}}

    Das Format von erhaltenen Nachrichten sieht ebenso aus.

    Statt nun eine Nachricht zu versenden, warten wir auf eine eintreffende Nachricht.


    Sobald nun eine Nachricht an den Bot gesendet wird, erhalten wir eine Nachricht. Die Struktur der Nachricht kann hier nachgelesen werden.

    Zum Abschluss des Einstieges möchte ich noch erwähnen, dass es neben der Polling Methode zum Nachrichten empfangen noch die Möglichkeit zum Einrichten eines Webhooks gibt. Diese Möglichkeit macht es aber notwendig Ports zu öffnen, weswegen ich bisher durchgängig auf Polling setze.


    Programmaufbau

    Alles folgende bezieht sich auf Beispiel 2.

    Beispiel 1 + 2 liegen von der Entstehung zeitlich etwas auseinander, weswegen sich meine herangehensweise etwas geändert hat.

    Klassen

    Aus telegramtechnischer Sicht arbeite ich im Hauptteil mit 2 Klassen.


    Klasse User enthält folgende Attribute

    • telegram_id - Enthält die Telegramid des Users um ihm antworten zu können
    • name - Name des Users
    • menue - Ist ein Menüpunkt aktiv so ist die entsprechende Funktion hier hinterlegt
    • umenue - =Untermenü um die Navigation innerhalb eines Menüpunktes zu ermöglichen

    Nimmt ein neuer/unbekannter User Kontakt mit dem Bot auf, so wird eine neue Instanz der Klasse User erstellt um die notwendigen Userbezogenen Daten hier speichern zu können.


    Klasse TutorialBot enthält folgende Attribute

    • bot - Ist wird die Botinstanz abgespeichert (Instanzierung des Bot von der API mit der zuweisung des Tokens)
    • offset - Wird benötigt um den Erhalt der Nachrichten quittieren zu können. Offset muss immer 1 höher sein als die letzte größte Zahl der Message ID


    Enthaltende Methoden

    • get_updates - Bestätigt mit Hilfe des Attributs offset den erhalt der Nachrichten


    Die API habe ich seit der Erstellung von Beispiel 2 so überarbeitet, dass get_updates direkt in der API enthalten ist. Deswegen ist im Beispiel 1 kein get_updates enthalten. Dafür werden in Beispiel 1 alle Botkommandos in der Klassse (hier TutorialBot) gespeichert

    Aufbau

    Nachrichten empfangen

    Zunächst fange ich immer an, dass ich Nachrichten mit dem Bot empfangen kann.

    Somit müssen wir erstmal unseren Bot mit dem zugehörigen Token instanzieren (Zeile 378). In Zeile 377 wird ein Dictonary erstellt um unsere später ankommenden Userinstanzen speichern zu können.


    In der while True Schleife wird alle ~0.5 Sekunden (Zeile 387) geprüft ob neue Nachrichten vorliegen -> Zeile 381 users = bot.get_updates(users)

    ~0,5 Sekunden deshalb, da es ja nur die Zeit ist, welche an der Stelle pausiert wird, nicht noch die Zeit welche benötigt wird um die aufgerufenen Funktionen abzuarbeiten.


    Wie ich seit der Erstellung des Codes durch Advent of Code durch __blackjack__ gelernt habe, ist es außerdem unüblich/nicht richtig das Dictonary zurück übergeben. Das users = müsste also eigentlich Weg. Jedoch möchte ich aktuell den Code nicht ändern, sondern mit dem Stand posten, wo ich wusste dass es im Produktiven Einsatz war.


    Nun müssen wir dem Code folgen, wir prüfen also ob eine Nachricht vorhanden ist.

    Die geschieht in der Methode get_updates() in Zeile 37 - 64.

    Ist seit dem letzten Aufruf also eine Nachricht vorhanden wird in Zeile 49 über das Resultat iteriert.

    Die Iteration ist deshalb nötig, da ja seit dem letzten Aufruf schon mehr als eine Nachricht vorliegen könnte. Mit diesem vorgehen arbeiten wir nun alle vorliegenden Nachrichten ab.

    Für den Fall das das Resultat etwas anderes enthält als eine Nachricht und somit der Key "message" nicht enthalten ist, soll mit der nächsten Iteration fortgefahren werden (Zeile 51, 52)

    Als nächstes wird mit Hilfe des user_handlers geprüft, ob in unserem Dictonary users der User von der vorliegenden Nachricht schon steht. Wenn nein wird der User aufgenommen (Zeile 69 - 72). Da ich mich entschieden hatte den Name nicht mit aufzunehmen, steht in Zeile 70 nur Test.

    Als Key der Einträge im Dictonary wird die Telegramid des Users verwendet.


    nachrichten_handler

    Als nächstes geht die uns vorliegende Nachricht zu Funktion nachrichten_handler() der, wie ich finde, zentrale Punkt des Programmes.

    Wir springen als von Zeile 54 nach Zeile 75 - 83.

    Hier wird (nochmals wie ich gerade merke) geprüft, ob die Nachricht den Schlüssel "message" enhält.

    Wenn dies der Fall ist, wird überprüft, ob es sich im vorliegenden Falle um ein Botkommando handelt. Ist es ein Botkommando wird die Nachricht an die Funktion bot_command weitergereicht. Um ein Botkommando handelt es sich immer dann, wenn der Text mit / beginnt

    Ansonsten wird überprüft ob bei dem Antwortenden User schon ein Menüpunkt aktiv ist (also ob schon in einer vorherigen Nachricht ein Menüpunkt einem Botkommando aktiviert worden ist). Ein Menüpunkt ist aktiv wenn bei dem Attribut nicht None hinterlegt ist.

    Da wir aktive Menüpunkte direkt an das Attribut menue binden, müssen wir von dem User nur menue aufrufen.

    Aufgrund der Tatsache, dass wir diesen Aufruf so durchführen, ist es zwingend erforderlich, dass alle Funktionen die mittels bot_command angesprochen werden, die selbe Struktur aufweisen! In meinem gezeigten Fall also dass jede Funktion die Paramter nachricht, bot, users, key entgegen nimmt.


    Da dieser Bot in diesem Beispiel nichts mit Nachrichten anfängt wenn keine Funktion aktiv ist, ist die Prüfung im nachrichten_handler beendet.

    Als nächstes wird die Struktuer der Funktion bot_command betrachtet und wie das Attribut menue seinen Status annimmt.


    bot_command

    In dieser Funktion (Zeile 89 - 114) werden alle verfügbaren Botkommandos aufgeführt.

    In einer if elif else Abfrage wird so jeder Eintrag durchgegangen ob er mit dem gesendeten Botkommando übereinstimmt.

    Innerhalb des Ifzeiges wird dann die entsprechende zugehörige Funktion zum Botkommando augerufen.

    z.B wird an unserem Bot das Kommando /statistik gesendet, so wird in Zeile 104, 105 die Funktion m_statistik_anzeigen() aufgerufen

    m = Menü zur Besseren Übersicht im Strukturbaum der IDE.

    Erreicht man den Else Teil der Abfrage, so erhält der Benutzer den Hinweis, dass das Kommando unbekannt ist.

    Nur /start darf ausgeführt werden, wenn der Benutzer noch nicht in der Datenbank steht, deshalb ist /start in einer seperaten if Abfrage, bei allen anderen Kommandos wird vorausgesetzt, dass der Benutzer bekannt ist. (Zeile 94, 95)


    Damit im Messanger die verfügbaren Kommandos angezeigt werden, muss Botfather eine Liste mit Botkommandos und kurzer Beschreibungstext mitgeteilt werden.

    Dazu bei Botfather den passenden Bot auswählen

    1. /mybots
    2. In der Liste gewünschten Bot wählen
    3. Edit Bot wählen
    4. Edit Commands
    5. Liste nach vorgegebener Formatierung schicken

    Nach dem Beispiel würde das wie folgt aussehen, hierzu erstelle ich mir immer eine kleine Textdatei botkommandos.txt

    Die hat den Vorteil, dass man z.B mit /help dann alle verfügbaren Kommandos anzeigen lassen kann. (siehe Zeile 141)

    Code
    /start - Erstmalige Ausführung zum Bestätigung der Datenschutzhinweise
    /help - Öffnet das Hilfemenü
    /del_acc - Löscht deinen Account
    /stop - Bricht alle offenen Befehle ab
    /statistik - Zeigt den Stand der Threadstatuse an
    /thread_bearbeiten - Zum mitteilen des Ergebnisses
    /threads_mod_anzeigen - Zeigt Threads an, die auf Bearbeitung durch Moderator warten
    /thread_mod_bearbeiten - Bearbeitung durch Moderator


    Ausführen von Kommandos

    ohne Zwischenspeicherung

    Wurde nun das Kommando /statistik an den Bot gesendet, wird über die Funktion bot_command die Funktion m_statistik_anzeigen() aufgerufen. (Zeile 173 - 181).

    In dieser Funktion ist es nicht notwendig, den Menüpunkt in user.menue zu speichern, da alles notwendige in einem Durchlauf abgearbeitet werden kann.

    Es wird zunächst das Bild für die Statistik generiert und im eingestellten Pfad abgespeichert.

    Anschließend bekommt der User mit der Zeile 180 den Text gesendet und in Zeile 181 das Bild.

    Für Fotos wird die Methode send_photo() anstelle send_message() benötigt.


    mit Zwischenspeicherung

    Nun wird es etwas "komplizierter".

    Als Beispiel beziehen wir uns auf die Funktion m_thread_bearbeiten() von Zeile 184 - 234.

    Der User hat also das Botkommando /thread_bearbeiten gesendet.

    Über den Nachrichten Handler wird die Funktion bot_command aufgerufen und in der If Abfrage wurde Zeile 107 ausgeführt.

    Wir wollen jetzt aber mit dem User interagieren können. Also Texte, Anweisungen senden, Angaben entgegen nehmen usw.

    Aus diesem Zweck gibt es in der Klasse User die Attribute menue und umenue

    In Zeile 187 wird der Zustand von umenue geprüft und festgestellt, dass der Zustand None ist.


    Somit wissen wir, die Funktion wird das erste mal betreten.

    Als erstes wird die aktive Funktion m_thread_bearbeiten in dem Attribut menue hinterlegt. Wichtig ist, die Funktion hinterlegen, nicht aufrufen. Das heißt die Funktion ohne () an menue binden.

    Wir erinnern uns, im Nachrichten Handler wird geprüft ob menue None ist, da dies jetzt nicht mehr der Fall ist, wird die Funktion bei der nächsten Nachricht erneut aufgerufen, obwohl kein Bot Kommando gesendet wird.

    Python
            elif users[key].menue is not None:
                users[key].menue(nachricht, bot, users, key)

    Dann wird dem Benutzer der Anweisungstesxt gesendet Zeile 189 - 195 und das Attribute umenue auf 1 gesetzt (Zeile 196). Dadurch, dass nun umenu auf 1 ist und nicht mehr None, wissen wir beim nächsten Aufruf, wenn der User etwas postet, dass die Funktion schon aktiv ist und der Teil von Zeile 187 - 196 wird nicht mehr betreten sondern die If Part == 1 von Zeile 197 - 209.

    Da die Prüfung mit is None und == 1 nicht mit elif Verknüpft ist, wird im selben Durchlauf auch noch der Teil von 197 - 208 bearbeitet.

    umenue ist also zum Zeitpunkt des ersten Verlassen der Funktion auf 2.

    Nun erfolgt die erste Antwort seit die Funktion aktiv ist bei dem User.

    Der Nachrichtenhandler ruft m_thread_bearbeiten auf, das menue enthält m_thread_bearbeiten.

    Fortgefahren wird in Zeile 209, da umenue die 2 enthält.

    Ist die Antwort des Users nicht nach dem geforderten Format, so wird das dem User mitgeteilt und die Funktion in Zeile 213 verlassen. Der Inhalt von menueund umenu bleibt also unverändert, sodass er die Eingabe erneut machen kann und an der selben Stelle der Funktion wieder landet.


    Da in dem Beispiel eine Mehrfacheingabe gewünscht war, ohne dass jedesmal /thread_bearbeiten eingegeben werden musste, wird nach korrektem Format nachdem der Datensatz aktualisiert wurde und der User benachricht, umenue und menue NICHT auf None gesetzt, wie es nach jeder überlichen Funktion nun nötig wäre, sondern umenue wird wieder zurück gesetzt auf 1 um auf die Nächste Eingabe zu warten. Ansonsten wäre es der korrekte Weg nun umenue und menue auf None zu setzen.


    In dem vorliegenden Fall ist es nur Möglich, dass die beiden Attribute wieder den Zustand None annehmen, wenn der Benutzer /abbrechen als Botkommando sendet und in Zeile 166 - 170 landet.


    Damit dies so funktioniert ist es jedoch nötig, die Reihenfolge der Behandlung im Nachrichten Handler wie gezeigt einzuhalten. Es muss also erst auf ein bot_command geprüft werden und erst danach darf geprüft werden ob menue None ist oder nicht.

    Python
            if "bot_command" in nachricht["message"].get("entities", [{}])[0].get("type", ""):
                users = bot_command(nachricht, bot, users, key)
            elif users[key].menue is not None:
                users[key].menue(nachricht, bot, users, key)


    Da der Punkt bisher noch etwas zu kurz kam.

    Damit der Bot es unterscheiden kann, von wem die Nachricht kommt und bei wem welcher Menüpunkt aktiv ist wird über das Dictonary users realisiert und dem ansprechen des Dictonarys über dem Key was der Telegram ID des Users entspricht.


    Mit diesem Wissen, so hoffe ich, sollte es dir Möglich sein deinen eigenen Bot zu erstellen.

    Was dieser Bot für Funktionen erfüllt, hängt natürlich davon ab, was in den einzelnen Botkommandos integriert wird.


    Jetzt noch etwas aus Beispiel 1

    Klassen

    Zum Abschluss sehen wir uns noch einige Punkte aus dem Beispiel 1 an

    Auch hier gibt es wieder 2 relevante Klassen Namens User und EmpyrionBot.

    User ist schon bekannt von dem vorherigen Beispiel.


    EmpyrionBot erbt nun von telegram_bot_api.Bot. Dies ist der erste Unterschied. Hat den Vorteil, dass ich innerhalb von Methoden der Klasse EmpyrionBot direkt auf die Methoden der API zugreifen kann.

    z.B.: Zeile 96 self.send_message(key, "Abgebrochen")


    Ebenso habe ich die bot_commands (hier nur commands genannt) als Methode zur Klasse zugeordnet und auch alle einzelnen Botkommandos als Methode hinterlegt anstatt einzelner Funktionen.


    Zugriffskontrolle

    In der Konfigurationsdatei gibt es einen Eintrag mit allowed_ids = {"username" = <telegramid>}

    In Zeile 170 wird diesesmal das Dictionary users über eine Dictionary Comprehension erstellt, wo für jeden Eintrag in allowed_ids eine Instanz der Klasse User erstellt und gespeichert wird.

    Kommt nun eine neue Nachricht prüft der Nachrichten Handler in Zeile 153 ob die Telegramid im Dictionary users bekannt ist, wenn nicht erhält der User eine Nachricht "Permission denied" in Zeile 154.


    Fließende Nachrichtenaktualisierung

    Der Bot aus Beispiel 1 soll einen Gameserver steuern und wenn nötig ein Update anstoßen. Die Konsolenausgabe des Updateprozesses wird mit dem Bot auf den Messanger wieder gegeben. (Zeile 122 - 140)

    Hierfür gibt es die Funktion edit_message_text in der API.

    Die Nachrichten auf Telegram sind auf 4096 Zeichen beschränkt, deshalb wird vor jedem editieren der Nachricht die Länge der Nachricht überprüft. Befindet es sich innerhalb der Zeichengrenze wird die Nachricht editiert, ansonsten wird eine neue Nachricht gesendet und dieses wieder editiert.



    Abschluss

    Anmerkungen und Kritik zum gezeigten Code bitte in einem seperaten Thread äußern.

    Anmerkungen und Kritik zum Tutorial sind gerne hier gesehen.

    Bei Problemen zur Umsetzung des hier gezeigten, bitte ebenfalls einen neuen Thread eröffnen.

    • Official Post

    Hallo Hofei!


    Ich hoffe ich darf hier antworten... Der von Dir genannte User bin ja ich. So, nun habe ich mich geoutet. :lol:


    Vielen Dank für diese Anleitung, da hast Du echt viel Zeit investiert und hat (dank auch Deines unten stehendem Tipps) bestens funktioniert! Cool, mein erster Telegram Bot!:bravo2:


    Ich habe das Beispiel send_message_example.py heute mal durchgespielt. Mein Problem, das ich an anderer Stelle auch schon ansprach, war ja die user = <telegramid> herauszufinden. Der Tipp mit @RawDataBot war echt Gold wert!


    Vielleicht kannst Du das im noch Tutorial ergänzen?


    :danke_ATDE: nochmals für Deine Mühen!

  • Vielleicht kannst Du das im noch Tutorial ergänzen?

    erledigt.


    Änderung:


    Die eigene Telegramid lässt sich einfach mit dem Raw Data Bot herausfinden.

    Der Bot kann immer nur mit einem User kommunizieren, wenn der User zunächst selbst Kontakt mit dem Bot aufnahm indem er auf starten klickte oder ihm eine eine gesendet hat. Zuvor kann der Bot keine Nachricht an den User senden.

  • Ein spannendes Projekt. Allerdings meine ich, dass Bots immer nur auf Anfrage reagieren. Ist das richtig?


    Ich hatte für meinen RPi eine SIM gekauft gehabt und damit einen User angelegt. Der kann mich auch ohne Anfrage ansprechen, wenn z. B. mein Server im WWW offline ist oder eine Anwendung zu hohe Lasten verursacht. Ein Shellscript überwacht verschiedene Dinge und funkt mich per Telegram an, falls was aus dem Ruder läuft. Ist wirklich sehr nützlich. Trotzdem die Frage: Könnte das auch ein Bot tun? Also könnte ich dem Shellscript sagen, dass er den Bot aktivieren soll? Ist vielleicht ein bisschen Offtopic, aber hier dürften die Experten über entsprechendes Wissen verfügen. Wäre nett, wenn jemand mir die Frage beantworten kann. :)

    • Official Post

    Allerdings meine ich, dass Bots immer nur auf Anfrage reagieren. Ist das richtig?

    Der Bot ist eigentlich nur so eine Art Vermittler zwischen einem von Dir geschriebenen Skript und dem Nachrichenempfänger (also Du). Wenn das Skript was zu sagen hat, dann schickt es eine Nachricht via Bot an den Empfänger. Wenn Du eine Anweisung per Bot versendet, dann ist Dein Skript der Empfänger und macht das was Du programmiert hast.


    Vergleichbar wäre das im weitesten Sinne mit einer DynDNS- Adresse.

  • Der Bot ist eigentlich nur so eine Art Vermittler zwischen einem von Dir geschriebenen Skript und dem Nachrichenempfänger (also Du). Wenn das Skript was zu sagen hat, dann schickt es eine Nachricht via Bot an den Empfänger. Wenn Du eine Anweisung per Bot versendet, dann ist Dein Skript der Empfänger und macht das was Du programmiert hast.


    Vergleichbar wäre das im weitesten Sinne mit einer DynDNS- Adresse.

    Das habe ich schon verstanden. Die Frage ist aber die, ob der Bot auch durch ein Script dazu gebracht werden kann, mir eine Nachricht zu schicken. Soweit ich das verstanden habe, muss ich den Bot selbst per Telegram mit den Commands ansprechen, um eine Antwort zu bekommen.


    Der User den ich jetzt im Einsatz habe, existiert wie ein Kontakt, der eben auch wie ich Telegram nutzen kann. Ich könnte damit Nachrichten an wen ich will versenden. Ich muss also kein Command senden, um eine Antwort zu bekommen. Darum geht es mir. Der Bot soll von sich aus reagieren können, ohne meine AKTION eine REAKTION zeigen.

  • Ich hab mir Hofeis API noch nicht angeschaut und benutze die python-telegram-bot API.


    Der Bot hört nicht nur auf deine Commands, also "/command".


    Du kannst mit:


    dir, je nachdem wie du das programmierst, im prinzip alles schicken.


    Was so nicht geht ist das Bots sich untereinander unterhalten.


    Meintest du das?

  • Allerdings meine ich, dass Bots immer nur auf Anfrage reagieren. Ist das richtig?

    Nein, welche Skriptlogik dahinter steckt, kommt auf das Skript an. Ich lass mir z.B immer 1x täglich, 1x wöchentlich 1x monatlich eine Zusammenfassung meiner Wetterdaten von meiner Wetterstation schicken.



    Ich hatte für meinen RPi eine SIM gekauft gehabt und damit einen User angelegt.

    Wurde die SIM gekauft, weil du an der Stelle keine Internet per (W)LAN zur Verfügung hattest, oder nur um eine neue Nummer für einen neuen Telegramuser zur verfügung zu haben. Wenn 2teres, wäre ein Bot genau deine Wahl gewesen ohne dass du eine SIM benötigt hättest.


    Trotzdem die Frage: Könnte das auch ein Bot tun?

    ja



    Könnte das auch ein Bot tun? Also könnte ich dem Shellscript sagen, dass er den Bot aktivieren soll?

    ja, der Bot ist das Skript ;)

  • Danke dir. Ich probiere das aus.

    Der Bot kann immer nur mit einem User kommunizieren, wenn der User zunächst selbst Kontakt mit dem Bot aufnahm indem er auf starten klickte oder ihm eine eine gesendet hat. Zuvor kann der Bot keine Nachricht an den User senden.

    Dabei bitte diesen Part hier beachten

  • Jetzt bin ich verwirrt. Also muss ich doch erst aktiv werden, bevor ein Bot mir etwas melden kann? Oder muss ich nur einmal den Bot aktivieren und er bleibt dann in Kontakt mit mir?

  • Das ist einmalig. Sonst könnte man ja mit seinen Bots wild fremden User Werbung Spam und sonstige unerwünschte Inhalte spielend leicht zukommen lassen in dem man bei Telegram I’d 1 anfängt und dann hochzählt und jedem ne Nachricht schicke .

    Der Erstkontakt muss vom User zum Bot gehen, ab dann kann der Bot immer schreiben bis man den Bot anhält

  • Alles klar. Dann sollte das wie geplant funktionieren. Ich dachte, ich müsste jedesmal erst kontaktieren, um Nachrichten abzufragen. Das wäre in dem Sinne zu umständlich und für den Zweck nicht geeignet. Ich will ja bei betimmten Events sofort benachrichtigt werden. Danke für die Hilfe!