Akış

wss wss://ws.xsignalfeed.com/v1/stream

Bağlanma

Akış, anahtarınızı REST ile aynı üç yoldan kabul eder. Sunucudan başlık kullanın; URL parametresini yalnızca başlık ayarlanamayan yerlerde kullanın. Anahtar ulaşmazsa ya da kabul edilmezse bağlantı açılır ve hemen 4001 ile kapanır; kapanma nedeni sebebini söyler.

Anahtarın gönderilme yoluNe zaman kullanılır
Authorization: Bearer xsf_…Sunucular için önerilir; REST ile aynı başlık
X-API-Key: xsf_…Yukarıdakiyle eşdeğer
?api_key=xsf_…Tarayıcılar ve el sıkışmada başlık ayarlayamayan istemciler. Anahtar URL'nin parçası olur; bu tür URL'leri günlüklerin dışında tutun
python — anahtar başlıkta
import websockets

async with websockets.connect("wss://ws.xsignalfeed.com/v1/stream",
                              additional_headers={"Authorization": "Bearer xsf_your_key"}) as ws:
    print(await ws.recv())    # {"t": "system.hello", ...}
Sorgu parametresiAnlamı
api_keyBaşlığı ayarlayamadığınızda anahtarınız
last_idBu sid değerinden sonra devam et. Anahtarda replay kapsamı yoksa sessizce yok sayılır
import asyncio, json, websockets

async def main():
    url = "wss://ws.xsignalfeed.com/v1/stream?api_key=xsf_your_key"
    async with websockets.connect(url) as ws:
        async for raw in ws:
            ev = json.loads(raw)
            if ev["t"].startswith("system."): continue
            print(ev["t"], ev["target"]["screen_name"], ev["d"].get("text", "")[:60])

asyncio.run(main())

Çerçeve

Üç çerçeve X'in değil, bizimdir:

ÇerçeveNe zaman
system.helloİlk çerçeve. targets, bu anahtarın şu anda izlediği hesap sayısıdır (sonradan eklenen hesaplar yeniden bağlanmadan katılır); replay_from, yeniden bağlanırken gönderdiğiniz last_id değerini geri verir, hiç göndermediyseniz null olur ve bu durumda hiçbir şey yeniden oynatılmaz
system.pingSessizlik sırasında canlı tutma amacıyla gönderilir; boştaki proxy'ler soketi kapatmasın diye
system.errorBağlantıda bir sorun var; ardından kapanış gelir

Kapanış kodu

El sıkışma her zaman başarılı olur ve kapanış hemen ardından gelir; böylece istemci kütüphaneniz çıplak bir HTTP hatası yerine kodu ve nedeni görür.

Kapanış koduAnlamı
1012Bakım sırasında hizmetin yeniden başlatılması. Geri çekilmeyle yeniden bağlanın ve işlediğiniz son sid değerini ?last_id= olarak gönderin: kesinti sırasındaki olaylar yeniden oynatılır, hiçbir şey kaybolmaz
4001Anahtar kabul edilmedi. Kapanma nedeni sebebini söyler: missing_api_key (bize hiç anahtar ulaşmadı: başlık adını ya da proxy'nizin veya istemci kütüphanenizin onu iletip iletmediğini kontrol edin), invalid_api_key (böyle bir anahtar yok: yazım hatası ya da döndürmeyle değişmiş bir gizli anahtar), key_revoked (anahtar iptal edildi)
4002Bu anahtar için çok fazla eşzamanlı bağlantı; kapanıştan önce bir system.error çerçevesi gelir
4003Anahtarda stream kapsamı yok

Doğru yeniden bağlanma

Bunu naif sürümüyle değil, bir kez doğru yazın. Önemli olan iki şey üstel geri çekilme ve sid değerini süreç yeniden başlatmasını atlatacak bir yerde kalıcı saklamaktır.

python — üretim biçimi
import asyncio, json, pathlib, random, websockets

STATE = pathlib.Path("xsf.cursor")          # survives restarts; a DB row is better still

async def run(key, handle):
    backoff = 1
    while True:
        last = STATE.read_text().strip() if STATE.exists() else None
        url = f"wss://ws.xsignalfeed.com/v1/stream?api_key={key}" + (f"&last_id={last}" if last else "")
        try:
            async with websockets.connect(url, ping_interval=20, max_size=2**22) as ws:
                backoff = 1
                async for raw in ws:
                    ev = json.loads(raw)
                    if ev["t"].startswith("system."): continue
                    handle(ev)                      # must be idempotent: dedupe on ev["id"]
                    if ev.get("sid"): STATE.write_text(ev["sid"])   # only after handling
        except Exception as e:
            print("disconnected:", e)
        await asyncio.sleep(backoff + random.random())   # jitter, or every client returns at once
        backoff = min(60, backoff * 2)