mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
131 lines
3.0 KiB
Go
131 lines
3.0 KiB
Go
package providers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/keybinds"
|
|
)
|
|
|
|
type JSONFileProvider struct {
|
|
filePath string
|
|
name string
|
|
}
|
|
|
|
func NewJSONFileProvider(filePath string) (*JSONFileProvider, error) {
|
|
if filePath == "" {
|
|
return nil, fmt.Errorf("file path cannot be empty")
|
|
}
|
|
|
|
expandedPath, err := expandPath(filePath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to expand path: %w", err)
|
|
}
|
|
|
|
name := filepath.Base(expandedPath)
|
|
name = name[:len(name)-len(filepath.Ext(name))]
|
|
|
|
return &JSONFileProvider{
|
|
filePath: expandedPath,
|
|
name: name,
|
|
}, nil
|
|
}
|
|
|
|
func (j *JSONFileProvider) Name() string {
|
|
return j.name
|
|
}
|
|
|
|
func (j *JSONFileProvider) GetCheatSheet() (*keybinds.CheatSheet, error) {
|
|
data, err := os.ReadFile(j.filePath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read file: %w", err)
|
|
}
|
|
|
|
var rawData map[string]interface{}
|
|
if err := json.Unmarshal(data, &rawData); err != nil {
|
|
return nil, fmt.Errorf("failed to parse JSON: %w", err)
|
|
}
|
|
|
|
title, _ := rawData["title"].(string)
|
|
provider, _ := rawData["provider"].(string)
|
|
if provider == "" {
|
|
provider = j.name
|
|
}
|
|
|
|
categorizedBinds := make(map[string][]keybinds.Keybind)
|
|
|
|
bindsRaw, ok := rawData["binds"]
|
|
if !ok {
|
|
return nil, fmt.Errorf("missing 'binds' field")
|
|
}
|
|
|
|
switch binds := bindsRaw.(type) {
|
|
case map[string]interface{}:
|
|
for category, categoryBindsRaw := range binds {
|
|
categoryBindsList, ok := categoryBindsRaw.([]interface{})
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
var keybindsList []keybinds.Keybind
|
|
categoryBindsJSON, _ := json.Marshal(categoryBindsList)
|
|
if err := json.Unmarshal(categoryBindsJSON, &keybindsList); err != nil {
|
|
continue
|
|
}
|
|
|
|
categorizedBinds[category] = keybindsList
|
|
}
|
|
|
|
case []interface{}:
|
|
flatBindsJSON, _ := json.Marshal(binds)
|
|
var flatBinds []struct {
|
|
Key string `json:"key"`
|
|
Description string `json:"desc"`
|
|
Category string `json:"cat,omitempty"`
|
|
Subcategory string `json:"subcat,omitempty"`
|
|
}
|
|
if err := json.Unmarshal(flatBindsJSON, &flatBinds); err != nil {
|
|
return nil, fmt.Errorf("failed to parse flat binds array: %w", err)
|
|
}
|
|
|
|
for _, bind := range flatBinds {
|
|
category := bind.Category
|
|
if category == "" {
|
|
category = "Other"
|
|
}
|
|
|
|
kb := keybinds.Keybind{
|
|
Key: bind.Key,
|
|
Description: bind.Description,
|
|
Subcategory: bind.Subcategory,
|
|
}
|
|
categorizedBinds[category] = append(categorizedBinds[category], kb)
|
|
}
|
|
|
|
default:
|
|
return nil, fmt.Errorf("'binds' must be either an object (categorized) or array (flat)")
|
|
}
|
|
|
|
return &keybinds.CheatSheet{
|
|
Title: title,
|
|
Provider: provider,
|
|
Binds: categorizedBinds,
|
|
}, nil
|
|
}
|
|
|
|
func expandPath(path string) (string, error) {
|
|
expandedPath := os.ExpandEnv(path)
|
|
|
|
if filepath.HasPrefix(expandedPath, "~") {
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
expandedPath = filepath.Join(home, expandedPath[1:])
|
|
}
|
|
|
|
return filepath.Clean(expandedPath), nil
|
|
}
|