Sicher, die enthaltenen Abzeichen sind … nett. An ihnen ist absolut nichts auszusetzen. Aber was, wenn Sie mehr wollen? Was, wenn Sie über den vordefinierten Symbolsatz hinausgehen möchten? Sicher, es gibt eine Admin-Seite, auf der Sie sie hochladen können. Aber was, wenn Sie eine ganze Menge Abzeichen erstellen möchten?
Nun, gute Nachrichten! Sie können dies über die API tun. Hier ist Python-Code, der zeigt, wie es funktioniert. (Und er verleiht das Abzeichen am Ende, zur Sicherheit.)
Dies sollte ziemlich einfach zu lesen sein, auch wenn Sie kein Python-Programmierer sind. Sie können es sogar mit curl auf der Kommandozeile replizieren, wenn Sie möchten.
Dies erwartet, dass Ihr API-Schlüssel in einer Umgebungsvariable DISCOURSE_API_KEY vorhanden ist.
#!/usr/bin/python3
import os # Zum Lesen der Umgebung
import sys # Zum Beenden. :)
import hashlib # Für den Bild-Hash
import requests # Erledigt die eigentliche Arbeit
# Website- und Authentifizierungsinformationen
DISCOURSE = "discussion.fedoraproject.org"
DISCOURSE_API_USER = "mattdm"
DISCOURSE_API_KEY = os.getenv("DISCOURSE_API_KEY")
if not DISCOURSE_API_KEY:
print(f"Fehler: DISCOURSE_API_KEY muss in der Umgebung gesetzt sein", file=sys.stderr)
sys.exit(2)
# Informationen für Ihr Abzeichen. Vermutlich würden Sie dies in der realen Anwendung nicht fest codieren.
NAME = "Apex"
IMAGE = "apex.png"
DESCRIPTION = "Segen des FPL"
MORE = "Du bist großartig und jeder sollte es wissen!"
TARGET_USER = "mattdm"
# Unsere Authentifizierungsheader von oben.
HEADERS = {'Api-Key': DISCOURSE_API_KEY, 'Api-Username': DISCOURSE_API_USER}
# Von hier aus können Sie die IDs und Beschreibungen von Abzeichensammlungen und
# die verschiedenen Abzeichentypen abrufen. Wenn Sie möchten. In diesem Beispiel wird dies nicht verwendet.
r = requests.get(f"https://{DISCOURSE}/admin/badges.json", headers=HEADERS)
if r.status_code != 200:
print(f"Fehler beim Abrufen der Abzeichenliste: Erhalten {r.status_code}", file=sys.stderr)
sys.exit(1)
# Prüfen, ob der Name nicht bereits existiert.
# Wahrscheinlich gibt es eine bessere Methode, aber diese reicht aus.
if NAME in list(map(lambda x: x['name'], r.json()['badges'])):
print(f"Fehler: Abzeichen '{NAME}' existiert bereits.")
sys.exit(3)
# Bild lesen. In echtem Code würden Sie hier eine bessere Fehlerbehandlung wünschen!
with open(IMAGE, "rb") as f:
image_data = f.read()
# Wahrscheinlich sollten Sie hier einige Plausibilitätsprüfungen für die
# Bildgröße/Dimensionen durchführen....
# Aber trotzdem, stellen Sie ein Informationspaket darüber zusammen, um es hochzuladen.
# Das einzig wirklich knifflige hier ist, die Prüfsumme des Bildes zu erhalten.
file_info = {'file_name': f'{IMAGE}',
'file_size': f'{len(image_data)}',
'type': 'badge_image',
'metadata[sha1-checksum]': hashlib.sha1(image_data).hexdigest(),
}
# Und fragen Sie Discourse, wohin es gesendet werden soll.
r = requests.post(
f"https://{DISCOURSE}/uploads/generate-presigned-put", json=file_info, headers=HEADERS)
if r.status_code != 200:
print(
f"Fehler beim Anfragen, wohin das Bild hochgeladen werden soll: Erhalten {r.status_code}", file=sys.stderr)
sys.exit(1)
upload_url = r.json()['url']
upload_uid = r.json()['unique_identifier']
# Jetzt legen Sie es dorthin, wo es uns gesagt wurde.
r = requests.put(upload_url, data=image_data)
if r.status_code != 200:
print(
f"Fehler beim Hochladen des Bildes in den externen Speicher: Erhalten {r.status_code}", file=sys.stderr)
sys.exit(1)
# Und teilen Sie Discourse mit, dass es funktioniert hat, und erhalten Sie eine ID zurück, auf die wir später verweisen können.
r = requests.post(f"https://{DISCOURSE}/uploads/complete-external-upload",
data=f'unique_identifier={upload_uid}', headers=HEADERS)
if r.status_code != 200:
print(f"Fehler beim Abschließen des Uploads: Erhalten {r.status_code}", file=sys.stderr)
sys.exit(1)
image_id = r.json()['id']
# Hinweis: Wenn Sie Font Awesome verwenden möchten, lassen Sie `image_upload_id` leer und
# setzen Sie stattdessen `icon` auf den entsprechenden Font Awesome-Namen. Und natürlich
# können Sie sich in diesem Fall den gesamten Bild-Upload-Aufwand sparen!
badge = {'allow_title': 'true',
'multiple_grant': 'false',
'listable': 'true',
'show_posts': 'false',
'target_posts': 'false',
'name': f'{NAME}',
'description': f'{DESCRIPTION}',
'long_description': f'{DESCRIPTION} {MORE}',
'image_upload_id': f'{image_id}',
'badge_grouping_id': '5',
'badge_type_id': '1',
}
r = requests.post(
f"https://{DISCOURSE}/admin/badges.json", json=badge, headers=HEADERS)
if r.status_code != 200:
print(f"Fehler beim Erstellen des Abzeichens: Erhalten {r.status_code}", file=sys.stderr)
sys.exit(1)
badge_id = r.json()['badge']['id']
print(f'Abzeichen "{NAME}: {DESCRIPTION}" wurde als {badge_id} erstellt!')
# Und zur Vollständigkeit, verleihen Sie das Abzeichen!
# Sie können auch einen "Grund" hinzufügen, der auf einen Beitrag oder ein Thema verweisen muss.
bestow = {'username': f"{TARGET_USER}", 'badge_id': f'{badge_id}'}
r = requests.post(f"https://{DISCOURSE}/user_badges",
json=bestow, headers=HEADERS)
if r.status_code != 200:
print(f"Fehler beim Verleihen des Abzeichens: Erhalten {r.status_code}", file=sys.stderr)
sys.exit(1)
print(f'Benutzer {TARGET_USER} hat das neue Abzeichen erhalten!')