
Neulich in Telegram: Ich schicke ein paar unserer Links mit KI-Titelbildern - und in Telegram bleiben sie unscharf. Komisch. Also schicke ich Links mit Nicht-KI-Titelbildern - und siehe da: scharf! Sah aus, als hätte der Windows-Desktop-Client tatsächlich eine KI-Erkennung. Sah so aus ...
Nach dem nächsten Systemstart hat ein Blick in den Chat schnell Entwarnung (aka Enttäuschung ...) gebracht: Alle Vorschaubilder scharf, offenbar war es wieder mal nur komischer Mirco-Fehler.
Aber dann war der Wunsch da: Automatische KI-Analyse, ob Bilder KI-generiert sind. Nun, mit der folgenden Bastelei könnte ich Bilder auch auf Nacktheit, Promis oder sonstwas prüfen lassen.
Wie immer bei meinen Basteleien: Es geht mir um PoCs, um Proofs of Concepts, zu Deutsch Machbarkeitsstudien. Ihr könntet es aber ziemlich simpel auf eine produktive Stufe heben und in echten Telegram-Gruppen echte automatisierte Analysen laufen lassen. Hier erstmal das Ergebnis:
Konzept
Zunächst mal mein Ziel: Sobald ein Bild in den Chat gepostet wird, soll es automatisch auf KI-Inhalt geprüft werden. Dann soll eine entsprechende Rückmeldung in dem Chat kommen.
Und natürlich: Entwickelt habe ich das Ganze mit ChatGPT - es ist einfach besser in Python als ich 🙁 Leider ist so eine KI trotzdem strunzdumm, schlägt blödsinnige Tools vor, versteht nicht immer, was kostenlos bedeuten soll, hält jeden möglichen Bug-Fix für DEN EINEN FIX SIE ALLE ZU FIXEN ... Insgesamt waren dann doch rund 6 Stunden Iterationen und sehr deutliche Anweisungen nötig, um das Ziel zu erreichen.
Das finale Prozedere:
- Bild per Drag&Drop an Chat schicken
- Bot schickt Bild an die API von DeepDetect.app
- DeepDetect.app analysiert das Bild und antwortet via ngrok im Chat
Nun, das war die Kurzversion, von außen. Hier mal die einzelnen Teile:
Bot: Der eigentliche Bot ist ganz fix per BotFather angelegt, Ergebnis: API-Schlüssel
Bot-Code: Rund 120 Zeilen Python-Code, die in etwa so arbeiten:
- Bot wird gestartet (samt eines Flask-Servers)
- Upload des Bilds
- Bot lädt Bild lokal herunter
- Bot übergibt das Bild der DeepDetect-API (plus Metadaten-Krempel)
- DeepDetect akzeptiert das Bild (und macht Metadaten-Krempel)
- DeepDetect analysiert das Bild
- DeepDetect triggert einen öffentlichen Webhook (ngrok-Account + lokale Installation)
- Webhook bekommt als Payload (Inhalt) die Bild-Analyse als JSON (plus Metadaten-Krempel)
- Der öffentliche ngrok-Webhook leitet an die lokale Installation weiter
- Lokale ngrok-Installation leitet an den Flask-Server des Bots weiter
- Bot schickt das Ergebnis an Telegram (in vereinfachter Form)
Im Grunde ist das alles ziemlich straight forward, außer dem ngrok-Kram. Das Bild aus Telegram an DeepDetect.app weiterzuleiten ist simpel. Aber dann muss von DeepDetect.app aus zurück an Telegram gemeldet werden. Die einzige Möglichkeit hier: Man kann in den DeepDetect.app-Einstellungen eine öffentlich erreichbare URL für Webhooks anlegen. Diese werden getriggert, sobald ein neues Bild analysiert wurde, egal woher es kommt.

Das Triggern des Webhooks heißt im Grunde nur, dass eine HTML-Anfrage an die URL gestellt wird, mit dem Analysebericht als Payload (also Fracht/Inhalt). Und ngrok ist wohl die bekannteste Plattform, um so einen öffentlichen Webhook (kostenlos) zu betreiben.

