From f79ff46b0c540c09e829cb7cd7d70861637391c8 Mon Sep 17 00:00:00 2001 From: Zsolt Tasnadi Date: Sun, 25 Jan 2026 16:18:24 +0100 Subject: [PATCH] play functionality for every versions --- domain/model.release.go | 1 + http/controller.play.go | 108 ++++++++++++++++++++++++++++-- http/router.go | 6 +- http/views/play/play.html | 23 +++++-- http/views/software/releases.html | 5 +- 5 files changed, 132 insertions(+), 11 deletions(-) diff --git a/domain/model.release.go b/domain/model.release.go index b5ebdc7..c8bb54c 100644 --- a/domain/model.release.go +++ b/domain/model.release.go @@ -8,4 +8,5 @@ type Release struct { Version string `gorm:"size:64" json:"version"` CartridgePath string `gorm:"size:255" json:"-"` SourcePath string `gorm:"size:255" json:"-"` + WebPlayable bool `gorm:"default:false" json:"web_playable"` } diff --git a/http/controller.play.go b/http/controller.play.go index aad09d8..7b1d044 100644 --- a/http/controller.play.go +++ b/http/controller.play.go @@ -21,7 +21,7 @@ func NewPlayController(softwareService domain.SoftwareServiceInterface) *PlayCon } } -func (c *PlayController) Play(w http.ResponseWriter, r *http.Request) { +func (c *PlayController) PlayV1(w http.ResponseWriter, r *http.Request) { name := chi.URLParam(r, "name") if name == "" { http.Error(w, "Name not provided", http.StatusBadRequest) @@ -38,6 +38,58 @@ func (c *PlayController) Play(w http.ResponseWriter, r *http.Request) { return } + var webPlayableRelease *domain.Release + for _, release := range software.Releases { + if release.WebPlayable { + webPlayableRelease = &release + break + } + } + + if webPlayableRelease == nil { + http.Error(w, "No web-playable version found for this software", http.StatusNotFound) + return + } + + http.Redirect(w, r, fmt.Sprintf("/play/%s/%s", name, webPlayableRelease.Version), http.StatusFound) +} + +func (c *PlayController) Play(w http.ResponseWriter, r *http.Request) { + name := chi.URLParam(r, "name") + if name == "" { + http.Error(w, "Name not provided", http.StatusBadRequest) + return + } + + version := chi.URLParam(r, "version") + if version == "" { + http.Error(w, "Version not provided", http.StatusBadRequest) + return + } + + software, err := c.softwareService.GetByNameWithReleases(name) + if err != nil { + if err == domain.ErrSoftwareNotFound { + http.Error(w, "Software not found", http.StatusNotFound) + return + } + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + var webPlayableRelease *domain.Release + for _, release := range software.Releases { + if release.Version == version && release.WebPlayable { + webPlayableRelease = &release + break + } + } + + if webPlayableRelease == nil { + http.Error(w, "No web-playable version found for this software", http.StatusNotFound) + return + } + tmpl, err := template_utils.GetTemplate("play_controller_play", "http/views/shared/layout.html", "http/views/play/play.html") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -45,11 +97,12 @@ func (c *PlayController) Play(w http.ResponseWriter, r *http.Request) { } tmpl.Execute(w, map[string]interface{}{ - "Software": software, + "Software": software, + "WebPlayableRelease": webPlayableRelease, }) } -func (c *PlayController) ServeContent(w http.ResponseWriter, r *http.Request) { +func (c *PlayController) ServeContentV1(w http.ResponseWriter, r *http.Request) { contentsPath := os.Getenv("GAMES_DIR") name := chi.URLParam(r, "name") if name == "" { @@ -57,7 +110,26 @@ func (c *PlayController) ServeContent(w http.ResponseWriter, r *http.Request) { return } - htmlBaseDir := filepath.Join(contentsPath, "html", name) + software, err := c.softwareService.GetByNameWithReleases(name) + if err != nil { + http.Error(w, fmt.Sprintf("Content for '%s' not found.", name), http.StatusNotFound) + return + } + + var webPlayableRelease *domain.Release + for _, release := range software.Releases { + if release.WebPlayable { + webPlayableRelease = &release + break + } + } + + if webPlayableRelease == nil { + http.Error(w, "No web-playable version found for this software", http.StatusNotFound) + return + } + + htmlBaseDir := filepath.Join(contentsPath, "html", name, webPlayableRelease.Version) if _, err := os.Stat(htmlBaseDir); os.IsNotExist(err) { http.Error(w, fmt.Sprintf("Content for '%s' not found.", name), http.StatusNotFound) @@ -70,3 +142,31 @@ func (c *PlayController) ServeContent(w http.ResponseWriter, r *http.Request) { fs := http.StripPrefix(fmt.Sprintf("/play/%s/content", name), http.FileServer(http.Dir(htmlBaseDir))) fs.ServeHTTP(w, r) } + +func (c *PlayController) ServeContent(w http.ResponseWriter, r *http.Request) { + contentsPath := os.Getenv("GAMES_DIR") + name := chi.URLParam(r, "name") + if name == "" { + http.Error(w, "Name not provided", http.StatusBadRequest) + return + } + + version := chi.URLParam(r, "version") + if version == "" { + http.Error(w, "Version not provided", http.StatusBadRequest) + return + } + + htmlBaseDir := filepath.Join(contentsPath, "html", name, version) + + if _, err := os.Stat(htmlBaseDir); os.IsNotExist(err) { + http.Error(w, fmt.Sprintf("Content for '%s' not found.", name), http.StatusNotFound) + return + } else if err != nil { + http.Error(w, fmt.Sprintf("Error accessing content for '%s': %v", name, err), http.StatusInternalServerError) + return + } + + fs := http.StripPrefix(fmt.Sprintf("/play/%s/%s/content", name, version), http.FileServer(http.Dir(htmlBaseDir))) + fs.ServeHTTP(w, r) +} diff --git a/http/router.go b/http/router.go index 0b358e2..23a904e 100755 --- a/http/router.go +++ b/http/router.go @@ -40,8 +40,10 @@ func (r *Router) Init() *chi.Mux { router.Get("/download/{name}/cartridge", r.downloadController.GetLatestCartridge) router.Get("/download/{name}/{version}/source", r.downloadController.GetSource) router.Get("/download/{name}/{version}/cartridge", r.downloadController.GetCartridge) - router.Get("/play/{name}", r.playController.Play) - router.Get("/play/{name}/content*", r.playController.ServeContent) + router.Get("/play/{name}", r.playController.PlayV1) + router.Get("/play/{name}/content*", r.playController.ServeContentV1) + router.Get("/play/{name}/{version}", r.playController.Play) + router.Get("/play/{name}/{version}/content*", r.playController.ServeContent) fs := http.FileServer(http.Dir("assets")) router.Handle("/assets/*", http.StripPrefix("/assets/", fs)) diff --git a/http/views/play/play.html b/http/views/play/play.html index d753057..67c529a 100644 --- a/http/views/play/play.html +++ b/http/views/play/play.html @@ -1,17 +1,32 @@ {{define "content"}}

Play {{.Software.Title}}

-
- +
+
-
+
+
+

Version

+

{{.WebPlayableRelease.Version}}

+

Other Versions

+
+ {{range .Software.Releases}} + {{if and .WebPlayable (ne .Version $.WebPlayableRelease.Version)}} + + {{.Version}} + + {{end}} + {{end}} +
+
+