Files
seanime-docker/seanime-2.9.10/internal/mediaplayers/mpchc/mpc_hc.go
2025-09-20 14:08:38 +01:00

140 lines
3.5 KiB
Go

package mpchc
import (
"fmt"
"io"
"net/http"
neturl "net/url"
"path/filepath"
"strings"
"github.com/rs/zerolog"
)
type MpcHc struct {
Host string
Port int
Path string
Logger *zerolog.Logger
}
func (api *MpcHc) url() string {
return fmt.Sprintf("http://%s:%d", api.Host, api.Port)
}
// Execute sends a command to MPC and returns the response.
func (api *MpcHc) Execute(command int, data map[string]interface{}) (string, error) {
url := fmt.Sprintf("%s/command.html?wm_command=%d", api.url(), command)
if data != nil {
queryParams := neturl.Values{}
for key, value := range data {
queryParams.Add(key, fmt.Sprintf("%v", value))
}
url += "&" + queryParams.Encode()
}
response, err := http.Get(url)
if err != nil {
api.Logger.Error().Err(err).Msg("mpc hc: Failed to execute command")
return "", err
}
defer response.Body.Close()
// Check HTTP status code and errors
statusCode := response.StatusCode
if !((statusCode >= 200) && (statusCode <= 299)) {
err = fmt.Errorf("http error code: %d\n", statusCode)
return "", err
}
// Get byte response and http status code
byteArr, readErr := io.ReadAll(response.Body)
if readErr != nil {
err = fmt.Errorf("error reading response: %s\n", readErr)
return "", err
}
// Write response
res := string(byteArr)
return res, nil
}
func escapeInput(input string) string {
if strings.HasPrefix(input, "http") {
return neturl.QueryEscape(input)
} else {
input = filepath.FromSlash(input)
return strings.ReplaceAll(neturl.QueryEscape(input), "+", "%20")
}
}
// OpenAndPlay opens a video file in MPC.
func (api *MpcHc) OpenAndPlay(filePath string) (string, error) {
url := fmt.Sprintf("%s/browser.html?path=%s", api.url(), escapeInput(filePath))
api.Logger.Trace().Str("url", url).Msg("mpc hc: Opening and playing")
response, err := http.Get(url)
if err != nil {
api.Logger.Error().Err(err).Msg("mpc hc: Failed to connect to MPC")
return "", err
}
defer response.Body.Close()
// Check HTTP status code and errors
statusCode := response.StatusCode
if !((statusCode >= 200) && (statusCode <= 299)) {
err = fmt.Errorf("http error code: %d\n", statusCode)
api.Logger.Error().Err(err).Msg("mpc hc: Failed to open and play")
return "", err
}
// Get byte response and http status code
byteArr, readErr := io.ReadAll(response.Body)
if readErr != nil {
err = fmt.Errorf("error reading response: %s\n", readErr)
api.Logger.Error().Err(err).Msg("mpc hc: Failed to open and play")
return "", err
}
// Write response
res := string(byteArr)
return res, nil
}
// GetVariables retrieves player variables from MPC.
func (api *MpcHc) GetVariables() (*Variables, error) {
url := fmt.Sprintf("%s/variables.html", api.url())
response, err := http.Get(url)
if err != nil {
api.Logger.Error().Err(err).Msg("mpc hc: Failed to get variables")
return &Variables{}, err
}
defer response.Body.Close()
// Check HTTP status code and errors
statusCode := response.StatusCode
if !((statusCode >= 200) && (statusCode <= 299)) {
err = fmt.Errorf("http error code: %d\n", statusCode)
api.Logger.Error().Err(err).Msg("mpc hc: Failed to get variables")
return &Variables{}, err
}
// Get byte response and http status code
byteArr, readErr := io.ReadAll(response.Body)
if readErr != nil {
err = fmt.Errorf("error reading response: %s\n", readErr)
api.Logger.Error().Err(err).Msg("mpc hc: Failed to get variables")
return &Variables{}, err
}
// Write response
res := string(byteArr)
vars := parseVariables(res)
return vars, nil
}