ngrok gibt dazu nach Anmeldung eine öffentliche URL heraus - und leitet Anfragen an diese an die lokale ngrok-Installation weiter. Bot und ngrok laufen hier einfach auf meinem LAN-Server. Und die lokale ngrok-Installation wiederum leitet an den laufden Flask-Server weiter, der Teil des Bots ist. Wer es nicht kennt: Flask ist im Grunde ein superminimaler Webserver, sowas wie Apache für "mal eben was hosten".
Und damit hat der Bot also letztlich den Analysebericht bekommen und kann daraus die gewünschten Infos auslesen und senden. DeepDetect.app liefert eine ausführliche Begründung, ...

... ich habe einfach eine Einschätzung samt Wahrscheinlichkeit gewählt:

Problemchen
Mein erster Ansatz sollte ohne Webhooks auskommen: Polling. Sprich der Bot sollte regelmäßig bei DeepDetect.app nachfragen, ob ein Ergebnis zur Verfügung steht. Das ist aber an vielen Kleinigkeiten gescheitert.
Der Webhook-Ansatz hat auch nicht sofort funktioniert, vor allem wegen des Metadaten-Krempels. Die IDs der Bilder stimmten nicht überein, also war es nicht möglich, Chats und Bilder und Analysen zuzuordnen und ... ach, die Details sind egal. Jedenfalls hat ChatGPT dann irgendein Mapping erstellt.
DeepDetect.app ist übrigens auch nicht perfekt: Zwar war es auf die Schnelle die einzige KI-Erkennung mit kostenlosem API-Zugriff, aber es sind nur 10 Zugriffe gratis - Trial&Error als Souls-like 😉 Schlimmer: DeepDetect.app bietet viele Services, neben KI- zum Beispiel auch Fake- oder Promi-Erkennung. Den gewünschten Service muss man für die API allerdings als Code angeben - der wiederum nicht dokumentiert und nur über die API zu bekommen ist (oder Spielereien mit den Browser-Dev-Tools). Übrigens: ChatGPT konnte mir nicht sagen, wie man an diese Service-Codes kommt. Nur mal so nebenbei.
Production ready
Wollte man das Ganze nun als echten Bot für die reale Welt aufbereiten, bräucht es noch etwas Arbeit:
- Bot und Webhook müssten auf öffentlichem Server laufen.
- Der Bot bräuchte eine GUI, damit er über Telegram konfiguriert werden könnte.
- Datenschutzgedanken müssten sich gemacht werden.
- Als SaaS-Angebot müssten Kosten durchkalkuliert werden (bei DeepDetect.app immerhin 5 Cent pro API-Anfrage).
- Die Antworten sollten ausführlich sein und vielleicht verlinkt werden.
- Der Fallback-Teil aus dem Python-Code sollte umgeschrieben werden.
Oder man guckt sich mal "Automated AI image analysis and response via Telegram", ein Ready-to-use-Produkt auf der Low-Code-Plattform n8n.io, an. Kostet aber.
Fazit
Solche automatischen Analyse-Bots könnten für Gruppen-Admins durchaus interessant sein. Sei es, um bestimmte Arten von Inhalten zu erkennen und zu sperren. Oder um sie als Fake oder KI-generiert zu kennzeichnen. Oder schlicht, um die Inhalte in der Gruppe zu analysieren.
Es gibt fertige Produkte, aber es ist auch nicht allzu kompliziert, sich mal eben selbst etwas zu basteln. Ich meine, um den Python-Code musste ich mich (ausnahmsweise mal) gar nicht kümmern. Den genauen Workflow konnte ich recht einfach gemeinsamt mit ChatGPT erarbeiten. Lediglich, wenn es an die Details ging, musste ich dann mehr selber denken.
Beispielsweise hat der Upload-Part beim Polling-Ansatz funktioniert, beim Webhook-Ansatz nicht. Also musste ich ChatGPT dazu bringen, zwei Teile aus zwei unterschiedlichen Ansätzen zu kombinieren - was jetzt nicht mit dem ersten Prompt funktioniert hat ...
Was man bei solchen Projektchen nie unterschätzen sollte: Die Auswahl der Tools frisst ordentlich Zeit. Es ist ja nicht so, als hätte ChatGPT sofort DeepDetect.app, Webhooks und ngrok vorgeschlagen -, sondern haufenweise Mist, der nicht passte.
Code
Und hier noch der Code - allerdings mehr zum Lernen gedacht. Wenn Ihr die Abhängigkeiten installiert und
- Bot-API-Key,
- DeepDetect.app-API-Key und
- ngrok-Webhook-URL
angebt, könnte/sollte es aber funktionieren. Falls das wirklich jemand probieren will, kleiner Tipp: Lokales ngrok und Flask-Server müssen mit demselben Port laufen - bei ngrok wird er beim Start angegeben, der Flask-Port steht ganz unten im Code.
import os
import requests
from flask import Flask, request, abort
from telegram import Bot
from telegram.ext import Updater, MessageHandler, Filters, CallbackContext
from telegram import Update
# === CONFIG ===
TELEGRAM_TOKEN = "ABCDE12345"
DEEPDETECT_API_KEY = "ABCDE12345"
DEEPDETECT_URL = "https://deepdetect.app/api/analyze-image"
# ACTION_CODE ist das Kürzel für den eigentlichen Service, hier KI-Erkennung.
ACTION_CODE = "x5B0jz"
WEBHOOK_SECRET = None
PUBLIC_WEBHOOK_URL = "https://1234567890.ngrok-free.app/webhook"
bot = Bot(token=TELEGRAM_TOKEN)
app = Flask(__name__)
# Map media_id -> chat_id/message_id
pending = {}
# === Upload image to DeepDetect ===
def submit_to_deepdetect(file_path, chat_id, message_id):
headers = {
"Accept": "application/json",
"dd-api-key": DEEPDETECT_API_KEY
}
with open(file_path, "rb") as f:
files = {"image": f}
data = {
"action": ACTION_CODE,
"webhook_url": PUBLIC_WEBHOOK_URL
}
r = requests.post(DEEPDETECT_URL, headers=headers, files=files, data=data)
try:
resp = r.json()
except Exception as e:
print("Error parsing response:", e, r.text)
return False
if resp.get("result") == "success":
# DeepDetect gives us media_id and media_url
media_id = resp.get("media_id")
if media_id:
pending[str(media_id)] = (chat_id, message_id)
return True
else:
print("DeepDetect error:", resp)
return False
# === Telegram handler ===
def handle_image(update: Update, context: CallbackContext):
photo = update.message.photo[-1] # highest resolution
file = context.bot.getFile(photo.file_id)
file_path = f"{photo.file_id}.jpg"
file.download(file_path)
submitted = submit_to_deepdetect(file_path, update.message.chat_id, update.message.message_id)
os.remove(file_path)
if submitted:
update.message.reply_text("🔍 Image submitted for AI detection. Waiting for results...")
else:
update.message.reply_text("⚠️ Failed to submit image to DeepDetect.")
# === Webhook endpoint ===
@app.route('/webhook', methods=['POST'])
def webhook():
if WEBHOOK_SECRET:
received_secret = request.headers.get("X-DeepDetect-Secret")
if received_secret != WEBHOOK_SECRET:
abort(403)
data = request.json
print("Webhook received:", data)
media_id = str(data.get("media_id"))
result = data.get("result", {})
print("Pending keys:", list(pending.keys()))
print("Webhook media_id:", media_id)
# Default fallback: pick the most recent chat_id if exact match fails
chat_id = None
if media_id in pending:
chat_id, _ = pending.pop(media_id)
elif pending:
# fallback: last stored entry
chat_id, _ = list(pending.values())[-1]
print(f"⚠️ media_id mismatch, using fallback chat_id {chat_id}")
if chat_id:
is_ai = result.get("is_ai_generated", False)
confidence = result.get("ai_confidence_score", 0.0)
try:
if is_ai:
text = f"🚨 AI-generated likely! (confidence: {confidence:.2f})"
else:
text = f"✅ Authentic-looking (confidence: {confidence:.2f})"
bot.send_message(chat_id=chat_id, text=text)
print("✅ Sent result to Telegram")
except Exception as e:
print("❌ Error sending Telegram message:", e)
else:
print("❌ No chat_id found for this webhook")
return {"status": "ok"}, 200
# === Run bot + Flask server ===
def main():
updater = Updater(TELEGRAM_TOKEN, use_context=True)
dp = updater.dispatcher
dp.add_handler(MessageHandler(Filters.photo, handle_image))
updater.start_polling()
print("Bot and webhook server running...")
app.run(host="0.0.0.0", port=5000)
if __name__ == "__main__":
main()