Mit Python auf Mastodon eine Nachricht senden

Mit nur wenigen Zeilen kann man in Python mit Mastodon.py einen Toot senden

Einführung

Im Blog Artikel zu den ersten Schritten, wurde umfangreich erklärt, wie man eine App registrieren kann. Genutzt wurde das für das erste Beispiel zum Lesen einer lokalen Timeline aber gar nicht. Das liegt daran, dass Mastodon drei verschiedene Ebenen der Authentifizierungen von Identitäten nutzt. Public bedeutet, man braucht gar keine Authentifizierung, App Code wird es in der Mastodon API genannt, wenn man mindestens mit einer Application registriert ist und sich einen Application Code geholt hat, mit dem man auf die API zugreifen will und letztendlich User, wo man als Identität einen Account benötigt und man mit diesem sich authentifiziert.

Es gibt eigentlich nur einen Endpunkt in der REST API der Mastodon Instanz, die App Code voraussetzt. Das ist dann, wenn man einen neuen Account auf der Instanz anlegen will (was aber auch nur geht, wenn die Registrierung “offen” ist). Nahezu alle anderen Endpunkte sind entweder Public oder erfordern einen User.

Der erste Toot

Gehen wir mal davon aus, ein Account wurde auf einer Instanz bereits registriert. Wir haben auf derselben Instanz noch unsere App registriert (wenn nicht, dann hier nachschauen), dann können wir mit wirklich wenigen Zeilen eine Nachricht an das Fediverse schicken.

Der erste Teil ist wie erwartet: Unsere App-Registrierungsdaten werden als client_id und client_secret übergeben:

import json
from mastodon import Mastodon

mastodon = Mastodon (
    client_id='ep********************************************Xo',
    client_secret='AY****************************************0s',
    api_base_url='https://social.tchncs.de'
)

Nun brauchen wir aber den originären Login des Users, um diese Identität anzunehmen (eigentlich arbeitet nun unser Client Script im Auftrage des Users):

mastodon.access_token = mastodon.log_in (
    username='<die email-adresse des users>,
    password='<das password des users>,
    scopes=['read', 'write']
)

Username und Password schreibt man üblicherweise nicht in Scripts, aber wir spielen ja noch rum. Besser wäre es, das Script liest sie aus den Argumenten ab oder es wird per Eingabe abgefragt.

Wir brauchen den Scope ‘write’ um eine Nachricht zu senden. Das ist unglaublich einfach:

response = mastodon.toot ("Das ist ein Test, bitte ignorieren.")
print (json.dumps(response, indent=4, default=str))

Das schauen wir uns mal in der Timeline an:

Mastodon Toot

Perfekt, hat wohl geklappt. Wir nervten gerade ein paar tausend aktive Nutzer in der lokalen Timeline mit unserem Test.

Spannend ist auch die Response des toot()-Aufrufs.

Hier ein (stark) gekürzter Auszug:

{
    "id": 108243723640515608,
    "created_at": "2022-05-04 12:42:26.372000+00:00",
    "visibility": "public",
    "language": "de",
    "uri": "https://social.tchncs.de/users/beandev/statuses/108243723640515608",
    "content": "<p>Das ist ein Test, bitte ignorieren.</p>",
    "reblog": null,
    "application": {
        "name": "Spielplatz",
        "website": "https://social.tchncs.de/@beandev"
    },
    "account": {
        "id": 38900,
        "username": "beandev",
        # ...
    },
    "media_attachments": [],
    "mentions": [],
    "tags": [],
    "emojis": [],
    "card": null,
    "poll": null
}

Man sieht aber in der Ausgabe, dass das Response-Objekt dramatisch größer ist. Lauter Attribute und vor allem eine komplette Account-Information.

Tatsächlich ist Mastodon (und alle anderen Dienste im Fediverse) so geschwätzig, weil damit die Clients mit nur einer Response alle wichtigen Informationen darstellen können ohne weitere Roundtrip-Anfragen zu stellen. Das ist in einem föderierten, verteilten System erheblich einfacher, als ständig mit Nachfragen der Clients bombardiert zu werden.

Abschließend sei gesagt, dass toot() nur für den ersten Test sinnvoll ist. Es gibt eine erheblich bessere Methode status_post(), die man dazu verwenden sollte (dazu aber mehr in einem anderen Artikel).