mirror of https://github.com/jetkvm/kvm.git
add jsonrpc keyboard macro get/set
This commit is contained in:
parent
1f8f885a1d
commit
5650bad796
61
config.go
61
config.go
|
@ -14,6 +14,65 @@ type WakeOnLanDevice struct {
|
|||
MacAddress string `json:"macAddress"`
|
||||
}
|
||||
|
||||
// Constants for keyboard macro limits
|
||||
const (
|
||||
MaxMacrosPerDevice = 25
|
||||
MaxStepsPerMacro = 10
|
||||
MaxKeysPerStep = 10
|
||||
MinStepDelay = 50
|
||||
MaxStepDelay = 2000
|
||||
)
|
||||
|
||||
type KeyboardMacroStep struct {
|
||||
Keys []string `json:"keys"`
|
||||
Modifiers []string `json:"modifiers"`
|
||||
Delay int `json:"delay"`
|
||||
}
|
||||
|
||||
func (s *KeyboardMacroStep) Validate() error {
|
||||
if len(s.Keys) > MaxKeysPerStep {
|
||||
return fmt.Errorf("too many keys in step (max %d)", MaxKeysPerStep)
|
||||
}
|
||||
|
||||
if s.Delay < MinStepDelay {
|
||||
s.Delay = MinStepDelay
|
||||
} else if s.Delay > MaxStepDelay {
|
||||
s.Delay = MaxStepDelay
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type KeyboardMacro struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Steps []KeyboardMacroStep `json:"steps"`
|
||||
SortOrder int `json:"sortOrder,omitempty"`
|
||||
}
|
||||
|
||||
func (m *KeyboardMacro) Validate() error {
|
||||
if m.Name == "" {
|
||||
return fmt.Errorf("macro name cannot be empty")
|
||||
}
|
||||
|
||||
if len(m.Steps) == 0 {
|
||||
return fmt.Errorf("macro must have at least one step")
|
||||
}
|
||||
|
||||
if len(m.Steps) > MaxStepsPerMacro {
|
||||
m.Steps = m.Steps[:MaxStepsPerMacro]
|
||||
}
|
||||
|
||||
for i := range m.Steps {
|
||||
if err := m.Steps[i].Validate(); err != nil {
|
||||
return fmt.Errorf("invalid step %d: %w", i+1, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
CloudURL string `json:"cloud_url"`
|
||||
CloudAppURL string `json:"cloud_app_url"`
|
||||
|
@ -26,6 +85,7 @@ type Config struct {
|
|||
LocalAuthToken string `json:"local_auth_token"`
|
||||
LocalAuthMode string `json:"localAuthMode"` //TODO: fix it with migration
|
||||
WakeOnLanDevices []WakeOnLanDevice `json:"wake_on_lan_devices"`
|
||||
KeyboardMacros []KeyboardMacro `json:"keyboard_macros"`
|
||||
EdidString string `json:"hdmi_edid_string"`
|
||||
ActiveExtension string `json:"active_extension"`
|
||||
DisplayMaxBrightness int `json:"display_max_brightness"`
|
||||
|
@ -43,6 +103,7 @@ var defaultConfig = &Config{
|
|||
CloudAppURL: "https://app.jetkvm.com",
|
||||
AutoUpdateEnabled: true, // Set a default value
|
||||
ActiveExtension: "",
|
||||
KeyboardMacros: []KeyboardMacro{},
|
||||
DisplayMaxBrightness: 64,
|
||||
DisplayDimAfterSec: 120, // 2 minutes
|
||||
DisplayOffAfterSec: 1800, // 30 minutes
|
||||
|
|
97
jsonrpc.go
97
jsonrpc.go
|
@ -792,6 +792,101 @@ func rpcSetScrollSensitivity(sensitivity string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getKeyboardMacros() (interface{}, error) {
|
||||
macros := make([]KeyboardMacro, len(config.KeyboardMacros))
|
||||
copy(macros, config.KeyboardMacros)
|
||||
|
||||
return macros, nil
|
||||
}
|
||||
|
||||
type KeyboardMacrosParams struct {
|
||||
Macros []interface{} `json:"macros"`
|
||||
}
|
||||
|
||||
func setKeyboardMacros(params KeyboardMacrosParams) (interface{}, error) {
|
||||
if params.Macros == nil {
|
||||
return nil, fmt.Errorf("missing or invalid macros parameter")
|
||||
}
|
||||
|
||||
newMacros := make([]KeyboardMacro, 0, len(params.Macros))
|
||||
|
||||
for i, item := range params.Macros {
|
||||
macroMap, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid macro at index %d", i)
|
||||
}
|
||||
|
||||
id, _ := macroMap["id"].(string)
|
||||
if id == "" {
|
||||
id = fmt.Sprintf("macro-%d", time.Now().UnixNano())
|
||||
}
|
||||
|
||||
name, _ := macroMap["name"].(string)
|
||||
description, _ := macroMap["description"].(string)
|
||||
|
||||
sortOrder := i + 1
|
||||
if sortOrderFloat, ok := macroMap["sortOrder"].(float64); ok {
|
||||
sortOrder = int(sortOrderFloat)
|
||||
}
|
||||
|
||||
steps := []KeyboardMacroStep{}
|
||||
if stepsArray, ok := macroMap["steps"].([]interface{}); ok {
|
||||
for _, stepItem := range stepsArray {
|
||||
stepMap, ok := stepItem.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
step := KeyboardMacroStep{}
|
||||
|
||||
if keysArray, ok := stepMap["keys"].([]interface{}); ok {
|
||||
for _, k := range keysArray {
|
||||
if keyStr, ok := k.(string); ok {
|
||||
step.Keys = append(step.Keys, keyStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if modsArray, ok := stepMap["modifiers"].([]interface{}); ok {
|
||||
for _, m := range modsArray {
|
||||
if modStr, ok := m.(string); ok {
|
||||
step.Modifiers = append(step.Modifiers, modStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if delay, ok := stepMap["delay"].(float64); ok {
|
||||
step.Delay = int(delay)
|
||||
}
|
||||
|
||||
steps = append(steps, step)
|
||||
}
|
||||
}
|
||||
|
||||
macro := KeyboardMacro{
|
||||
ID: id,
|
||||
Name: name,
|
||||
Description: description,
|
||||
Steps: steps,
|
||||
SortOrder: sortOrder,
|
||||
}
|
||||
|
||||
if err := macro.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("invalid macro at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
newMacros = append(newMacros, macro)
|
||||
}
|
||||
|
||||
config.KeyboardMacros = newMacros
|
||||
|
||||
if err := SaveConfig(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var rpcHandlers = map[string]RPCHandler{
|
||||
"ping": {Func: rpcPing},
|
||||
"getDeviceID": {Func: rpcGetDeviceID},
|
||||
|
@ -857,4 +952,6 @@ var rpcHandlers = map[string]RPCHandler{
|
|||
"setCloudUrl": {Func: rpcSetCloudUrl, Params: []string{"apiUrl", "appUrl"}},
|
||||
"getScrollSensitivity": {Func: rpcGetScrollSensitivity},
|
||||
"setScrollSensitivity": {Func: rpcSetScrollSensitivity, Params: []string{"sensitivity"}},
|
||||
"getKeyboardMacros": {Func: getKeyboardMacros},
|
||||
"setKeyboardMacros": {Func: setKeyboardMacros, Params: []string{"params"}},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue