diff --git a/backend/internal/api/mods.go b/backend/internal/api/mods.go new file mode 100644 index 0000000..be17a17 --- /dev/null +++ b/backend/internal/api/mods.go @@ -0,0 +1,89 @@ +package api + +import ( + "net/http" + + "arma3-web-server/internal/services" + + "github.com/gin-gonic/gin" +) + +type deleteModInput struct { + Path string `json:"path" binding:"required"` +} + +func (h *Handler) ListMods(c *gin.Context) { + workshopMods := services.ListWorkshopMods(h.serverfileDir) + localMods := services.ListLocalMods(h.modsDir) + + usedWorkshop, usedLocal := services.BuildUsageMap(h.modlists) + + for i := range workshopMods { + if lists, ok := usedWorkshop[workshopMods[i].ID]; ok { + workshopMods[i].InUse = true + workshopMods[i].Modlists = lists + // pull name from first modlist that has it + if workshopMods[i].Name == "" { + workshopMods[i].Name = lists[0] + } + } + } + + for i := range localMods { + // check both the display name and the @name + if lists, ok := usedLocal[localMods[i].ID]; ok { + localMods[i].InUse = true + localMods[i].Modlists = lists + } else if lists, ok := usedLocal[localMods[i].Name]; ok { + localMods[i].InUse = true + localMods[i].Modlists = lists + } + } + + all := append(workshopMods, localMods...) + if all == nil { + all = []services.ModInfo{} + } + c.JSON(http.StatusOK, all) +} + +func (h *Handler) DeleteMod(c *gin.Context) { + var input deleteModInput + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if err := services.RemoveMod(input.Path); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusNoContent, nil) +} + +func (h *Handler) CleanupMods(c *gin.Context) { + workshopMods := services.ListWorkshopMods(h.serverfileDir) + localMods := services.ListLocalMods(h.modsDir) + + usedWorkshop, usedLocal := services.BuildUsageMap(h.modlists) + + var deleted int + for _, m := range workshopMods { + if _, ok := usedWorkshop[m.ID]; !ok { + if err := services.RemoveMod(m.Path); err == nil { + deleted++ + } + } + } + for _, m := range localMods { + if _, ok := usedLocal[m.ID]; !ok { + if _, ok2 := usedLocal[m.Name]; !ok2 { + if err := services.RemoveMod(m.Path); err == nil { + deleted++ + } + } + } + } + + c.JSON(http.StatusOK, gin.H{"deleted": deleted}) +} diff --git a/backend/internal/api/router.go b/backend/internal/api/router.go index 599d079..7d2c686 100644 --- a/backend/internal/api/router.go +++ b/backend/internal/api/router.go @@ -80,6 +80,10 @@ func (h *Handler) SetupRoutes(r *gin.Engine) { api.GET("/modlists/:id/check", h.CheckModlistMods) api.POST("/modlists/:id/download-missing", h.DownloadMissingMods) api.POST("/modlists/:id/update-all", h.UpdateAllMods) + + api.GET("/mods", h.ListMods) + api.DELETE("/mods", h.DeleteMod) + api.POST("/mods/cleanup", h.CleanupMods) } r.GET("/ws/server/logs", h.StreamLogs)