Files
SimpleArmaAdmin/cmd/worker/main.go

175 lines
4.7 KiB
Go

package main
import (
"bufio"
"encoding/json"
"log"
"net/url"
"os"
"strings"
"sync"
"time"
"SimpleArmaAdmin/internal/crypto"
"SimpleArmaAdmin/internal/parser"
"github.com/gorilla/websocket"
)
var mockLogs = []string{
"12:30:01.122 SCRIPT : [RJSSupport][Chat] [Global] Zauberklöte: hi, leute kurze frage. zock seit monaten wieder mal arma, was ist aus dem gtg#4 und #5 geworden, da ist ja nix los",
"09:37:50.865 DEFAULT : BattlEye Server: 'Player #0 Mike1Delta (92.209.175.19:6679) connected'",
"13:29:19.727 SCRIPT : [RJSSupport][Chat] [Global] 纱雾.: WHAT",
"09:38:53.842 DEFAULT : BattlEye Server: 'Player #0 Mike1Delta disconnected'",
"14:56:34.622 SCRIPT : [RJSSupport][Chat] [Global] Toope: help?",
"15:04:22.868 SCRIPT : [RJSSupport][Chat] [Global] vatrano: Transpo 5-10min abwesend",
}
// extractPlayerName extracts the player name from event content
func extractPlayerName(content string) string {
// For JOIN/LEAVE: "Mike1Delta connected to server"
if strings.Contains(content, "connected to server") {
parts := strings.Split(content, " connected")
if len(parts) > 0 {
return strings.TrimSpace(parts[0])
}
}
if strings.Contains(content, "left the server") {
parts := strings.Split(content, " left")
if len(parts) > 0 {
return strings.TrimSpace(parts[0])
}
}
// For CHAT: "PlayerName: message"
if strings.Contains(content, ":") {
parts := strings.SplitN(content, ":", 2)
if len(parts) > 0 {
return strings.TrimSpace(parts[0])
}
}
return ""
}
func main() {
gatewayURL := os.Getenv("GATEWAY_URL")
logFilePath := os.Getenv("LOG_FILE_PATH")
mockMode := os.Getenv("MOCK_MODE") == "true"
if logFilePath == "" {
logFilePath = "arma_server.rpt"
}
masterKey := []byte("this-is-a-32-byte-master-key-xyz")
communityID := "comm-123-abc"
// TODO: Initialize SQLite buffer for offline mode
// offlineBuffer, err := initOfflineBuffer("worker_buffer.db")
// if err != nil {
// log.Fatalf("Failed to init offline buffer: %v", err)
// }
// defer offlineBuffer.Close()
u, _ := url.Parse(gatewayURL)
log.Printf("Worker starting for community %s. MockMode: %v, Offline-Buffer: enabled", communityID, mockMode)
for {
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Printf("Dial failed: %v. Retrying in 5s...", err)
time.Sleep(5 * time.Second)
continue
}
log.Println("Connected to gateway")
var mu sync.Mutex
// 1. Telemetry Loop
go func() {
for {
telemetry := map[string]interface{}{
"type": "TELEMETRY",
"community_id": communityID,
"fps": 45.5 + float64(time.Now().Unix()%5),
"players": 12,
"ai_count": 142 + (time.Now().Unix() % 10),
"vehicle_count": 24,
}
data, _ := json.Marshal(telemetry)
mu.Lock()
err := c.WriteMessage(websocket.TextMessage, data)
mu.Unlock()
if err != nil {
return
}
time.Sleep(5 * time.Second)
}
}()
// 2. Log Tailing / Mocking
go func() {
if mockMode {
i := 0
for {
line := mockLogs[i%len(mockLogs)]
event := parser.ParseLine(line)
if event != nil {
// Enrich event with blind index for player names
if event.Type == "JOIN" || event.Type == "LEAVE" || event.Type == "CHAT" {
playerName := extractPlayerName(event.Content)
if playerName != "" {
blindIndex := crypto.GenerateBlindIndex(playerName, masterKey)
event.Content = event.Content + " [BLIND:" + blindIndex + "]"
}
}
payload, _ := json.Marshal(event)
encrypted, _ := crypto.Encrypt(payload, masterKey)
mu.Lock()
err := c.WriteMessage(websocket.BinaryMessage, encrypted)
mu.Unlock()
if err != nil {
return
}
log.Printf("Sent MOCK event: %s", event.Type)
}
i++
time.Sleep(10 * time.Second)
}
} else {
file, err := os.Open(logFilePath)
if err != nil {
log.Printf("Could not open log file: %v", err)
return
}
file.Seek(0, 2)
scanner := bufio.NewScanner(file)
for {
if scanner.Scan() {
line := scanner.Text()
event := parser.ParseLine(line)
if event != nil {
payload, _ := json.Marshal(event)
encrypted, _ := crypto.Encrypt(payload, masterKey)
mu.Lock()
err := c.WriteMessage(websocket.BinaryMessage, encrypted)
mu.Unlock()
if err != nil {
return
}
log.Printf("Sent LIVE event: %s", event.Type)
}
}
time.Sleep(500 * time.Millisecond)
}
}
}()
for {
if _, _, err := c.ReadMessage(); err != nil {
log.Printf("Read error: %v. Reconnecting...", err)
break
}
}
c.Close()
time.Sleep(2 * time.Second)
}
}