WebSockets (Live)

Real-time push za stat event-e, status promene i rezultate. Koristi Pusher protokol (naš server je Laravel Reverb), pa postojeći SDK-ovi rade out-of-box.

Connection config

Hoststats-api.ds2.app
Port443 (wss, preko nginx proxy-ja)
App keystats-admin-public-key
ProtocolPusher 7.x
Auth endpointhttps://stats-api.ds2.app/api/v1/broadcasting/auth

App key je javan — sigurnost dolazi od tajnog Bearer token-a na auth endpoint-u.

Kanali

Svi su private — moraš imati pretplatu na odgovarajuće takmičenje.

KanalŠta šaljeUslov pristupa
private-match.{id}.event.received (svaki shot/rebound/...), .status.changedPretplata na takmičenje tog meča
private-competition.{id}.status.changed (kad meč promeni status)Pretplata na to takmičenje
private-gamesSve .event.received i .status.changed globalnoBilo koji aktivan nalog (za ticker)

Tipovi događaja

.event.received

Novi stat event je upisan (shot, rebound, assist, itd.). Payload:

json
{
  "match_id": 123,
  "home_score": 45,
  "away_score": 42,
  "current_period": 2,
  "current_clock": "07:23",
  "status": "in_progress",
  "event": {
    "id": 9871,
    "client_id": "7b2a...uuid",
    "type": "3pt_made",
    "team_id": 16,
    "player_id": 88,
    "period": 2,
    "clock": "07:23",
    "x": 42.5,
    "y": 18.2,
    "event_at": "2026-04-13T20:15:30+00:00"
  }
}

.status.changed

json
{
  "match_id": 123,
  "competition_id": 4,
  "status": "finished",
  "previous_status": "in_progress",
  "home_score": 89,
  "away_score": 84
}

Setup (Node.js / browser)

bash
npm install laravel-echo pusher-js
echo-client.jsjavascript
import Echo from 'laravel-echo'
import Pusher from 'pusher-js'

// Pusher must be on window for laravel-echo to find it
window.Pusher = Pusher

export const echo = new Echo({
  broadcaster: 'reverb',
  key: 'stats-admin-public-key',
  wsHost: 'stats-api.ds2.app',
  wssPort: 443,
  forceTLS: true,
  enabledTransports: ['ws', 'wss'],
  disableStats: true,

  // Private channel auth — echoes our Bearer token to the server
  authEndpoint: 'https://stats-api.ds2.app/api/v1/broadcasting/auth',
  auth: {
    headers: {
      Authorization: 'Bearer ' + process.env.STATS_API_TOKEN,
    },
  },
})

Primer: prati jedan meč

javascript
import { echo } from './echo-client'

const channel = echo.private('match.123')

channel.listen('.event.received', (data) => {
  console.log(`Score: ${data.home_score} : ${data.away_score}`)
  console.log(`Last event: ${data.event.type}`)
  updateScoreboard(data)
})

channel.listen('.status.changed', (data) => {
  if (data.status === 'finished') {
    showFinalResult(data)
  }
})

// Kad završiš sa praćenjem:
echo.leave('match.123')

Primer: global ticker

javascript
const ticker = echo.private('games')

ticker.listen('.event.received', (data) => {
  // Svaki nov event iz bilo kog meča u sistemu
  refreshTickerCard(data.match_id, data.home_score, data.away_score)
})

ticker.listen('.status.changed', (data) => {
  // Live dot menja status u ticker karuselu
  refreshTickerStatus(data.match_id, data.status)
})

Reconnect i error handling

Pusher klijent automatski reconnect-uje. Za robustnost dodaj handler:

javascript
echo.connector.pusher.connection.bind('error', (err) => {
  console.error('WS error:', err)
})

echo.connector.pusher.connection.bind('connected', () => {
  console.log('WS connected — refetch state from HTTP API to catch missed updates')
  // Re-fetch box score / standings via /api/v1 to backfill gap
})

echo.connector.pusher.connection.bind('disconnected', () => {
  console.warn('WS disconnected — pusher-js will auto-reconnect')
})

PHP / Python / drugi jezici

Pusher protokol ima zvanične SDK-ove za većinu jezika. Config je uvek isti:key=stats-admin-public-key, host=stats-api.ds2.app,port=443, tls=true, auth endpoint =/api/v1/broadcasting/auth sa Bearer header-om.

  • PHP: pusher/pusher-php-client — ali retko treba (obično server-side PHP ne subscribe-uje)
  • Python: pusherclient ili pysher
  • Go: pusher-http-go
  • Java/Kotlin: pusher-java-client