edge/pkg/module/cast/module.go

217 lines
4.8 KiB
Go

package cast
import (
"context"
"time"
"forge.cadoles.com/arcad/edge/pkg/app"
"forge.cadoles.com/arcad/edge/pkg/module"
"github.com/dop251/goja"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger"
)
const (
defaultTimeout = 30 * time.Second
)
type Module struct{}
func (m *Module) Name() string {
return "cast"
}
func (m *Module) Export(export *goja.Object) {
if err := export.Set("refreshDevices", m.refreshDevices); err != nil {
panic(errors.Wrap(err, "could not set 'refreshDevices' function"))
}
if err := export.Set("getDevices", m.getDevices); err != nil {
panic(errors.Wrap(err, "could not set 'getDevices' function"))
}
if err := export.Set("loadUrl", m.loadUrl); err != nil {
panic(errors.Wrap(err, "could not set 'loadUrl' function"))
}
if err := export.Set("stopCast", m.stopCast); err != nil {
panic(errors.Wrap(err, "could not set 'stopCast' function"))
}
if err := export.Set("getStatus", m.getStatus); err != nil {
panic(errors.Wrap(err, "could not set 'getStatus' function"))
}
}
func (m *Module) refreshDevices(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
rawTimeout := call.Argument(0).String()
timeout, err := m.parseTimeout(rawTimeout)
if err != nil {
panic(rt.ToValue(errors.WithStack(err)))
}
promise := app.NewPromiseProxyFrom(rt)
go func() {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
devices, err := ListDevices(ctx, true)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "error refreshing casting devices list", logger.CapturedE(errors.WithStack(err)))
promise.Reject(err)
return
}
promise.Resolve(toLegacyDevices(devices...))
}()
return rt.ToValue(promise)
}
func (m *Module) getDevices(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
ctx := context.Background()
devices, err := ListDevices(ctx, false)
if err != nil {
panic(rt.ToValue(errors.WithStack(err)))
}
return rt.ToValue(toLegacyDevices(devices...))
}
func (m *Module) loadUrl(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
if len(call.Arguments) < 2 {
panic(rt.ToValue(errors.WithStack(module.ErrUnexpectedArgumentsNumber)))
}
deviceUUID := call.Argument(0).String()
url := call.Argument(1).String()
rawTimeout := call.Argument(2).String()
timeout, err := m.parseTimeout(rawTimeout)
if err != nil {
panic(rt.ToValue(errors.WithStack(err)))
}
promise := app.NewPromiseProxyFrom(rt)
go func() {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
err := LoadURL(ctx, deviceUUID, url)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "error while casting url", logger.CapturedE(err))
promise.Reject(err)
return
}
promise.Resolve(nil)
}()
return rt.ToValue(promise)
}
func (m *Module) stopCast(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
if len(call.Arguments) < 1 {
panic(rt.ToValue(errors.WithStack(module.ErrUnexpectedArgumentsNumber)))
}
deviceUUID := call.Argument(0).String()
rawTimeout := call.Argument(1).String()
timeout, err := m.parseTimeout(rawTimeout)
if err != nil {
panic(rt.ToValue(errors.WithStack(err)))
}
promise := app.NewPromiseProxyFrom(rt)
go func() {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
err := StopCast(ctx, deviceUUID)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "error while quitting casting device app", logger.CapturedE(errors.WithStack(err)))
promise.Reject(err)
return
}
promise.Resolve(nil)
}()
return rt.ToValue(promise)
}
func (m *Module) getStatus(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
if len(call.Arguments) < 1 {
panic(rt.ToValue(errors.WithStack(module.ErrUnexpectedArgumentsNumber)))
}
deviceUUID := call.Argument(0).String()
rawTimeout := call.Argument(1).String()
timeout, err := m.parseTimeout(rawTimeout)
if err != nil {
panic(rt.ToValue(errors.WithStack(err)))
}
promise := app.NewPromiseProxyFrom(rt)
go func() {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
status, err := GetStatus(ctx, deviceUUID)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "error while getting casting device status", logger.CapturedE(err))
promise.Reject(err)
return
}
promise.Resolve(status)
}()
return rt.ToValue(promise)
}
func (m *Module) parseTimeout(rawTimeout string) (time.Duration, error) {
var (
timeout time.Duration
err error
)
if rawTimeout == "undefined" {
timeout = defaultTimeout
} else {
timeout, err = time.ParseDuration(rawTimeout)
if err != nil {
return defaultTimeout, errors.Wrapf(err, "invalid duration format '%s'", rawTimeout)
}
}
return timeout, nil
}
func CastModuleFactory() app.ServerModuleFactory {
return func(server *app.Server) app.ServerModule {
return &Module{}
}
}