diff --git a/pkg/api/user.go b/pkg/api/user.go index 189b61fc9..262375b75 100644 --- a/pkg/api/user.go +++ b/pkg/api/user.go @@ -27,6 +27,7 @@ type ( Wid string `json:"wid"` } AppMeta struct { + Alias string `json:"alias,omitempty"` Title string `json:"title"` System string `json:"system"` } diff --git a/pkg/api/worker.go b/pkg/api/worker.go index cd9284346..0436ee731 100644 --- a/pkg/api/worker.go +++ b/pkg/api/worker.go @@ -25,6 +25,7 @@ type ( PlayerIndex int `json:"player_index"` } GameInfo struct { + Alias string `json:"alias"` Base string `json:"base"` Name string `json:"name"` Path string `json:"path"` diff --git a/pkg/coordinator/hub.go b/pkg/coordinator/hub.go index 8b57df746..56d5cbc3d 100644 --- a/pkg/coordinator/hub.go +++ b/pkg/coordinator/hub.go @@ -75,7 +75,7 @@ func (h *Hub) handleUserConnection() http.HandlerFunc { apps := h.launcher.GetAppNames() list := make([]api.AppMeta, len(apps)) for i := range apps { - list[i] = api.AppMeta{Title: apps[i].Name, System: apps[i].System} + list[i] = api.AppMeta{Alias: apps[i].Alias, Title: apps[i].Name, System: apps[i].System} } user.InitSession(worker.Id().String(), h.conf.Webrtc.IceServers, list) log.Info().Str(logger.DirectionField, logger.MarkPlus).Msgf("user %s", user.Id()) diff --git a/pkg/games/launcher.go b/pkg/games/launcher.go index ad20ab0f5..8850ea7ff 100644 --- a/pkg/games/launcher.go +++ b/pkg/games/launcher.go @@ -14,6 +14,7 @@ type Launcher interface { } type AppMeta struct { + Alias string Base string Name string Path string @@ -39,7 +40,7 @@ func (gl GameLauncher) ExtractAppNameFromUrl(name string) string { return Extrac func (gl GameLauncher) GetAppNames() (apps []AppMeta) { for _, game := range gl.lib.GetAll() { - apps = append(apps, AppMeta{Name: game.Name, System: game.System}) + apps = append(apps, AppMeta{Alias: game.Alias, Name: game.Name, System: game.System}) } return } diff --git a/pkg/games/library.go b/pkg/games/library.go index 884f38520..abf30b411 100644 --- a/pkg/games/library.go +++ b/pkg/games/library.go @@ -1,8 +1,11 @@ package games import ( + "bufio" + "errors" "fmt" "io/fs" + "os" "path/filepath" "sort" "strings" @@ -57,6 +60,7 @@ type WithEmulatorInfo interface { } type GameMetadata struct { + Alias string Base string Name string // the display name of the game Path string // the game path relative to the library base path @@ -123,6 +127,37 @@ func (lib *library) FindGameByName(name string) GameMetadata { return game } +func (lib *library) AliasFileMaybe() map[string]string { + dir := lib.config.path + path := dir + "/alias.txt" + + if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { + return nil + } + + // read + f, err := os.Open(path) + if err != nil { + lib.log.Error().Msgf("couldn't open alias file, %v", err) + return nil + } + defer func() { _ = f.Close() }() + + m := make(map[string]string) + s := bufio.NewScanner(f) + for s.Scan() { + id, alias, ok := strings.Cut(s.Text(), "=") + if ok { + m[id] = alias + } + } + if err = s.Err(); err != nil { + lib.log.Error().Msgf("alias file read error, %v", err) + } + + return m +} + func (lib *library) Scan() { if !lib.hasSource { lib.log.Info().Msg("Lib scan... skipped (no source)") @@ -142,6 +177,14 @@ func (lib *library) Scan() { lib.log.Debug().Msg("Lib scan... started") + // game name aliases + aliases := lib.AliasFileMaybe() + + if aliases != nil { + lib.log.Debug().Msgf("Lib game alises found") + lib.log.Debug().Msgf(">>> %v", aliases) + } + start := time.Now() var games []GameMetadata dir := lib.config.path @@ -155,6 +198,13 @@ func (lib *library) Scan() { meta.System = lib.emuConf.GetEmulator(meta.Type, meta.Path) + if aliases != nil { + k, ok := aliases[meta.Name] + if ok { + meta.Alias = k + } + } + if _, ok := lib.config.ignored[meta.Name]; !ok { games = append(games, meta) } @@ -247,12 +297,12 @@ func (lib *library) isExtAllowed(path string) bool { // getMetadata returns game info from a path func getMetadata(path string, basePath string) GameMetadata { name := filepath.Base(path) - ext := strings.ToLower(filepath.Ext(name)) + ext := filepath.Ext(name) relPath, _ := filepath.Rel(basePath, path) return GameMetadata{ Name: strings.TrimSuffix(name, ext), - Type: ext[1:], + Type: strings.ToLower(ext[1:]), Path: relPath, } } @@ -270,7 +320,11 @@ func (lib *library) dumpLibrary() { for _, k := range keys { game := lib.games[k] - gameList.WriteString(fmt.Sprintf(" %7s %s (%s)\n", game.System, game.Name, game.Path)) + alias := game.Alias + if alias != "" { + alias = fmt.Sprintf("[%s] ", game.Alias) + } + gameList.WriteString(fmt.Sprintf(" %7s %s %s(%s)\n", game.System, game.Name, alias, game.Path)) } lib.log.Debug().Msgf("Lib dump\n"+ diff --git a/web/js/gameList.js b/web/js/gameList.js index bb92b34c8..cae642204 100644 --- a/web/js/gameList.js +++ b/web/js/gameList.js @@ -155,7 +155,7 @@ const ui = (() => { const render = () => { rootEl.innerHTML = games.list.map(game => ``) .join('')