Make SCUM logs live relay only
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
package companion
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const logEventsPath = "/api/v1/game-client-bridge/companion/logs/events"
|
||||
|
||||
type LogEntry struct {
|
||||
Seq uint64 `json:"seq"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Level string `json:"level,omitempty"`
|
||||
Line string `json:"line"`
|
||||
Fields map[string]string `json:"fields,omitempty"`
|
||||
Redacted bool `json:"redacted"`
|
||||
}
|
||||
|
||||
type LogStreamEvent struct {
|
||||
ServerInstanceID string `json:"serverInstanceId"`
|
||||
StreamID string `json:"streamId"`
|
||||
Source string `json:"source"`
|
||||
StreamKey string `json:"streamKey"`
|
||||
LogSessionID string `json:"logSessionId,omitempty"`
|
||||
SessionStartedAt time.Time `json:"sessionStartedAt,omitempty"`
|
||||
LatestSeq uint64 `json:"latestSeq"`
|
||||
Entry LogEntry `json:"entry"`
|
||||
}
|
||||
|
||||
type logStreamRequest struct {
|
||||
SessionToken string `json:"sessionToken"`
|
||||
}
|
||||
|
||||
func (client *Client) StreamLogEvents(ctx context.Context, handle func(LogStreamEvent) error) error {
|
||||
if handle == nil {
|
||||
return fmt.Errorf("log event handler is required")
|
||||
}
|
||||
token, err := client.currentSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
encoded, err := json.Marshal(logStreamRequest{SessionToken: token})
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode log stream request: %w", err)
|
||||
}
|
||||
if len(encoded) > maxRequestBytes {
|
||||
return fmt.Errorf("platform request exceeds the bounded payload size")
|
||||
}
|
||||
request, err := http.NewRequestWithContext(ctx, http.MethodPost, client.config.Platform.BaseURL+logEventsPath, bytes.NewReader(encoded))
|
||||
if err != nil {
|
||||
return fmt.Errorf("create log stream request: %w", err)
|
||||
}
|
||||
request.Header.Set("Accept", "text/event-stream")
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
response, err := client.httpClient.Do(request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open log stream: %w", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != http.StatusOK {
|
||||
_, _ = io.Copy(io.Discard, io.LimitReader(response.Body, 4096))
|
||||
return HTTPError{StatusCode: response.StatusCode, ExpectedStatus: http.StatusOK}
|
||||
}
|
||||
return readLogEventStream(ctx, response.Body, handle)
|
||||
}
|
||||
|
||||
func readLogEventStream(ctx context.Context, body io.Reader, handle func(LogStreamEvent) error) error {
|
||||
reader := bufio.NewReader(body)
|
||||
var eventName string
|
||||
var dataLines []string
|
||||
flush := func() error {
|
||||
if len(dataLines) == 0 {
|
||||
eventName = ""
|
||||
return nil
|
||||
}
|
||||
name := eventName
|
||||
if name == "" {
|
||||
name = "message"
|
||||
}
|
||||
payload := strings.Join(dataLines, "\n")
|
||||
eventName = ""
|
||||
dataLines = nil
|
||||
if name != "log" {
|
||||
return nil
|
||||
}
|
||||
var event LogStreamEvent
|
||||
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
||||
return fmt.Errorf("decode log event: %w", err)
|
||||
}
|
||||
return handle(event)
|
||||
}
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
if len(line) > 0 {
|
||||
line = strings.TrimRight(line, "\r\n")
|
||||
switch {
|
||||
case line == "":
|
||||
if flushErr := flush(); flushErr != nil {
|
||||
return flushErr
|
||||
}
|
||||
case strings.HasPrefix(line, ":"):
|
||||
case strings.HasPrefix(line, "event:"):
|
||||
eventName = strings.TrimSpace(strings.TrimPrefix(line, "event:"))
|
||||
case strings.HasPrefix(line, "data:"):
|
||||
dataLines = append(dataLines, strings.TrimSpace(strings.TrimPrefix(line, "data:")))
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if ctx != nil && ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
if err == io.EOF {
|
||||
return flush()
|
||||
}
|
||||
return fmt.Errorf("read log stream: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user