تمت ترجمة هذه الصفحة آليًا. النسخة الإنجليزية هي المصدر وقد تكون أكثر دقة أو أحدث. العرض بالإنجليزية

Browser WebSocket

اتصل بواجهة finlight.me WebSocket API مباشرةً من متصفّح الويب باستخدام واجهة WebSocket الأصلية. وهذا مثالي للوحات التحكم ومنصّات التداول وأي تطبيق واجهة أمامية يحتاج إلى تحديثات مقالات في الوقت الفعلي دون وكيل من جانب الخادم.


كيف يعمل

  1. اتصل بـ wss://wss.finlight.me (مُثرى) أو wss://wss.finlight.me/raw (raw) مع مفتاح API الخاص بك كمعامل استعلام
  2. اشترك بإرسال رسالة JSON تتضمّن معايير التصفية وclientNonce
  3. استقبِل رسالة admit تؤكّد اتصالك، تليها رسائل sendArticle فور وصول المقالات
  4. حافظ على الاتصال حيًّا بإرسال رسائل ping كل 25 ثانية
  5. اقطع الاتصال باستدعاء ws.close()

عناوين URL للاتصال

  • Name
    مُثرى
    Type
    wss://wss.finlight.me
    Description

    مقالات بإثراء كامل: تحليل المشاعر، واستخراج الكيانات، والفئات، والمحتوى الكامل (حسب فئة اشتراكك).

  • Name
    Raw
    Type
    wss://wss.finlight.me/raw
    Description

    مقالات raw منخفضة الكمون دون إثراء. الأفضل لحالات الاستخدام التي تكون فيها السرعة أولوية وتحتاج إلى المقالات بأسرع ما يمكن.

معاملات الاستعلام

  • Name
    apiKey
    Type
    string
    Description

    مفتاح finlight API الخاص بك. يُستخدم للمصادقة لأن WebSocket المتصفّح لا يمكنه تعيين ترويسات مخصّصة.

  • Name
    takeover
    Type
    string
    Description

    عيّنه إلى "true" لاستبدال أقدم اتصال تلقائيًا عند بلوغ حدّ الاتصالات المتزامنة.

  • Name
    clientVersion
    Type
    string
    Description

    معرّف اختياري لتطبيق العميل الخاص بك. مثل "my-dashboard/1.0"


رسالة الاشتراك

بعد فتح الاتصال، أرسل رسالة JSON للاشتراك في المقالات. سيردّ الخادم برسالة admit ثم يبدأ بدفع المقالات المطابقة.

  • Name
    clientNonce
    Type
    string
    Description

    معرّف فريد (مثل UUID) لطلب الاشتراك هذا. يعيده الخادم في استجابة admit.

  • Name
    query
    Type
    string
    Description

    استعلام البحث للعثور على المقالات ذات الصلة. يدعم الاستعلامات المتقدمة.

  • Name
    sources
    Type
    string[]
    Description

    التصفية حسب نطاقات المصادر. مثل ["www.reuters.com", "www.cnbc.com"]

  • Name
    excludeSources
    Type
    string[]
    Description

    يستبعد نطاقات مصادر محدّدة.

  • Name
    tickers
    Type
    string[]
    Description

    التصفية حسب رموز التداول. مثل ["AAPL", "NVDA"] (المُثرى فقط)

  • Name
    countries
    Type
    string[]
    Description

    التصفية حسب رموز الدول بصيغة ISO 3166-1 alpha-2. مثل ["US", "DE"] (المُثرى فقط)

  • Name
    language
    Type
    string
    Description

    التصفية حسب اللغة (ISO 639-1). القيمة الافتراضية هي en، التي تُرجع الإنجليزية فقط وتستبعد اللغات الأخرى — راجع اللغة والتغطية.


رسائل الخادم

يرسل الخادم رسائل JSON تتضمّن حقل action يشير إلى نوع الرسالة:

  • Name
    admit
    Type
    object
    Description

    تُرسَل بعد نجاح المصافحة. تتضمّن leaseId وserverNow (طابع زمني) وclientNonce الخاص بك.

  • Name
    sendArticle
    Type
    object
    Description

    مقال جديد يطابق اشتراكك. توجد بيانات المقال في حقل data.

  • Name
    pong
    Type
    object
    Description

    ردّ على نبضة ping الخاصة بك.

  • Name
    preempted
    Type
    object
    Description

    استُبدِل اتصالك بجلسة أخرى (عندما اتصل عميل آخر بـ takeover: true).

  • Name
    error
    Type
    object
    Description

    حدث خطأ. تحقّق من حقل data أو error للتفاصيل.


