Null-DRM-Official/apps/agent/internal/client/client.go
404errordeveloper 2fa8f2435f Initial commit: Null DRM Official
Capture, decrypt, and restream toolkit with compiled-in app modules
(RTE, TG4, BBC), on-device MITM proxy, streamd control plane, and www.
BBC module.yaml is published (clear streams); other module values stay local.
2026-10-06 00:25:35 +02:00

118 lines
2.8 KiB
Go

package client
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
)
type Client struct {
BaseURL string
Token string
HTTP *http.Client
UserAgent string
}
func New(baseURL, token string) *Client {
return &Client{
BaseURL: strings.TrimRight(baseURL, "/"),
Token: token,
HTTP: &http.Client{Timeout: 30 * time.Second},
UserAgent: "drm-agent/1.0",
}
}
type Stream struct {
ID int64 `json:"id"`
Name string `json:"name"`
Title string `json:"title"`
App string `json:"app"`
Channel string `json:"channel"`
MPD string `json:"mpd"`
Key string `json:"key"`
Enabled bool `json:"enabled"`
Health string `json:"health"`
LastError string `json:"last_error"`
PlaylistAgeS float64 `json:"playlist_age_s"`
ClaimedBy string `json:"claimed_by"`
}
type Credentials struct {
MPD string `json:"mpd"`
Key string `json:"key"`
PSSH string `json:"pssh,omitempty"`
Auth string `json:"auth,omitempty"`
PID string `json:"pid,omitempty"`
}
func (c *Client) Health() error {
_, err := c.do(http.MethodGet, "/api/health", nil)
return err
}
func (c *Client) ListStreams() ([]Stream, error) {
body, err := c.do(http.MethodGet, "/api/streams", nil)
if err != nil {
return nil, err
}
var wrap struct {
Streams []Stream `json:"streams"`
}
if err := json.Unmarshal(body, &wrap); err != nil {
return nil, err
}
return wrap.Streams, nil
}
func (c *Client) Claim(id int64, agentID string, ttlSec int) error {
payload := map[string]any{"agent_id": agentID, "ttl_sec": ttlSec}
_, err := c.do(http.MethodPost, fmt.Sprintf("/api/streams/%d/claim", id), payload)
return err
}
func (c *Client) ReleaseClaim(id int64, agentID string) error {
payload := map[string]any{"agent_id": agentID}
_, err := c.do(http.MethodPost, fmt.Sprintf("/api/streams/%d/claim/release", id), payload)
return err
}
func (c *Client) PostCredentials(id int64, cred Credentials) error {
_, err := c.do(http.MethodPost, fmt.Sprintf("/api/streams/%d/credentials", id), cred)
return err
}
func (c *Client) do(method, path string, payload any) ([]byte, error) {
var rdr io.Reader
if payload != nil {
b, err := json.Marshal(payload)
if err != nil {
return nil, err
}
rdr = bytes.NewReader(b)
}
req, err := http.NewRequest(method, c.BaseURL+path, rdr)
if err != nil {
return nil, err
}
if payload != nil {
req.Header.Set("Content-Type", "application/json")
}
req.Header.Set("User-Agent", c.UserAgent)
if c.Token != "" {
req.Header.Set("Authorization", "Bearer "+c.Token)
}
resp, err := c.HTTP.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode >= 300 {
return nil, fmt.Errorf("%s %s: %s — %s", method, path, resp.Status, strings.TrimSpace(string(body)))
}
return body, nil
}