200 lines
5.9 KiB
Go
200 lines
5.9 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type ConfigProfileEditor struct {
|
|
Name string `json:"name"`
|
|
Path string `json:"path"`
|
|
Description string `json:"description"`
|
|
Queue ConfigProfileQueueEditor `json:"queue"`
|
|
Instance ConfigProfileInstanceEditor `json:"instance"`
|
|
Raw map[string]any `json:"raw"`
|
|
}
|
|
|
|
type ConfigProfileQueueEditor struct {
|
|
Size string `json:"size"`
|
|
Strategy string `json:"strategy"`
|
|
}
|
|
|
|
type ConfigProfileInstanceEditor struct {
|
|
Name string `json:"name"`
|
|
Template string `json:"template"`
|
|
DisplayName string `json:"display_name"`
|
|
DeviceCode string `json:"device_code"`
|
|
SiteName string `json:"site_name"`
|
|
RTSPURL string `json:"rtsp_url"`
|
|
PublishHLSPath string `json:"publish_hls_path"`
|
|
PublishRTSPPort string `json:"publish_rtsp_port"`
|
|
PublishRTSPPath string `json:"publish_rtsp_path"`
|
|
ChannelNo string `json:"channel_no"`
|
|
AdvancedParams map[string]any `json:"advanced_params"`
|
|
}
|
|
|
|
func (s *ConfigPreviewService) GetProfileEditor(name string) (*ConfigProfileEditor, error) {
|
|
raw, path, err := s.readAssetJSON("profiles", name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
queueMap, _ := raw["queue"].(map[string]any)
|
|
instance := ConfigProfileInstanceEditor{}
|
|
instancesRaw, _ := raw["instances"].([]any)
|
|
if len(instancesRaw) > 0 {
|
|
instanceMap, _ := instancesRaw[0].(map[string]any)
|
|
paramsMap, _ := instanceMap["params"].(map[string]any)
|
|
advanced := cloneMap(paramsMap)
|
|
for _, key := range []string{
|
|
"display_name",
|
|
"device_code",
|
|
"site_name",
|
|
"rtsp_url",
|
|
"publish_hls_path",
|
|
"publish_rtsp_port",
|
|
"publish_rtsp_path",
|
|
"channel_no",
|
|
} {
|
|
delete(advanced, key)
|
|
}
|
|
if len(advanced) == 0 {
|
|
advanced = nil
|
|
}
|
|
instance = ConfigProfileInstanceEditor{
|
|
Name: stringValue(instanceMap["name"]),
|
|
Template: stringValue(instanceMap["template"]),
|
|
DisplayName: stringValue(paramsMap["display_name"]),
|
|
DeviceCode: stringValue(paramsMap["device_code"]),
|
|
SiteName: stringValue(paramsMap["site_name"]),
|
|
RTSPURL: stringValue(paramsMap["rtsp_url"]),
|
|
PublishHLSPath: stringValue(paramsMap["publish_hls_path"]),
|
|
PublishRTSPPort: valueString(paramsMap["publish_rtsp_port"]),
|
|
PublishRTSPPath: stringValue(paramsMap["publish_rtsp_path"]),
|
|
ChannelNo: stringValue(paramsMap["channel_no"]),
|
|
AdvancedParams: advanced,
|
|
}
|
|
}
|
|
return &ConfigProfileEditor{
|
|
Name: firstString(raw["name"], name),
|
|
Path: path,
|
|
Description: stringValue(raw["description"]),
|
|
Queue: ConfigProfileQueueEditor{
|
|
Size: valueString(queueMap["size"]),
|
|
Strategy: stringValue(queueMap["strategy"]),
|
|
},
|
|
Instance: instance,
|
|
Raw: raw,
|
|
}, nil
|
|
}
|
|
|
|
func (s *ConfigPreviewService) BuildProfileDocument(editor ConfigProfileEditor) (map[string]any, error) {
|
|
name := strings.TrimSpace(editor.Name)
|
|
if name == "" {
|
|
return nil, fmt.Errorf("profile name is required")
|
|
}
|
|
if err := validateConfigName(name); err != nil {
|
|
return nil, fmt.Errorf("invalid profile name: %w", err)
|
|
}
|
|
|
|
instanceName := strings.TrimSpace(editor.Instance.Name)
|
|
if instanceName == "" {
|
|
return nil, fmt.Errorf("instance name is required")
|
|
}
|
|
if err := validateConfigName(instanceName); err != nil {
|
|
return nil, fmt.Errorf("invalid instance name: %w", err)
|
|
}
|
|
|
|
displayName := strings.TrimSpace(editor.Instance.DisplayName)
|
|
if displayName == "" {
|
|
return nil, fmt.Errorf("display name is required")
|
|
}
|
|
|
|
rtspURL := strings.TrimSpace(editor.Instance.RTSPURL)
|
|
if rtspURL == "" {
|
|
return nil, fmt.Errorf("rtsp url is required")
|
|
}
|
|
|
|
params := map[string]any{}
|
|
setString(params, "display_name", displayName)
|
|
setString(params, "device_code", editor.Instance.DeviceCode)
|
|
setString(params, "site_name", editor.Instance.SiteName)
|
|
setString(params, "rtsp_url", rtspURL)
|
|
setString(params, "publish_hls_path", editor.Instance.PublishHLSPath)
|
|
setString(params, "publish_rtsp_path", editor.Instance.PublishRTSPPath)
|
|
setString(params, "channel_no", editor.Instance.ChannelNo)
|
|
|
|
if port := strings.TrimSpace(editor.Instance.PublishRTSPPort); port != "" {
|
|
value, err := strconv.Atoi(port)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("publish rtsp port must be a number")
|
|
}
|
|
params["publish_rtsp_port"] = value
|
|
}
|
|
|
|
for key, value := range cloneMap(editor.Instance.AdvancedParams) {
|
|
params[key] = value
|
|
}
|
|
|
|
instance := map[string]any{
|
|
"name": instanceName,
|
|
"params": params,
|
|
}
|
|
setString(instance, "template", editor.Instance.Template)
|
|
|
|
doc := map[string]any{
|
|
"name": name,
|
|
"instances": []map[string]any{instance},
|
|
}
|
|
setString(doc, "description", editor.Description)
|
|
|
|
queue := map[string]any{}
|
|
if size := strings.TrimSpace(editor.Queue.Size); size != "" {
|
|
value, err := strconv.Atoi(size)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("queue size must be a number")
|
|
}
|
|
queue["size"] = value
|
|
}
|
|
setString(queue, "strategy", editor.Queue.Strategy)
|
|
if len(queue) > 0 {
|
|
doc["queue"] = queue
|
|
}
|
|
|
|
return doc, nil
|
|
}
|
|
|
|
func (s *ConfigPreviewService) SaveProfileEditor(editor ConfigProfileEditor) error {
|
|
doc, err := s.BuildProfileDocument(editor)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
root := s.mediaRepoRoot()
|
|
if root == "" {
|
|
return fmt.Errorf("media repo path is not configured")
|
|
}
|
|
path := filepath.Join(root, "configs", "profiles", strings.TrimSpace(editor.Name)+".json")
|
|
body, err := marshalConfigJSON(doc)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return os.WriteFile(path, body, 0o644)
|
|
}
|
|
|
|
func setString(m map[string]any, key string, value string) {
|
|
if strings.TrimSpace(value) != "" {
|
|
m[key] = strings.TrimSpace(value)
|
|
}
|
|
}
|
|
|
|
func marshalConfigJSON(doc map[string]any) ([]byte, error) {
|
|
body, err := json.MarshalIndent(doc, "", " ")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return append(body, '\n'), nil
|
|
}
|