Harici İşleyici
Harici işleyici, kodunuz ile Telegram arasında bir köprüdür. Yapıcının mantığı yetmediğinde, belirli bir tepkiyi kendi sunucunuza devredersiniz: sunucu olayları alır ve Telegram Bot API formatında komutlarla yanıt verir; taşıma, teslim ve tüm Telegram işlemleri GetMyBot tarafından üstlenilir.
Bu nedir
GetMyBot'taki tepkiler görsel olarak oluşturulur: tetikleyici → koşullar → eylemler. Karmaşık veya standart dışı mantığı — kendi veritabanınızı, hesaplamaları, harici sistemlere yapılan çağrıları, makine öğrenmesini, dallanan senaryoları — yapıcıda ifade etmek güçtür. Harici işleyici bu tavanı kaldırır: kendi backend'inizi bağlar ve tüm tepkilerin işlenmesini ona devredersiniz.
Harici servis, GetMyBot'tan olayları alır (tetikleyici çalıştı, kullanıcı metin yanıtladı, düğmeye tıkladı) ve karşılığında bota ne göndereceğini söyler. GetMyBot, komutları kendi bot token'ı ile uygular — rate-limit, yeniden denemeler, deduplication ve diyalog günlüğü bunun üzerinde çalışır.
Çalışma modeli
- GetMyBot bir WebSocket sunucusudur. Servisiniz kendisi bağlanır ve genel bir adrese veya webhook uç noktasına ihtiyaç duymaz. GetMyBot, servisinize giden bağlantı yapmaz; bu nedenle SSRF yüzeyi yoktur.
- Kimlik doğrulama — entegrasyon token'ı ile. Servis, bağlantıda token'ı sunar; GetMyBot bunu hash ile doğrular ve bağlantıyı açık tutar.
- Olaylar ve komutlar — Telegram Bot API formatında. Servis bir olay alır ve yanıt olarak "metot + parametreler" biçiminde çağrı dizisi gönderir; aynen normal bir botla çalışırken olduğu gibi.
- Komutlar GetMyBot tarafından kendi token'ıyla uygulanır. Servis asla doğrudan Telegram ile iletişim kurmaz: komutlar doğrulamadan geçer ve GetMyBot'un dahili outbox'ına girer; oradan rate-limit, yeniden denemeler, deduplication ve günlükle birlikte bot token'ı aracılığıyla gönderilir.
Tek bir bağlantı, bir entegrasyonun tüm diyaloglarına hizmet eder — farklı kullanıcıların olayları çoğullanır ve session_id alanıyla ayırt edilir.
Entegrasyon kurulumu
- Sol menüde Entegrasyonlar bölümünü açın ve Entegrasyon Ekle düğmesine tıklayın.
- Harici İşleyici servisini seçin ve bir ad belirleyin.
- Oluşturulduktan sonra kart şunları gösterir:
- WebSocket adresi —
wss://api.mybot.app/ext/ws/<integrationID>biçiminde;<integrationID>, bu entegrasyonun UUID'sidir. Servisiniz bu adrese bağlanır. Yolda id olmadan bağlantı kurulamaz. - Bağlantı token'ı — oluşturulurken yalnızca bir kez gösterilir. Kopyalayın ve güvenli bir yerde saklayın; token tekrar görüntülenemez (yalnızca hash olarak saklanır).
- Token'ı yenile — düğme yeni bir token üretir ve eskisini hemen geçersiz kılar. Yenilemeden sonra token'ı servisinizde güncelleyin.
- Çevrimiçi göstergesi — servisinizin şu anda aktif bir bağlantı tutup tutmadığını gösterir.
- WebSocket adresi —
Protokolü etkileyen ek entegrasyon parametreleri:
session_ttl_seconds— saniye cinsinden oturum ömrü (varsayılan3600).on_unavailable_reaction_id— tetikleme anında servis çevrimdışıysa başlatılan yedek tepki (bkz. Güvenilirlik).
Tepkiye bağlama
Harici işleyici ayrı bir tetikleyici olarak değil, bir eylem olarak bağlanır. Tepki editörüne Harici İşleyiciye Aktar eylemini ekleyin ve ilgili entegrasyonu seçin.
Diyalogu herhangi bir mevcut GetMyBot tetikleyicisi açabilir — komut, metin, düğme tıklaması, bağlantıdan gelen parametre, gelen web isteği, zamanlama. Böyle bir tetikleyici çalıştığında ve eyleme ulaştığında, GetMyBot bir proxy oturumu açar ve servise session.open olayı gönderir.
Bu sırada servis bağlı değilse, GetMyBot entegrasyon ayarından yedek tepkiyi (on_unavailable_reaction_id) başlatır. Yedek tanımlanmamışsa — hiçbir şey olmaz (kullanıcıya hata gösterilmeden sessizce).
Bağlantı ve yetkilendirme
Uç nokta: WebSocket (wss) üzerinden GET /ext/ws/{integrationID}. integrationID — "Harici İşleyici" türündeki entegrasyonun UUID'si. Kare boyutu sınırı — 256 KiB.
İki yöntemden biriyle yetkilendirilebilir.
1. El sıkışmada başlık (önerilen). Token'ı Authorization başlığında iletin:
Authorization: Bearer <token>
2. Auth karesiyle. Bearer başlığı iletilmemişse, bağlantı kurulduktan sonra 10 saniye içinde ilk kare olarak şunu gönderin:
{ "type": "auth", "token": "<token>" }
10 saniye içinde auth karesi gelmezse — bağlantı 4401 koduyla kapatılır. Her iki yöntemde de yanlış token — yine 4401 kodu ile kapatma.
Token, entegrasyon oluşturulurken üretilir, bir kez gösterilir ve yalnızca hash (sha256) olarak saklanır; doğrulama sabit süreli yapılır. Token rotasyonu:
POST /api/bots/{botID}/integrations/{integrationID}/rotate-token
Uç nokta yeni düz metin token döndürür; eski token hemen çalışmayı durdurur.
Olaylar: bot → servis
Her olay bir JSON karesidir (EventEnvelope). type alanı şunlardan biridir: session.open, message, callback, session.cancel, session.expired.
Zarfın tam alan kümesi:
{
"type": "session.open",
"session_id": "string",
"bot_id": "string",
"user": {
"tg_user_id": 123456789,
"first_name": "Ivan",
"username": "ivan",
"params": { "utm": "promo" }
},
"chat": { "id": 123456789, "type": "private" },
"update": { "...": "ham Telegram Update (raw JSON)" },
"event": { "...": "normalleştirilmiş GetMyBot olayı (raw JSON)" }
}
session_id— oturum (diyalog) tanımlayıcısı.bot_id— bot tanımlayıcısı.user— kullanıcı verileri:tg_user_id(int64), isteğe bağlıfirst_name,usernameveparams— kullanıcı parametreleri (bağlantıdan gelenler dahil), anahtar→değer map'i.chat— sohbet:id(int64) vetype(örneğin"private").update— ham Telegram Update (raw JSON).session.open,message,callbackiçin mevcuttur.event— normalleştirilmiş GetMyBot olayı (raw JSON).
Türlere göre içerik farklılık gösterir:
session.open— tetikleyici çalıştı, yeni diyalog açıldı.update(ham Update) veevent(tam normalleştirilmiş olay) mevcuttur,user.paramsdoldurulmuştur.message— servis "bekleme tuttuğunda" (expect=text/any) ve kullanıcı mesaj gönderdiğinde gelir. İçeriksession.openile aynıdır.callback— kullanıcı, daha önce servisin gönderdiği bir düğmeye tıkladı.updateham;user'da yalnızcatg_user_iddoldurulmuştur;eventyalnızca servisin düğmede belirlediği orijinal callback_data'yı içerir:
{ "callback_data": "<servisin düğmede belirlediği orijinal değer>" }
session.cancel/session.expired— minimum zarf:session_id,bot_id,user.tg_user_id,chat.id(canceliçin ayrıcachat.type).update/eventalanları yoktur. Bu olaylar yalnızca servis çevrimiçiyse teslim edilir — çevrimdışı kuyruğuna konulmaz.
Komutlar: servis → bot
Komut bir JSON karesidir (CommandEnvelope). type alanı şunlardan biridir: execute, session.close, auth, ping, pong.
{
"type": "execute",
"session_id": "string",
"methods": [
{ "method": "sendMessage", "params": { "text": "Merhaba" } }
],
"expect": "none"
}
session_id— komutun ait olduğu oturum.token— yalnızcatype: "auth"için (bkz. Bağlantı ve yetkilendirme).methods—{ "method": "<Telegram Bot API metot adı>", "params": { ... } }nesnelerinden oluşan dizi. Metot adı, Telegram Bot API'deki ile birebir aynıdır (örneğinsendMessage);paramsise bu metodun parametre nesnesidir.expect— servisin kullanıcı yanıtı bekleyip beklemediği:"none","text"veya"any"(boş değernoneolarak yorumlanır).session.close— diyalogu açıkça kapat.
Komutlar doğrudan Telegram'a gitmez: GetMyBot bunları doğrulayarak kendi outbox'ına koyar; oradan rate-limit, yeniden denemeler, deduplication ve günlükle birlikte bot token'ı aracılığıyla gönderilir.
execute nasıl işlenir
Şu durumlarda execute komutu tamamen düşürülür: session_id boşsa; oturum bulunamazsa veya open durumunda değilse; oturum başka bir entegrasyona aitse; oturum süresi dolmuşsa.
Ardından:
- Rate-limit: oturum başına dakikada 60
execute(kayan pencere). Limitin üzerinde — düşürme. - Tek bir
execute'ta en fazla 30 metot; fazlası sessizce atılır. - Her metot için whitelist kontrolü yapılır (bkz. İzin verilen metodlar) — listede olmayan metot reddedilir.
- Chat-guard:
params'tachat_idveyafrom_chat_iddeğeri0'dan farklı ve oturumunchat_id'siyle eşleşmiyorsa — metodun tamamı reddedilir (başka bir sohbete mesaj gönderilemez).chat_idhiç belirtilmeyebilir: GetMyBot oturum sohbetini zorunlu olarak atar. callback_dataiçeren inline düğmeler otomatik olarak token'a dönüştürülür (dahili formatx:<token>); düğme ömrü = oturum TTL'sine kadar.url/webapp/switch_inlinedüğmelerine dokunulmaz.
İzin verilen metodlar
Servis, botu kendi token'ıyla yönetir; bu nedenle metot kümesi whitelist ile sınırlıdır — yalnızca mevcut diyalog mesajlarının gönderilmesi ve yönetimi. Listede olmayan metodlar sessizce yok sayılır (bu bir hata değildir).
- gönderme:
sendMessage,sendPhoto,sendDocument,sendVideo,sendAudio,sendMediaGroup,sendAnimation,sendVoice,sendLocation,sendChatAction; - düzenleme ve silme:
editMessageText,editMessageCaption,editMessageReplyMarkup,deleteMessage; - tıklamaya yanıt:
answerCallbackQuery; - iletme ve kopyalama:
forwardMessage,copyMessage; - sabitleme:
pinChatMessage,unpinChatMessage.
Hesap düzeyindeki metodlar (setWebhook, getUpdates, logOut, close, setMyCommands vb.) izin verilmez.
Bekleme ve oturum yaşam döngüsü
Her execute sonrasında oturumun durumu expect değerine ve komutta callback_data içeren inline düğme olup olmadığına bağlıdır:
expect=textveyaany— kullanıcının bir sonraki mesajımessageolayıyla servise iletilir.expect=noneVE komutta callback'li inline düğme YOK — oturum otomatik olarak kapanır. Bu "terminal" mesajdır.expect=none, ANCAK callback düğmeleri VAR — oturum açık kalır: tıklamalar, düğme token'ları (TTL'ye kadar) yaşarken yakalanır.
Önemli: expect, düğme tıklamalarının alımını etkilemez. Token'lı düğmelere tıklamalar, expect değerinden bağımsız olarak — oturum ve düğme token'ı yaşadığı sürece — yakalanır. expect yalnızca servisin metin/isteğe bağlı yanıt bekleyip beklemediğini kontrol eder.
Diyalog sınırları
Diyalog bağlamı, oturum açık olduğu sürece yaşar:
- Aktif bekleme sırasında metin yanıtı (
expect=text/any) — botun normal tepkilerini başlatmak yerinemessageolayıyla servise gönderilir. - Token'lı düğmeye tıklama — orijinal
callback_datailecallbackolayı olarak servise gönderilir. GetMyBot her zaman tıklamayı kendisi onaylar (answerCallbackQuery); tıklamanın aidiyeti (bot + kullanıcı + oturum sohbeti) kontrol edilir. Düğme, oturumu kapatmaz. /cancel(ayrıca/cancel@botve "iptal") — aktif harici oturumda — oturum kapanır, servisesession.cancelgönderilir, kullanıcıya "İptal edildi." gönderilir.- Kullanıcı başına bir diyalog. Yeni oturum açılması, bu kullanıcının önceki açık oturumunu geçersiz kılar — ona
session.cancelgönderilir. - TTL süresi dolumu. Zamanlayıcıyla oturum
expiredolarak işaretlenir ve (servis çevrimiçiyse) servisesession.expiredgönderilir.
Limitler ve zaman aşımları
- Kare boyutu: 256 KiB.
- Oturum TTL'si: varsayılan 3600 saniye (entegrasyonun
session_ttl_secondsparametresiyle ayarlanabilir). - Komut sıklığı: oturum başına dakikada 60
execute(kayan pencere). - Bir
execute'taki metot sayısı: en fazla 30 (fazlası atılır). - Entegrasyon başına açık oturum: en fazla 1000.
- Çevrimdışı kuyruğu: oturum başına en fazla 100 olay.
- Heartbeat: her 30 saniyede bir
ping; aktivite eksikliği zaman aşımı — 60 saniye. - Auth karesi zaman aşımı: 10 saniye.
Güvenilirlik (heartbeat, çevrimdışı, kuyruk, fallback)
- Heartbeat. Sunucu her 30 saniyede bir
{"type":"ping"}karesi gönderir. İstemciden 60 saniyeden fazla aktivite yoksa — bağlantı kapatılır. İstemci, aktifliği korumak için kendiping/pong'larını gönderebilir. Bağlantı kesilmesi diyalogları öldürmez: oturumlar TTL'ye veya yeniden bağlanmaya kadar veritabanında yaşar. - Yeniden bağlanma — servis tarafında. Bağlantı koptuğunda servisiniz yeniden bağlanmalıdır. Veritabanındaki açık oturumlar TTL dolana kadar yeniden başlatmaları atlatır.
- Başlangıçta çevrimdışı fallback. Tepki tetiklendiğinde servis bağlı değilse — entegrasyon ayarından yedek tepki başlatılır (
on_unavailable_reaction_id). Tanımlanmamışsa — hiçbir şey olmaz (sessizce). - Çevrimdışı kuyruğu. Çevrimdışı nedeniyle teslim edilemeyen
message/callbackolayları çevrimdışı kuyruğuna eklenir (en fazla 100 olay, FIFO, oturum süresine kadar saklanır) ve yeniden bağlandığında teslim edilir.session.open/session.cancel/session.expiredolayları kuyruğa konulmaz. - Teslim garantisi — en fazla bir kez (at-most-once). Kuyruk dolması veya süresinin dolması durumunda olaylar atılır. Tek bir olayın atlanmasının senaryoyu bozmaması için mantığınızı buna göre tasarlayın.
Çevrimiçi göstergesi
Servisin aktif bağlantı tutup tutmadığı şu uç nokta ile kontrol edilebilir:
GET /api/bots/{botID}/integrations/{integrationID}/status
Yanıt:
{ "online": true }
Aynı gösterge, yönetim panelindeki entegrasyon kartında da mevcuttur. MCP'deki karşılığı — get_integration_status aracı.
Güvenlik
GetMyBot, harici bir servisin komutlarını kendi token'ıyla yürütür; bu nedenle koruma katıdır.
- SSRF yüzeyi yoktur. GetMyBot bir WebSocket sunucusu olarak hareket eder ve servise giden bağlantı yapmaz — servistir bağlanan taraf. Platformun dışarıdan kontrol edilebilir bir URL'ye gittiği durum söz konusu değildir.
- Token hash olarak saklanır (sha256), doğrulama sabit süreli yapılır, rotasyon desteklenir.
- Kiracı izolasyonu. Komut kendi entegrasyonuna sıkı sıkıya bağlıdır; oturum — bota + kullanıcıya + sohbete. Diğer botların olayları sokete gelmez.
- Metot whitelist'i + zorunlu
chat_id, botu rastgele sohbetlere mesaj göndericiye dönüştürmez. - Bot token'ı dışarıya iletilmez — servis hiçbir zaman doğrudan Telegram ile iletişim kurmaz.
- Gizli değerlerin maskelenmesi. Entegrasyon token'ı ve hassas değerler günlük ve loglarda gizlenir.
Örnekler
Minimum işleyici: diyalog açıldığında mesaj gönderir ve oturumu kapatır (expect: "none"). Entegrasyon id'sini ve token'ı yerine koyun. Adres, yolda zorunlu olarak <integrationID> içermelidir.
Node.js
import WebSocket from "ws";
const URL = `wss://api.mybot.app/ext/ws/${process.env.MYBOT_INTEGRATION_ID}`;
const ws = new WebSocket(URL, {
headers: { Authorization: `Bearer ${process.env.MYBOT_TOKEN}` },
});
ws.on("message", (raw) => {
const ev = JSON.parse(raw);
if (ev.type === "session.open") {
ws.send(JSON.stringify({
type: "execute",
session_id: ev.session_id,
expect: "none",
methods: [{ method: "sendMessage", params: { text: "Harici işleyiciden merhaba!" } }],
}));
}
});
Python
import json, os, asyncio, websockets
async def main():
url = f"wss://api.mybot.app/ext/ws/{os.environ['MYBOT_INTEGRATION_ID']}"
headers = {"Authorization": f"Bearer {os.environ['MYBOT_TOKEN']}"}
async with websockets.connect(url, additional_headers=headers) as ws:
async for raw in ws:
ev = json.loads(raw)
if ev["type"] == "session.open":
await ws.send(json.dumps({
"type": "execute",
"session_id": ev["session_id"],
"expect": "none",
"methods": [
{"method": "sendMessage", "params": {"text": "Harici işleyiciden merhaba!"}}
],
}))
asyncio.run(main())
Inline düğme ve callback işleme
Tıklamayı yakalamak için callback_data içeren bir düğme gönderin (GetMyBot otomatik olarak token'a dönüştürür). expect: "none" ile düğmeli oturum, düğme token'ı yaşadığı sürece açık kalır — tıklama, event.callback_data'sının servisin düğmede belirlediği orijinal değere eşit olduğu callback olayıyla gelir. Tıklamayı onaylamaya (answerCallbackQuery) gerek yoktur — GetMyBot bunu kendisi yapar.
if (ev.type === "session.open") {
ws.send(JSON.stringify({
type: "execute",
session_id: ev.session_id,
expect: "none",
methods: [{
method: "sendMessage",
params: {
text: "Düğmeye tıklayın",
reply_markup: { inline_keyboard: [[{ text: "Haydi", callback_data: "go" }]] },
},
}],
}));
} else if (ev.type === "callback" && ev.event.callback_data === "go") {
ws.send(JSON.stringify({
type: "execute",
session_id: ev.session_id,
expect: "none",
methods: [{ method: "sendMessage", params: { text: "Düğmeye basıldı!" } }],
}));
}
Sırada ne var
- Entegrasyonlar — bağlanabilir servislere genel bakış.
- Tepkiler — tetikleyiciler, koşullar ve eylemler nasıl oluşturulur.
- Web istekleri ve webhook'lar — diyalogsuz harici URL çağırmanın daha basit yolu.