WEBSOCKETالمتصفّح

مثال كامل

عميل WebSocket للمتصفّح بسيط ومستقلّ عن أُطر العمل، مع إعادة اتصال تلقائية ونبضة قلب:

  • يصادِق عبر معاملات الاستعلام
  • يرسل رسالة اشتراك عند الاتصال
  • يحافظ على فاصل نبضة قلب مدّته 25 ثانية
  • يعيد الاتصال بتراجع أسّي (من 500 مللي ثانية إلى 10 ثوانٍ)
  • يعالج جميع أنواع رسائل الخادم

Browser Client

WEBSOCKET
wss://wss.finlight.me
const API_KEY = 'YOUR_API_KEY'
const WSS_URL = 'wss://wss.finlight.me' // Use '/raw' path for raw articles

let ws = null
let pingInterval = null
let reconnectTimeout = null
let reconnectAttempt = 0

function connect(filters = {}) {
  const params = new URLSearchParams({
    apiKey: API_KEY,
    takeover: 'true',
    clientVersion: 'my-app/1.0',
  })
  const url = `${WSS_URL}?${params}`

  ws = new WebSocket(url)

  ws.onopen = () => {
    console.log('Connected')
    reconnectAttempt = 0

    // Send subscription with filters
    ws.send(JSON.stringify({
      clientNonce: crypto.randomUUID(),
      query: filters.query || '',
      language: filters.language || 'en',
      sources: filters.sources || [],
      tickers: filters.tickers || [],
      countries: filters.countries || [],
    }))

    // Start heartbeat
    pingInterval = setInterval(() => {
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
          action: 'ping',
          t: Date.now(),
        }))
      }
    }, 25000)
  }

  ws.onmessage = (event) => {
    const msg = JSON.parse(event.data)

    switch (msg.action) {
      case 'admit':
        console.log('Admitted, lease:', msg.leaseId)
        break
      case 'sendArticle':
        console.log('Article:', msg.data.title)
        // Handle the article here
        break
      case 'pong':
        break // Heartbeat OK
      case 'preempted':
        console.warn('Connection replaced')
        break
      case 'error':
        console.error('Server error:', msg.data || msg.error)
        break
    }
  }

  ws.onclose = (event) => {
    clearInterval(pingInterval)

    // Don't reconnect on policy violations
    if (event.code === 1008 || event.code === 4002) {
      console.error('Connection blocked')
      return
    }

    // Exponential backoff reconnect
    const delay = Math.min(500 * 2 ** reconnectAttempt, 10000)
    reconnectAttempt++
    console.log(`Reconnecting in ${delay}ms...`)
    reconnectTimeout = setTimeout(() => connect(filters), delay)
  }

  ws.onerror = () => console.error('WebSocket error')
}

function disconnect() {
  clearInterval(pingInterval)
  clearTimeout(reconnectTimeout)
  if (ws) ws.close(1000)
}

// Usage
connect({ query: 'Nvidia', language: 'en', countries: ['US'] })

admit Response

{
  "action": "admit",
  "leaseId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
  "serverNow": 1708185600000,
  "clientNonce": "your-uuid-here"
}

sendArticle Response

{
  "action": "sendArticle",
  "data": {
    "link": "https://www.reuters.com/technology/nvidia-2026-02-17",
    "source": "www.reuters.com",
    "title": "Nvidia Reports Record Revenue",
    "summary": "Nvidia announced record quarterly revenue...",
    "publishDate": "2026-02-17T10:30:00Z",
    "language": "en",
    "sentiment": "positive",
    "confidence": 0.92,
    "countries": ["US"],
    "categories": ["markets", "technology"],
    "companies": [
      {
        "name": "NVIDIA Corporation",
        "ticker": "NVDA",
        "country": "US"
      }
    ]
  }
}

المُثرى مقابل Raw

الميزةالمُثرى (/)Raw (/raw)
تحليل المشاعرنعملا
استخراج الكيانات (الشركات)نعم (حسب الفئة)لا
الفئاتنعملا
المحتوى الكاملنعم (حسب الفئة)لا
الكمونقياسيالأدنى
المرشّح: tickersنعملا
المرشّح: countriesنعملا
المرشّح: query وsources وlanguageنعمنعم

ما الخطوة التالية؟