183 lines
3.5 KiB
Go
183 lines
3.5 KiB
Go
package services
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"arma3-web-server/internal/models"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type ModlistManager struct {
|
|
dir string
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
func NewModlistManager(dataDir string) *ModlistManager {
|
|
return &ModlistManager{
|
|
dir: filepath.Join(dataDir, "modlists"),
|
|
}
|
|
}
|
|
|
|
func (mm *ModlistManager) path(id string) string {
|
|
return filepath.Join(mm.dir, id+".json")
|
|
}
|
|
|
|
func (mm *ModlistManager) List() ([]models.ModlistListItem, error) {
|
|
mm.mu.RLock()
|
|
defer mm.mu.RUnlock()
|
|
|
|
entries, err := os.ReadDir(mm.dir)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return []models.ModlistListItem{}, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
var items []models.ModlistListItem
|
|
for _, e := range entries {
|
|
if e.IsDir() || !strings.HasSuffix(e.Name(), ".json") {
|
|
continue
|
|
}
|
|
data, err := os.ReadFile(filepath.Join(mm.dir, e.Name()))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
var m models.Modlist
|
|
if err := json.Unmarshal(data, &m); err != nil {
|
|
continue
|
|
}
|
|
items = append(items, models.ModlistListItem{
|
|
ID: m.ID,
|
|
Name: m.Name,
|
|
ModCount: len(m.Mods),
|
|
CreatedAt: m.CreatedAt,
|
|
UpdatedAt: m.UpdatedAt,
|
|
})
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
func (mm *ModlistManager) Get(id string) (*models.Modlist, error) {
|
|
mm.mu.RLock()
|
|
defer mm.mu.RUnlock()
|
|
|
|
data, err := os.ReadFile(mm.path(id))
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return nil, fmt.Errorf("modlist not found")
|
|
}
|
|
return nil, err
|
|
}
|
|
var m models.Modlist
|
|
if err := json.Unmarshal(data, &m); err != nil {
|
|
return nil, err
|
|
}
|
|
return &m, nil
|
|
}
|
|
|
|
func (mm *ModlistManager) Create(name string) (*models.Modlist, error) {
|
|
mm.mu.Lock()
|
|
defer mm.mu.Unlock()
|
|
|
|
now := time.Now().UTC()
|
|
m := &models.Modlist{
|
|
ID: uuid.New().String(),
|
|
Name: name,
|
|
Mods: []models.ModEntry{},
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
data, err := json.MarshalIndent(m, "", " ")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := os.MkdirAll(mm.dir, 0755); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := os.WriteFile(mm.path(m.ID), data, 0644); err != nil {
|
|
return nil, err
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
func (mm *ModlistManager) Update(id, name string, mods []models.ModEntry) (*models.Modlist, error) {
|
|
mm.mu.Lock()
|
|
defer mm.mu.Unlock()
|
|
|
|
m, err := mm.getLocked(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.Name = name
|
|
m.Mods = mods
|
|
m.UpdatedAt = time.Now().UTC()
|
|
|
|
data, err := json.MarshalIndent(m, "", " ")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := os.WriteFile(mm.path(id), data, 0644); err != nil {
|
|
return nil, err
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
func (mm *ModlistManager) Delete(id string) error {
|
|
mm.mu.Lock()
|
|
defer mm.mu.Unlock()
|
|
return os.Remove(mm.path(id))
|
|
}
|
|
|
|
func (mm *ModlistManager) Duplicate(id, newName string) (*models.Modlist, error) {
|
|
mm.mu.Lock()
|
|
defer mm.mu.Unlock()
|
|
|
|
orig, err := mm.getLocked(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
now := time.Now().UTC()
|
|
dup := &models.Modlist{
|
|
ID: uuid.New().String(),
|
|
Name: newName,
|
|
Mods: orig.Mods,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
data, err := json.MarshalIndent(dup, "", " ")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := os.WriteFile(mm.path(dup.ID), data, 0644); err != nil {
|
|
return nil, err
|
|
}
|
|
return dup, nil
|
|
}
|
|
|
|
func (mm *ModlistManager) getLocked(id string) (*models.Modlist, error) {
|
|
data, err := os.ReadFile(mm.path(id))
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return nil, fmt.Errorf("modlist not found")
|
|
}
|
|
return nil, err
|
|
}
|
|
var m models.Modlist
|
|
if err := json.Unmarshal(data, &m); err != nil {
|
|
return nil, err
|
|
}
|
|
return &m, nil
|
|
}
|