Skip to content

Commit 68642cd

Browse files
authored
Merge pull request #127 from keyxmakerx/claude/foundry-module-review-IrVxd
fix: rewrite Foundry module manifest URLs via JSON parsing instead of…
2 parents 257af4d + 1d00ee7 commit 68642cd

1 file changed

Lines changed: 36 additions & 10 deletions

File tree

internal/app/app.go

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package app
66
import (
77
"archive/zip"
88
"database/sql"
9+
"encoding/json"
910
"errors"
1011
"fmt"
1112
"io/fs"
@@ -288,30 +289,33 @@ func (a *App) serveFoundryModuleManifest(c echo.Context) error {
288289
return echo.NewHTTPError(http.StatusNotFound, "module.json not found")
289290
}
290291

291-
baseURL := strings.TrimRight(a.Config.BaseURL, "/")
292-
content := string(data)
292+
var manifest map[string]any
293+
if err := json.Unmarshal(data, &manifest); err != nil {
294+
return echo.NewHTTPError(http.StatusInternalServerError, "invalid module.json")
295+
}
293296

294-
// Replace manifest and download URLs with this Chronicle instance's URLs.
295-
content = strings.Replace(content,
296-
`"manifest": "https://raw.githubusercontent.com/keyxmakerx/Chronicle/main/foundry-module/module.json"`,
297-
fmt.Sprintf(`"manifest": "%s/foundry-module/module.json"`, baseURL), 1)
298-
content = strings.Replace(content,
299-
`"download": "https://github.com/keyxmakerx/Chronicle/releases/download/foundry-v0.1.0/chronicle-sync.zip"`,
300-
fmt.Sprintf(`"download": "%s/foundry-module/chronicle-sync.zip"`, baseURL), 1)
297+
// Always rewrite manifest and download URLs to point at this instance.
298+
baseURL := strings.TrimRight(a.Config.BaseURL, "/")
299+
manifest["manifest"] = baseURL + "/foundry-module/module.json"
300+
manifest["download"] = baseURL + "/foundry-module/chronicle-sync.zip"
301301

302-
return c.JSONBlob(http.StatusOK, []byte(content))
302+
return c.JSON(http.StatusOK, manifest)
303303
}
304304

305305
// serveFoundryModuleZip dynamically zips the foundry-module/ directory and
306306
// serves it as chronicle-sync.zip. Foundry VTT downloads this during module
307307
// installation. The zip contains all files under a chronicle-sync/ root
308308
// directory, which is the expected structure for Foundry module archives.
309+
// The module.json inside the zip gets its manifest/download URLs rewritten
310+
// to point at this Chronicle instance.
309311
func (a *App) serveFoundryModuleZip(c echo.Context) error {
310312
moduleDir := "foundry-module"
311313
if _, err := os.Stat(moduleDir); err != nil {
312314
return echo.NewHTTPError(http.StatusNotFound, "foundry module directory not found")
313315
}
314316

317+
baseURL := strings.TrimRight(a.Config.BaseURL, "/")
318+
315319
c.Response().Header().Set("Content-Type", "application/zip")
316320
c.Response().Header().Set("Content-Disposition", "attachment; filename=chronicle-sync.zip")
317321
c.Response().WriteHeader(http.StatusOK)
@@ -343,6 +347,16 @@ func (a *App) serveFoundryModuleZip(c echo.Context) error {
343347
if err != nil {
344348
return err
345349
}
350+
351+
// Rewrite module.json URLs inside the zip so the installed module
352+
// points back at this Chronicle instance for updates.
353+
if name == "module.json" {
354+
data, err = a.rewriteModuleManifest(data, baseURL)
355+
if err != nil {
356+
return err
357+
}
358+
}
359+
346360
_, err = w.Write(data)
347361
return err
348362
})
@@ -352,6 +366,18 @@ func (a *App) serveFoundryModuleZip(c echo.Context) error {
352366
return zw.Close()
353367
}
354368

369+
// rewriteModuleManifest parses module.json and rewrites the manifest and
370+
// download URLs to point at the given baseURL.
371+
func (a *App) rewriteModuleManifest(data []byte, baseURL string) ([]byte, error) {
372+
var manifest map[string]any
373+
if err := json.Unmarshal(data, &manifest); err != nil {
374+
return data, err
375+
}
376+
manifest["manifest"] = baseURL + "/foundry-module/module.json"
377+
manifest["download"] = baseURL + "/foundry-module/chronicle-sync.zip"
378+
return json.MarshalIndent(manifest, "", " ")
379+
}
380+
355381
// Start begins listening for HTTP requests on the configured port.
356382
func (a *App) Start() error {
357383
addr := fmt.Sprintf(":%d", a.Config.Port)

0 commit comments

Comments
 (0)