diff --git a/src/handlers.go b/src/handlers.go index b40a09c..a7fd8d9 100644 --- a/src/handlers.go +++ b/src/handlers.go @@ -12,6 +12,7 @@ import ( "strconv" "time" "github.com/gorilla/mux" + "archive/zip" ) type JSONResponse struct { @@ -34,9 +35,10 @@ func listInstalledModsHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") - mod_list, err := listInstalledModsByFolder() - resp.Data = mod_list.Mods + mods, err := newMods(config.FactorioModsDir) + if err != nil { + w.WriteHeader(500) resp.Data = fmt.Sprintf("Error in ListInstalledMods handler: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in list mods: %s", err) @@ -44,6 +46,7 @@ func listInstalledModsHandler(w http.ResponseWriter, r *http.Request) { return } + resp.Data = mods.listInstalledMods().ModsResult resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -69,6 +72,7 @@ func LoginFactorioModPortal(w http.ResponseWriter, r *http.Request) { w.WriteHeader(statusCode) if err != nil { + w.WriteHeader(500) resp.Data = fmt.Sprintf("Error in getUserToken or LoginFactorioModPortal handler: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in Factorio-Login: %s", err) @@ -101,6 +105,7 @@ func ModPortalSearchHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(statusCode) if err != nil { + w.WriteHeader(500) resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in searchModPortal: %s", err) @@ -133,6 +138,7 @@ func ModPortalDetailsHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(statusCode) if err != nil { + w.WriteHeader(500) resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in searchModPortal: %s", err) @@ -162,12 +168,13 @@ func ModPortalInstallHandler(w http.ResponseWriter, r *http.Request) { filename := r.FormValue("filename") mod_name := r.FormValue("modName") - var statusCode int - resp.Data, err, statusCode = installMod(username, userKey, downloadUrl, filename, mod_name) - - w.WriteHeader(statusCode) + mods, err := newMods(config.FactorioModsDir) + if err == nil { + err = mods.downloadMod(username, userKey, downloadUrl, filename, mod_name) + } if err != nil { + w.WriteHeader(500) resp.Data = fmt.Sprintf("Error in installMod: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in installMod: %s", err) @@ -193,16 +200,21 @@ func ToggleModHandler(w http.ResponseWriter, r *http.Request) { //Get Data out of the request mod_name := r.FormValue("mod_name") - resp.Data, err = toggleMod(mod_name) + mods, err := newMods(config.FactorioModsDir) + if err == nil { + err = mods.ModSimpleList.toggleMod(mod_name) + } if err != nil { - resp.Data = fmt.Sprintf("Error in toggleMod: %s", err) + w.WriteHeader(500) + resp.Data = fmt.Sprintf("Error in listInstalledModsByFolder: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { - log.Printf("Error in toggleMod: %s", err) + log.Printf("Error in listInstalledModsByFolder: %s", err) } return } + resp.Data = mods.listInstalledMods().ModsResult resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -221,9 +233,13 @@ func DeleteModHandler(w http.ResponseWriter, r *http.Request) { //Get Data out of the request mod_name := r.FormValue("mod_name") - resp.Data, err = deleteMod(mod_name) + mods, err := newMods(config.FactorioModsDir) + if err == nil { + mods.deleteMod(mod_name) + } if err != nil { + w.WriteHeader(500) resp.Data = fmt.Sprintf("Error in deleteMod: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in DeleteModHandler: %s", err) @@ -231,6 +247,7 @@ func DeleteModHandler(w http.ResponseWriter, r *http.Request) { return } + resp.Data = mods.listInstalledMods().ModsResult resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -253,21 +270,13 @@ func UpdateModHandler(w http.ResponseWriter, r *http.Request) { download_url := r.FormValue("downloadUrl") file_name := r.FormValue("filename") - _, err = deleteMod(mod_name) - if err != nil { - resp.Data = fmt.Sprintf("Error in deleteMod, installing Mod will not be executed: %s", err) - if err := json.NewEncoder(w).Encode(resp); err != nil { - log.Printf("Error in deleteMod, installing Mod will not be executed: %s", err) - } - return - } - - var statusCode int - resp.Data, err, statusCode = installMod(username, user_key, download_url, file_name, mod_name) - - w.WriteHeader(statusCode) + mods, err := newMods(config.FactorioModsDir) + if err == nil { + err = mods.updateMod(mod_name, username, user_key, download_url, file_name) + } if err != nil { + w.WriteHeader(500) resp.Data = fmt.Sprintf("Error in deleteMod: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in DeleteModHandler: %s", err) @@ -275,6 +284,7 @@ func UpdateModHandler(w http.ResponseWriter, r *http.Request) { return } + resp.Data = mods.listInstalledMods() resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -292,16 +302,17 @@ func UploadModHandler(w http.ResponseWriter, r *http.Request) { r.ParseMultipartForm(32 << 20) - //get file out of the POST - for file_key, mod_file := range r.MultipartForm.File["mod_file"] { - err = uploadMod(mod_file) - if err != nil { - resp.ErrorKeys = append(resp.ErrorKeys, file_key) - resp.Error = "An error occurred during upload or saving, pls check manually, if all went well and delete invalid files. (This program also could be crashed)" + mods, err := newMods(config.FactorioModsDir) + if err == nil { + for file_key, mod_file := range r.MultipartForm.File["mod_file"] { + err = mods.uploadMod(mod_file) + if err != nil { + resp.ErrorKeys = append(resp.ErrorKeys, file_key) + resp.Error = "An error occurred during upload or saving, pls check manually, if all went well and delete invalid files. (This program also could be crashed)" + } } } - resp.Data, err = listInstalledModsByFolder() if err != nil { w.WriteHeader(500) resp.Data = fmt.Sprintf("Error in uploadMod, listing mods wasn't successful: %s", err) @@ -311,6 +322,7 @@ func UploadModHandler(w http.ResponseWriter, r *http.Request) { return } + resp.Data = mods.listInstalledMods() resp.Success = true if err = json.NewEncoder(w).Encode(resp); err != nil { @@ -326,12 +338,10 @@ func ListModPacksHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") - var mod_packs ModPackList - err = mod_packs.getModPacks() - - resp.Data = mod_packs + mod_pack_map, err := newModPackMap() if err != nil { + w.WriteHeader(500) w.WriteHeader(http.StatusInternalServerError) resp.Data = fmt.Sprintf("Error listing modpack files: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -340,6 +350,7 @@ func ListModPacksHandler(w http.ResponseWriter, r *http.Request) { return } + resp.Data = mod_pack_map.listInstalledModPacks() resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -357,7 +368,11 @@ func CreateModPackHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") - resp.Data, err = createModPack(name) + mod_pack_map, err := newModPackMap() + if err == nil { + err = mod_pack_map.createModPack(name) + } + if err != nil { w.WriteHeader(http.StatusInternalServerError) resp.Data = fmt.Sprintf("Error creating modpack file: %s", err) @@ -367,6 +382,7 @@ func CreateModPackHandler(w http.ResponseWriter, r *http.Request) { return } + resp.Data = mod_pack_map.listInstalledModPacks() resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -375,16 +391,61 @@ func CreateModPackHandler(w http.ResponseWriter, r *http.Request) { } func DownloadModPackHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/zip;charset=UTF-8") + var err error vars := mux.Vars(r) modpack := vars["modpack"] - modFile := config.FactorioModPackDir + "/" + modpack + ".zip" - w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", modpack + ".zip")) - log.Printf("%s downloading: %s", r.Host, modFile) + mod_pack_map, err := newModPackMap() + if err != nil { + log.Printf("error on loading modPacks: %s", err) + w.WriteHeader(http.StatusInternalServerError) + return + } - http.ServeFile(w, r, modFile) + if mod_pack_map.checkModPackExists(modpack) { + zip_writer := zip.NewWriter(w) + defer zip_writer.Close() + + //iterate over folder and create everything in the zip + err = filepath.Walk(filepath.Join(config.FactorioModPackDir, modpack), func(path string, info os.FileInfo, err error) error { + if info.IsDir() == false { + writer, err := zip_writer.Create(info.Name()) + if err != nil { + log.Printf("error on creating new file inside zip: %s", err) + return err + } + + file, err := os.Open(path) + if err != nil { + log.Printf("error on opening modfile: %s", err) + return err + } + defer file.Close() + + _, err = io.Copy(writer, file) + if err != nil { + log.Printf("error on copying file into zip: %s", err) + return err + } + } + + return nil + }) + if err != nil { + log.Printf("error on walking over the modpack: %s", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + } else { + log.Printf("requested modPack doesnt exist") + w.WriteHeader(http.StatusNotFound) + return + } + + writer_header := w.Header() + writer_header.Set("Content-Type", "application/zip;charset=UTF-8") + writer_header.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", modpack + ".zip")) } func DeleteModPackHandler(w http.ResponseWriter, r *http.Request) { @@ -397,7 +458,11 @@ func DeleteModPackHandler(w http.ResponseWriter, r *http.Request) { name := r.FormValue("name") - resp.Data, err = deleteModPack(name) + mod_pack_map, err := newModPackMap() + if err == nil { + err = mod_pack_map.deleteModPack(name) + } + if err != nil { w.WriteHeader(http.StatusInternalServerError) resp.Data = fmt.Sprintf("Error deleting modpack file: %s", err) @@ -407,6 +472,7 @@ func DeleteModPackHandler(w http.ResponseWriter, r *http.Request) { return } + resp.Data = mod_pack_map.listInstalledModPacks() resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -424,7 +490,11 @@ func LoadModPackHandler(w http.ResponseWriter, r *http.Request) { name := r.FormValue("name") - resp.Data, err = loadModPack(name) + mod_pack_map, err := newModPackMap() + if err == nil { + mod_pack_map[name].loadModPack() + } + if err != nil { w.WriteHeader(http.StatusInternalServerError) resp.Data = fmt.Sprintf("Error loading modpack file: %s", err) @@ -434,6 +504,7 @@ func LoadModPackHandler(w http.ResponseWriter, r *http.Request) { return } + resp.Data = mod_pack_map[name].Mods.listInstalledMods() resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -441,6 +512,38 @@ func LoadModPackHandler(w http.ResponseWriter, r *http.Request) { } } +func ModPackToggleModHandler(w http.ResponseWriter, r *http.Request) { + var err error + resp := JSONResponse{ + Success: false, + } + + w.Header().Set("Content-Type", "application/json;charset=UTF-8") + + mod_name := r.FormValue("mod_name") + mod_pack_name := r.FormValue("mod_pack") + + mod_pack_map, err := newModPackMap() + if err == nil { + err = mod_pack_map[mod_pack_name].Mods.ModSimpleList.toggleMod(mod_name) + } + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + resp.Data = fmt.Sprintf("Error loading modpack file: %s", err) + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error loading modpack: %s", err) + } + return + } + + resp.Data = mod_pack_map[mod_pack_name].Mods.listInstalledMods() + resp.Success = true + + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error creating loading modpack response: %s", err) + } +} + // Lists all save files in the factorio/saves directory func ListSaves(w http.ResponseWriter, r *http.Request) { var err error diff --git a/src/mod_Mods.go b/src/mod_Mods.go new file mode 100644 index 0000000..ec9ff61 --- /dev/null +++ b/src/mod_Mods.go @@ -0,0 +1,212 @@ +package main + +import ( + "log" + "net/http" + "io" + "io/ioutil" + "mime/multipart" + "bytes" + "archive/zip" +) + +type Mods struct { + ModSimpleList ModSimpleList `json:"mod_simple_list"` + ModInfoList ModInfoList `json:"mod_info_list"` +} +type ModsResult struct { + ModInfo + Enabled bool `json:"enabled"` +} +type ModsResultList struct { + ModsResult []ModsResult `json:"mods"` +} + +func newMods(destination string) (Mods, error) { + var err error + var mods Mods + + mods.ModSimpleList, err = newModSimpleList(destination) + if err != nil { + log.Printf("error on creating newModSimpleList: %s", err) + return mods, err + } + + mods.ModInfoList, err = newModInfoList(destination) + if err != nil { + log.Printf("error on creating newModInfoList: %s", err) + return mods, err + } + + return mods, nil +} + +func (mods *Mods) listInstalledMods() ModsResultList { + var result ModsResultList + + for _, mod_info := range mods.ModInfoList.Mods { + var mods_result ModsResult + mods_result.Name = mod_info.Name + mods_result.FileName = mod_info.FileName + mods_result.Author = mod_info.Author + mods_result.Title = mod_info.Title + mods_result.Version = mod_info.Version + + for _, simple_mod := range mods.ModSimpleList.Mods { + if simple_mod.Name == mods_result.Name { + mods_result.Enabled = simple_mod.Enabled + break + } + } + + result.ModsResult = append(result.ModsResult, mods_result) + } + + return result +} + +func (mods *Mods) deleteMod(mod_name string) (error) { + var err error + + err = mods.ModInfoList.deleteMod(mod_name) + if err != nil { + log.Printf("error when deleting mod in ModInfoList: %s", err) + return err + } + + err = mods.ModSimpleList.deleteMod(mod_name) + if err != nil { + log.Printf("error when deleting mod in ModSimpleList: %s", err) + return err + } + + return nil +} + +func (mods *Mods) createMod(mod_name string, file_name string, file_rc io.Reader) (error) { + var err error + + //check if mod already exists and delete it + if mods.ModSimpleList.checkModExists(mod_name) { + err = mods.ModSimpleList.deleteMod(mod_name) + if err != nil { + log.Printf("error when deleting mod: %s", err) + return err + } + + err = mods.ModInfoList.deleteMod(mod_name) + if err != nil { + log.Printf("error when deleting mod: %s", err) + return err + } + } + + + //create new mod + err = mods.ModInfoList.createMod(mod_name, file_name, file_rc) + if err != nil { + log.Printf("error on creating mod-file: %s", err) + return err + } + err = mods.ModSimpleList.createMod(mod_name) + if err != nil { + log.Printf("error on adding mod to the mod-list.json: %s", err) + return err + } + + return nil +} + +func (mods *Mods) downloadMod(username string, userKey string, url string, filename string, mod_id string) (error) { + var err error + + //download the mod from the mod portal api + complete_url := "https://mods.factorio.com" + url + "?username=" + username + "&token=" + userKey + + response, err := http.Get(complete_url) + if err != nil { + log.Printf("error on downloading mod: %s", err) + return err + } + + defer response.Body.Close() + + if response.StatusCode != 200 { + text, _ := ioutil.ReadAll(response.Body) + log.Printf("StatusCode: %d \n ResponseBody: %s", response.StatusCode, text) + + return err + } + + err = mods.createMod(mod_id, filename, response.Body) + if err != nil { + log.Printf("error when creating Mod: %s", err) + return err + } + + //done everything is made inside the createMod + + return nil +} + +func (mods *Mods) uploadMod(header *multipart.FileHeader) (error) { + var err error + + if header.Header.Get("Content-Type") != "application/zip" { + log.Print("The uploaded file wasn't a zip-file -> ignore it") + return nil //simply do nothing xD + } + + file, err := header.Open() + if err != nil { + log.Printf("error on open file via fileHeader. %s", err) + return err + } + defer file.Close() + + var buff bytes.Buffer + file_length, err := buff.ReadFrom(file) + if err != nil { + log.Printf("Error occured while reading bytes.Buffer.ReadFrom: %s", err) + return err + } + + zip_reader, err := zip.NewReader(file, file_length) + if err != nil { + log.Printf("Uploaded file could not put into zip.Reader: %s", err) + return err + } + + var mod_info ModInfo + err = mod_info.getModInfo(zip_reader) + if err != nil { + log.Printf("Error in getModInfo: %s", err) + return err + } + + err = mods.createMod(mod_info.Name, header.Filename, file) + if err != nil { + log.Printf("error on creating Mod: %s", err) + return err + } + + return nil +} + +func (mods *Mods) updateMod(mod_name string, username string, userKey string, url string, filename string) error { + var err error + + err = mods.deleteMod(mod_name) + if err != nil { + log.Printf("updateMod ... error when deleting mod: %s", err) + return err + } + + err = mods.downloadMod(username, userKey, url, filename, mod_name) + if err != nil { + log.Printf("updateMod ... error hen downloading the new Mod: %s", err) + return err + } + + return nil +} \ No newline at end of file diff --git a/src/mod_modInfo.go b/src/mod_modInfo.go new file mode 100644 index 0000000..9d4e102 --- /dev/null +++ b/src/mod_modInfo.go @@ -0,0 +1,164 @@ +package main + +import ( + "log" + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + "archive/zip" + "errors" + "io" +) + +type ModInfoList struct { + Mods []ModInfo `json:"mods"` + Destination string `json:"-"` +} +type ModInfo struct { + Name string `json:"name"` + Version string `json:"version"` + Title string `json:"title"` + Author string `json:"author"` + FileName string `json:"file_name"` +} + +func newModInfoList(destination string) (ModInfoList, error) { + var err error + mod_info_list := ModInfoList{ + Destination: destination, + } + + err = mod_info_list.listInstalledMods() + if err != nil { + log.Printf("ModInfoList ... error listing installed Mods: %s", err) + return mod_info_list, err + } + + return mod_info_list, nil +} + +func (mod_info_list *ModInfoList) listInstalledMods() (error) { + var err error + mod_info_list.Mods = nil + + err = filepath.Walk(mod_info_list.Destination, func(path string, info os.FileInfo, err error) error { + if !info.IsDir() && filepath.Ext(path) == ".zip" { + zip_file, err := zip.OpenReader(path) + if err != nil { + log.Fatalln(err) + return err + } + + var mod_info ModInfo + err = mod_info.getModInfo(&zip_file.Reader) + if err != nil { + log.Fatalf("Error in getModInfo: %s", err) + } + + mod_info.FileName = info.Name() + mod_info_list.Mods = append(mod_info_list.Mods, mod_info) + } + + return nil + }) + + if err != nil { + log.Printf("error while walking over the given dir: %s", err) + return err + } + + return nil +} + +func (mod_info_list *ModInfoList) deleteMod(mod_name string) (error) { + var err error + + //search for mod, that should be deleted + for _, mod := range mod_info_list.Mods { + if mod.Name == mod_name { + //delete mod + err = os.Remove(mod_info_list.Destination + "/" + mod.FileName) + if err != nil { + log.Printf("ModInfoList ... error when deleting mod: %s", err) + return err + } + + //reload mod-list + err = mod_info_list.listInstalledMods() + if err != nil { + log.Printf("ModInfoList ... error while refreshing installedModList: %s", err) + return err + } + + return nil + } + } + + log.Printf("the mod-file doesnt exists!") + return nil +} + +func (mod_info *ModInfo) getModInfo(reader *zip.Reader) error { + for _, single_file := range reader.File { + if single_file.FileInfo().Name() == "info.json" { + //interpret info.json + rc, err := single_file.Open() + + if err != nil { + log.Fatal(err) + return err + } + + byte_array, err := ioutil.ReadAll(rc) + rc.Close() + if err != nil { + log.Fatal(err) + return err + } + + err = json.Unmarshal(byte_array, mod_info) + if err != nil { + log.Fatalln(err) + return err + } + + return nil + } + } + + return errors.New("info.json not found in zip-file") +} + +func (mod_info_list ModInfoList) createMod(mod_name string, file_name string, mod_file io.Reader) error { + var err error + + //save uploaded file + new_file, err := os.Create(mod_info_list.Destination + "/" + file_name) + if err != nil { + log.Printf("error on creating new file - %s: %s", file_name, err) + return err + } + defer new_file.Close() + + _, err = io.Copy(new_file, mod_file) + if err != nil { + log.Printf("error on copying file to disk: %s", err) + return err + } + + //reload the list + err = new_file.Close() + if err != nil { + log.Printf("error on closing new created zip-file: %s", err) + return err + } + + err = mod_info_list.listInstalledMods() + if err != nil { + log.Printf("error on listing mod-infos: %s", err) + return err + } + + return nil +} diff --git a/src/mod_modSimple.go b/src/mod_modSimple.go new file mode 100644 index 0000000..0434448 --- /dev/null +++ b/src/mod_modSimple.go @@ -0,0 +1,143 @@ +package main + +import ( + "log" + "io/ioutil" + "encoding/json" +) + +type ModSimple struct { + Name string `json:"name"` + Enabled bool `json:"enabled"` +} + +type ModSimpleList struct { + Mods []ModSimple `json:"mods"` + Destination string `json:"-"` +} + +func newModSimpleList(destination string) (ModSimpleList, error) { + var err error + + mod_simple_list := ModSimpleList{ + Destination: destination, + } + + err = mod_simple_list.listInstalledMods() + if err != nil { + log.Printf("ModSimpleList ... error list installed mods: %s", err) + return mod_simple_list, err + } + + return mod_simple_list, nil +} + +func (mod_simple_list *ModSimpleList) listInstalledMods() (error) { + var err error + + file, err := ioutil.ReadFile(mod_simple_list.Destination + "/mod-list.json") + if err != nil { + log.Printf("ModSimpleList ... error read the mod-info.json: %s", err) + return err + } + + err = json.Unmarshal(file, mod_simple_list) + if err != nil { + log.Printf("ModSimpleList ... error while decode mod-info.json: %s", err) + return err + } + + return nil +} + +func (mod_simple_list *ModSimpleList) saveModInfoJson() (error) { + var err error + + //build json of current state + new_json, _ := json.Marshal(mod_simple_list) + + err = ioutil.WriteFile(mod_simple_list.Destination + "/mod-list.json", new_json, 0664) + if err != nil { + log.Printf("error when writing new mod-list: %s", err) + return err + } + + return nil +} + +func (mod_simple_list *ModSimpleList) deleteMod(mod_name string) (error) { + var err error + + for index, mod := range mod_simple_list.Mods { + if mod.Name == mod_name { + slice1 := mod_simple_list.Mods[:index] + slice2 := mod_simple_list.Mods[index + 1:] + var new_mod_list []ModSimple + new_mod_list = append(new_mod_list, slice1...) + new_mod_list = append(new_mod_list, slice2...) + mod_simple_list.Mods = new_mod_list + break + } + } + + err = mod_simple_list.saveModInfoJson() + if err != nil { + log.Printf("error when saving new mod_list: %s", err) + return err + } + + return nil +} + +func (mod_simple_list *ModSimpleList) checkModExists(mod_name string) (bool) { + for _, single_mod := range mod_simple_list.Mods { + if single_mod.Name == mod_name { + return true + } + } + + return false +} + +func (mod_simple_list *ModSimpleList) createMod(mod_name string) (error) { + var err error + + new_mod_simple := ModSimple{ + Name: mod_name, + Enabled: true, + } + + mod_simple_list.Mods = append(mod_simple_list.Mods, new_mod_simple) + + err = mod_simple_list.saveModInfoJson() + if err != nil { + log.Printf("error when saving new Info.json: %s", err) + return err + } + + //reloading not necessary, just changed it live xD + + return nil +} + + +func (mod_simple_list *ModSimpleList) toggleMod(mod_name string) error { + var err error + + for index, mod := range mod_simple_list.Mods { + if mod.Name == mod_name { + mod_simple_list.Mods[index].Enabled = !mod_simple_list.Mods[index].Enabled + break + } + } + + err = mod_simple_list.saveModInfoJson() + if err != nil { + log.Printf("error on savin new ModSimpleList: %s", err) + return err + } + + //i changed it already don't need to reload it + + return nil +} diff --git a/src/mod_modpacks.go b/src/mod_modpacks.go new file mode 100644 index 0000000..2e314a1 --- /dev/null +++ b/src/mod_modpacks.go @@ -0,0 +1,280 @@ +package main + +import ( + "path/filepath" + "log" + "os" + "errors" + "io/ioutil" + "io" +) + +type ModPackMap map[string]*ModPack +type ModPack struct { + Mods Mods +} + +type ModPackResult struct { + Name string `json:"name"` + Mods ModsResultList `json:"mods"` +} +type ModPackResultList struct { + ModPacks []ModPackResult `json:"mod_packs"` +} + +func newModPackMap() (ModPackMap, error) { + var err error + //var mod_pack_map ModPackMap + mod_pack_map := make(ModPackMap) + + err = mod_pack_map.reload() + if err != nil { + log.Printf("error on loading the modpacks: %s", err) + return mod_pack_map, err + } + + return mod_pack_map, nil +} + +func newModPack(mod_pack_folder string) (*ModPack, error) { + var err error + var mod_pack ModPack + + mod_pack.Mods, err = newMods(mod_pack_folder) + if err != nil { + log.Printf("error on loading mods in mod_pack_dir: %s", err) + return &mod_pack, err + } + + return &mod_pack, err +} + +func (mod_pack_map *ModPackMap) reload() error { + var err error + new_mod_pack_map := make(ModPackMap) + + err = filepath.Walk(config.FactorioModPackDir, func(path string, info os.FileInfo, err error) error { + if path == config.FactorioModPackDir || !info.IsDir() { + return nil + } + + mod_pack_name := filepath.Base(path) + + new_mod_pack_map[mod_pack_name], err = newModPack(path) + if err != nil { + log.Printf("error on creating newModPack: %s", err) + return err + } + + return nil + }) + if err != nil { + log.Printf("error on walking over the ModDir: %s", err) + return err + } + + *mod_pack_map = new_mod_pack_map + + return nil +} + +func (mod_pack_map *ModPackMap) listInstalledModPacks() ModPackResultList { + var mod_pack_result_list ModPackResultList + + for mod_pack_name, mod_pack := range *mod_pack_map { + var mod_pack_result ModPackResult + mod_pack_result.Name = mod_pack_name + mod_pack_result.Mods = mod_pack.Mods.listInstalledMods() + + mod_pack_result_list.ModPacks = append(mod_pack_result_list.ModPacks, mod_pack_result) + } + + return mod_pack_result_list +} + +func (mod_pack_map *ModPackMap) createModPack(mod_pack_name string) error { + var err error + + mod_pack_folder := filepath.Join(config.FactorioModPackDir, mod_pack_name) + + if mod_pack_map.checkModPackExists(mod_pack_name) == true { + log.Printf("ModPack %s already existis", mod_pack_name) + return errors.New("ModPack " + mod_pack_name + " already exists, please choose a different name") + } + + source_file_info, err := os.Stat(config.FactorioModsDir) + if err != nil { + log.Printf("error when reading factorioModsDir. %s", err) + return err + } + + //Create the modPack-folder + err = os.MkdirAll(mod_pack_folder, source_file_info.Mode()) + if err != nil { + log.Printf("error on creating the new ModPack directory: %s", err) + return err + } + + files, err := ioutil.ReadDir(config.FactorioModsDir) + if err != nil { + log.Printf("error on reading the dactorio mods dir: %s", err) + return err + } + + for _, file := range files { + if file.IsDir() == false { + source_filepath := filepath.Join(config.FactorioModsDir, file.Name()) + destination_filepath := filepath.Join(mod_pack_folder, file.Name()) + + source_file, err := os.Open(source_filepath) + if err != nil { + log.Printf("error on opening source_filepath: %s", err) + return err + } + defer source_file.Close() + + destination_file, err := os.Create(destination_filepath) + if err != nil { + log.Printf("error on creating destination_filepath: %s", err) + return err + } + defer destination_file.Close() + + _, err = io.Copy(destination_file, source_file) + if err != nil { + log.Printf("error on copying data from source to destination: %s", err) + return err + } + + source_file.Close() + destination_file.Close() + } + } + + //reload the ModPackList + err = mod_pack_map.reload() + if err != nil { + log.Printf("error on reloading ModPack: %s", err) + return err + } + + return nil +} + +func (mod_pack_map *ModPackMap) checkModPackExists(mod_pack_name string) bool { + for mod_pack_id := range *mod_pack_map { + if mod_pack_id == mod_pack_name { + return true + } + } + + return false +} + +func (mod_pack_map *ModPackMap) deleteModPack(mod_pack_name string) error { + var err error + + mod_pack_dir := filepath.Join(config.FactorioModPackDir, mod_pack_name) + + err = os.RemoveAll(mod_pack_dir) + if err != nil { + log.Printf("error on removing the ModPack: %s", err) + return err + } + + err = mod_pack_map.reload() + if err != nil { + log.Printf("error on reloading the ModPackList: %s", err) + return err + } + + return nil +} + +func (mod_pack *ModPack) loadModPack() error { + var err error + + //get filemode, so it can be restored + file_info, err := os.Stat(config.FactorioModsDir) + if err != nil { + log.Printf("error on trying to save folder infos: %s", err) + return err + } + folder_mode := file_info.Mode() + + //clean factorio mod directory + err = os.RemoveAll(config.FactorioModsDir) + if err != nil { + log.Printf("error on removing the factorio mods dir: %s", err) + return err + } + + err = os.Mkdir(config.FactorioModsDir, folder_mode) + if err != nil { + log.Printf("error on recreating mod dir: %s", err) + return err + } + + //copy the modpack folder to the normal mods directory + err = filepath.Walk(mod_pack.Mods.ModInfoList.Destination, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + new_file, err := os.Create(filepath.Join(config.FactorioModsDir, info.Name())) + if err != nil { + log.Printf("error on creting mod file: %s", err) + return err + } + defer new_file.Close() + + old_file, err := os.Open(path) + if err != nil { + log.Printf("error on opening modFile: %s", err) + return err + } + defer old_file.Close() + + _ ,err = io.Copy(new_file, old_file) + if err != nil { + log.Printf("error on copying data to the new file: %s", err) + return err + } + + return nil + }) + if err != nil { + log.Printf("error on copying the mod pack: %s", err) + return err + } + + //mods, err := newMods(config.FactorioModsDir) + + return nil +} + +//func modPackToggleMod(mod_pack_name string, mod_name string) (ModPackList, error) { +// //var err error +// //var mod_pack_list ModPackList +// // +// //mod_pack := ModPack{ +// // Name: mod_pack_name, +// //} +// // +// //temp_dir, err := mod_pack.create_temp_dir() +// //if err != nil { +// // log.Printf("error when creating temp_dir: %s", err) +// // return mod_pack_list, err +// //} +// //defer os.RemoveAll(temp_dir) +// // +// //var mods_list ModsList +// //err = mods_list.listInstalledMods(temp_dir) +// //if err != nil { +// // log.Printf("error on listing mods in temp_dir: %s", err) +// // return mod_pack_list, err +// //} +// // +// //log.Print(mods_list) +// +// return ModPackList{}, nil +//} diff --git a/src/mods.go b/src/mods.go index be3f950..23c6a5c 100644 --- a/src/mods.go +++ b/src/mods.go @@ -1,232 +1,12 @@ package main import ( - "io/ioutil" - "log" - "encoding/json" "net/http" "net/url" - "os" - "io" - "path/filepath" - "archive/zip" - "mime/multipart" - "errors" - "bytes" + "log" + "io/ioutil" ) -type Mod struct { - Name string `json:"name"` - Enabled bool `json:"enabled"` -} - -type ModsList struct { - Mods []Mod `json:"mods"` -} - -func (mod_list *ModsList) check_mod_exists(mod_name string) bool { - for _, single_mod := range mod_list.Mods { - if single_mod.Name == mod_name { - return true - } - } - - return false -} - -// List mods installed in the factorio/mods directory -func listInstalledMods() (ModsList, error) { - file, err := ioutil.ReadFile(config.FactorioModsDir + "/mod-list.json") - - if err != nil { - log.Println(err.Error()) - } - - var result ModsList - err_json := json.Unmarshal(file, &result) - - if err_json != nil { - log.Println(err_json.Error()) - return result, err_json - } - - return result, nil -} - -type ModInfoList struct { - Mods []ModInfo `json:"mods"` -} -type ModInfo struct { - Name string `json:"name"` - Version string `json:"version"` - Title string `json:"title"` - Author string `json:"author"` - FileName string `json:"file_name"` - Enabled bool `json:"enabled"` -} - -func (mod_info *ModInfo) getModInfo(reader *zip.Reader) error { - for _, single_file := range reader.File { - if single_file.FileInfo().Name() == "info.json" { - //interpret info.json - rc, err := single_file.Open() - - if err != nil { - log.Fatal(err) - return err - } - - byte_array, err := ioutil.ReadAll(rc) - rc.Close() - if err != nil { - log.Fatal(err) - return err - } - - //var mod_info ModInfo - err = json.Unmarshal(byte_array, mod_info) - if err != nil { - log.Fatalln(err) - return err - } - - return nil - } - } - - return errors.New("info.json not found in zip-file!") -} - -func listInstalledModsByFolder() (ModInfoList, error) { - //scan ModFolder - var result ModInfoList - var err_o error - err_o = filepath.Walk(config.FactorioModsDir, func(path string, info os.FileInfo, err error) error { - if !info.IsDir() && filepath.Ext(path) == ".zip" { - zip_file, err := zip.OpenReader(path) - if err != nil { - log.Fatalln(err) - return err - } - - var mod_info ModInfo - err = mod_info.getModInfo(&zip_file.Reader) - if err != nil { - log.Fatalf("Error in getModInfo: %s", err) - } - - mod_info.FileName = info.Name() - result.Mods = append(result.Mods, mod_info) - } - - return nil - }) - - if err_o != nil { - return ModInfoList{}, err_o - } - - mod_list_by_json, err_o := listInstalledMods() - if err_o != nil { - return ModInfoList{}, err_o - } - - for _, json_mod := range mod_list_by_json.Mods { - for result_index, result_mod := range result.Mods { - if result_mod.Name == json_mod.Name { - result.Mods[result_index].Enabled = json_mod.Enabled - break - } - } - } - - return result, nil -} - -func toggleMod(mod_name string)([]ModInfo, error) { - var err error - - mod_list, err := listInstalledMods() - - if err != nil { - return nil, err - } - - for index, mod := range mod_list.Mods { - if mod.Name == mod_name { - mod_list.Mods[index].Enabled = !mod_list.Mods[index].Enabled - break - } - } - - //build new json - new_json, _ := json.Marshal(mod_list) - - ioutil.WriteFile(config.FactorioModsDir + "/mod-list.json", new_json, 0664) - - mod_info_list, err := listInstalledModsByFolder() - if err != nil { - log.Fatal(err) - return nil, err - } - - return mod_info_list.Mods, nil -} - -func deleteMod(mod_name string) ([]ModInfo, error) { - var err error - mod_list, err := listInstalledMods() - - if err != nil { - return nil, err - } - - for index, mod := range mod_list.Mods { - if mod.Name == mod_name { - slice1 := mod_list.Mods[:index] - slice2 := mod_list.Mods[index + 1:] - var new_mod_list []Mod - new_mod_list = append(new_mod_list, slice1...) - new_mod_list = append(new_mod_list, slice2...) - mod_list.Mods = new_mod_list - break - } - } - - //build new json - new_json, _ := json.Marshal(mod_list) - - ioutil.WriteFile(config.FactorioModsDir + "/mod-list.json", new_json, 0664) - - mod_info_list, err := listInstalledModsByFolder() - if err != nil { - log.Fatal(err) - return nil, err - } - - var delete_file_name string - //search for mod in own setup - for index, mod := range mod_info_list.Mods { - if mod.Name == mod_name { - delete_file_name = mod.FileName - - //remove mod from list (faster than scanning path new) - slice1 := mod_info_list.Mods[:index] - slice2 := mod_info_list.Mods[index+1:] - var new_mod_list []ModInfo - new_mod_list = append(new_mod_list, slice1...) - new_mod_list = append(new_mod_list, slice2...) - mod_info_list.Mods = new_mod_list - break - } - } - - os.Remove(config.FactorioModsDir + "/" + delete_file_name) - - return mod_info_list.Mods, nil -} - - type LoginErrorResponse struct { Message string `json:"message"` Status int `json:"status"` @@ -308,415 +88,3 @@ func getModDetails(modId string) (string, error, int) { return text_string, nil, resp.StatusCode } - -func installMod(username string, userKey string, url string, filename string, mod_id string) ([]ModInfo, error, int) { - var err error - //download the mod from the mod portal api - complete_url := "https://mods.factorio.com" + url + "?username=" + username + "&token=" + userKey - - mod_list, err := listInstalledMods() - if err != nil { - return nil, err, 500 - } - - if mod_list.check_mod_exists(mod_id) { - log.Printf("delete old mod %s.", mod_id) - _, err = deleteMod(mod_id) - if err != nil { - log.Printf("error on deleting mod: %s", err) - return nil, err, 500 - } - } - - // don't worry about errors - response, err := http.Get(complete_url) - if err != nil { - log.Fatal(err) - return nil, err, 500 - } - - if response.StatusCode != 200 { - text, _ := ioutil.ReadAll(response.Body) - log.Printf("StatusCode: %d \n ResponseBody: %s", response.StatusCode, text) - - defer response.Body.Close() - return nil, err, response.StatusCode - } - - defer response.Body.Close() - - //open a file for writing - file, err := os.Create(config.FactorioModsDir + "/" + filename) - if err != nil { - log.Fatal(err) - return nil, err, 500 - } - // Use io.Copy to just dump the response body to the file. This supports huge files - _, err = io.Copy(file, response.Body) - if err != nil { - log.Fatal(err) - return nil, err, 500 - } - file.Close() - - mod_list, err = listInstalledMods() - if err != nil { - return nil, err, 500 - } - - //add new mod - new_mod_entry := Mod{ - Name: mod_id, - Enabled:true, - } - mod_list.Mods = append(mod_list.Mods, new_mod_entry) - - //build new json - new_json, _ := json.Marshal(mod_list) - - ioutil.WriteFile(config.FactorioModsDir + "/mod-list.json", new_json, 0664) - - mod_info_list, err := listInstalledModsByFolder() - if err != nil { - log.Fatal(err) - return nil, err, 500 - } - - return mod_info_list.Mods, nil, response.StatusCode -} - -func uploadMod(header *multipart.FileHeader) (error) { - var err error - if header.Header.Get("Content-Type") != "application/zip" { - log.Print("The uploaded file wasn't a zip-file -> ignore it") - return nil //simply do nothing xD - } - - if _,err_file := os.Stat(config.FactorioModsDir + "/" + header.Filename); !os.IsNotExist(err_file) { - log.Print("The uploaded file already exists -> ignore it") - return nil //simply do nothing xD - } - - file, err := header.Open() - if err != nil { - log.Printf("error on open file via fileHeader. %s", err) - return err - } - - var buff bytes.Buffer - file_length, err := buff.ReadFrom(file) - if err != nil { - log.Printf("Error occured while reading bytes.Buffer.ReadFrom: %s", err) - return err - } - - zip_reader, err := zip.NewReader(file, file_length) - if err != nil { - log.Printf("Uploaded file could not put into zip.Reader: %s", err) - return err - } - - var mod_info ModInfo - err = mod_info.getModInfo(zip_reader) - if err != nil { - log.Printf("Error in getModInfo: %s", err) - return err - } - - //check if mod already exists in mod_list.json - mods_list, err := listInstalledMods() - if err != nil { - log.Printf("Error in listInstalledMods: %s", err) - return err - } - - mod_already_exists := mods_list.check_mod_exists(mod_info.Name) - - if mod_already_exists { - _, err = deleteMod(mod_info.Name) - if err != nil { - log.Printf("error when trying to delete mod: %s", err) - return err - } - } - - //save uploaded file - new_file, err := os.Create(config.FactorioModsDir + "/" + header.Filename) - if err != nil { - log.Printf("error on creating new file - %s: %s", header.Filename, err) - return err - } - defer new_file.Close() - - file.Seek(0,0) //reset file-cursor to 0,0 - _, err = io.Copy(new_file, file) - if err != nil { - log.Printf("error on copying file to disk: %s", err) - return err - } - - //build new json - mods_list, err = listInstalledMods() - if err != nil { - log.Printf("Error in listInstalledMods: %s", err) - return err - } - - //add this mod - mods_list.Mods = append(mods_list.Mods, Mod{ - Name: mod_info.Name, - Enabled: true, - }) - - //save mod-list.json with the new mod - new_json, _ := json.Marshal(mods_list) - ioutil.WriteFile(config.FactorioModsDir + "/mod-list.json", new_json, 0664) - - return nil -} - -type ModPack struct { - Name string `json:"name"` - Mods ModInfoList `json:"mods"` -} - -func (mod_pack *ModPack) readModPack(reader zip.Reader) error { - //var err error - var mod_info_list ModInfoList - var pack_list ModsList - - for _, mod_file := range reader.File { - mod_file_rc, err := mod_file.Open() - if err != nil { - log.Printf("Error opening mod_file: %s", err) - return err - } - - mod_file_b, err := ioutil.ReadAll(mod_file_rc) - if err != nil { - log.Printf("Error on reading file to RAM: %s", err) - return err - } - - if filepath.Ext(mod_file.Name) == ".zip" { - mod_file_r := bytes.NewReader(mod_file_b) - - single_mod_reader, err := zip.NewReader(mod_file_r, int64(len(mod_file_b))) - if err != nil { - log.Printf("Error on reading byte_array to zip_reader: %s", err) - return err - } - - var mod_info ModInfo - err = mod_info.getModInfo(single_mod_reader) - if err != nil { - log.Printf("Error in getModInfo with the zip-byte-array: %s", err) - return err - } - - mod_info_list.Mods = append(mod_info_list.Mods, mod_info) - } else if mod_file.Name == "mod-list.json" { - err := json.Unmarshal(mod_file_b, &pack_list) - if err != nil { - log.Printf("Error on Unmashal the mod-info.json: %s", err) - return err - } - } - } - - for _, json_mod := range pack_list.Mods { - for result_index, result_mod := range mod_info_list.Mods { - if result_mod.Name == json_mod.Name { - mod_info_list.Mods[result_index].Enabled = json_mod.Enabled - break - } - } - } - - mod_pack.Mods = mod_info_list - - return nil -} - -type ModPackList struct { - ModPacks []ModPack `json:"mod_packs"` -} -func (mod_pack_list *ModPackList) getModPacks() error { - var err error - err = filepath.Walk(config.FactorioModPackDir, func(path string, info os.FileInfo, err error) error { - if !info.IsDir() && filepath.Ext(path) == ".zip" { - //var modpack ModPack - zip_file, err := zip.OpenReader(path) - if err != nil { - log.Printf("error on opening zip-file %s: %s", path, err) - return err - } - defer zip_file.Close() - - var mod_pack ModPack - err = mod_pack.readModPack(zip_file.Reader) - if err != nil { - log.Printf("Error in readModPack: %s", err) - return err - } - - var extension = filepath.Ext(info.Name()) - mod_pack.Name = info.Name()[0:len(info.Name())-len(extension)] - - mod_pack_list.ModPacks = append(mod_pack_list.ModPacks, mod_pack) - } - return nil - }) - - if err != nil { - log.Printf("error while walking over path: %s", err) - return err - } - - return nil -} - -func createModPack(pack_name string) (ModPackList, error) { - var err error - var mod_pack_list ModPackList - - pack_name_file := config.FactorioModPackDir + "/" + pack_name + ".zip" - - if _, err := os.Stat(pack_name_file); !os.IsNotExist(err) || pack_name == "" { - log.Printf("ModPack %s already exists", pack_name) - return mod_pack_list, errors.New("ModPack " + pack_name + " already exists, pls choose a different name") - } - - file, err := os.Create(pack_name_file) - if err != nil { - log.Printf("error while creating mod-pack file: %s", err) - return mod_pack_list, err - } - - zip_file := zip.NewWriter(file) - defer zip_file.Close() - - err = filepath.Walk(config.FactorioModsDir, func(path string, info os.FileInfo, err error) error { - if !info.IsDir() && (filepath.Ext(path) == ".zip" || info.Name() == "mod-list.json") { - file_writer, err := zip_file.Create(info.Name()) - if err != nil { - log.Printf("Error on creating file inside the zip: %s", err) - return err - } - - current_file, err := os.Open(path) - if err != nil { - log.Printf("Error on opening file %s: %s", path, err) - return err - } - defer current_file.Close() - - _, err = io.Copy(file_writer, current_file) - if err != nil { - log.Printf("Error while copying file %s into the zip: %s", path, err) - return err - } - } - - return nil - }) - - if err != nil { - log.Printf("Error in Walking over the folder; %s", err) - return mod_pack_list, err - } - - zip_file.Close() - - err = mod_pack_list.getModPacks() - if err != nil { - return mod_pack_list, err - } - - return mod_pack_list, nil -} - -func deleteModPack(mod_name string) (ModPackList, error) { - var err error - var mod_pack_list ModPackList - - err = os.Remove(config.FactorioModPackDir + "/" + mod_name + ".zip") - if err != nil { - log.Printf("Error when deleting modPack: %s", err) - return mod_pack_list, err - } - - err = mod_pack_list.getModPacks() - if err != nil { - log.Printf("error when listing modPacks: %s", err) - return mod_pack_list, err - } - - return mod_pack_list, nil -} - -func loadModPack(name string) ([]ModInfo, error) { - var err error - - zip_rc, err := zip.OpenReader(config.FactorioModPackDir + "/" + name + ".zip") - if err != nil { - log.Printf("Error opening ModPack zip: %s", err) - return nil, err - } - defer zip_rc.Close() - - //delete current mods - factorio_mods_dir, err := os.Open(config.FactorioModsDir) - if err != nil { - log.Printf("Error opening factorioModsDir: %s", err) - return nil, err - } - defer factorio_mods_dir.Close() - - folder_names, err := factorio_mods_dir.Readdirnames(-1) - if err != nil { - log.Printf("Error on reading dirnames: %s", err) - return nil, err - } - - for _, name := range folder_names { - err = os.RemoveAll(filepath.Join(config.FactorioModsDir, name)) - if err != nil { - log.Printf("Removing everything in the dir failed: %s", err) - return nil, err - } - } - - //unpack zip to mods-directory - for _, single_file := range zip_rc.File { - new_file, err := os.Create(config.FactorioModsDir + "/" + single_file.Name) - if err != nil { - log.Printf("error when creating new file in mod-dir: %s", err) - return nil, err - } - - singe_file_rc, err := single_file.Open() - if err != nil { - log.Printf("error when opening file inside zip: %s", err) - return nil, err - } - - _, err = io.Copy(new_file, singe_file_rc) - - new_file.Close() - singe_file_rc.Close() - if err != nil { - log.Printf("error when copying into the new file: %s", err) - return nil, err - } - } - - //read the new mod configuration - mod_info_list, err := listInstalledModsByFolder() - if err != nil { - log.Printf("error when listing mods after extracting a ModPack: %s", err) - return nil, err - } - - return mod_info_list.Mods, nil -} diff --git a/src/mods_old.go b/src/mods_old.go deleted file mode 100644 index 369f67c..0000000 --- a/src/mods_old.go +++ /dev/null @@ -1,244 +0,0 @@ -package main - -//import ( -// "archive/zip" -// "encoding/json" -// "errors" -// "fmt" -// "io/ioutil" -// "log" -// "os" -// "path/filepath" -// "strings" -//) -// -//type ModList struct { -// Mods []Mod `json:"mods"` -//} -// -// -//// List mods installed in the factorio/mods directory -//func listInstalledMods(modDir string) ([]string, error) { -// result := []string{} -// -// files, err := ioutil.ReadDir(modDir) -// if err != nil { -// log.Printf("Error listing installed mods: %s", err) -// return result, err -// } -// for _, f := range files { -// if f.Name() == "mod-list.json" { -// continue -// } -// result = append(result, f.Name()) -// } -// -// return result, nil -//} -// -//// Delete mod by provided filename -//func rmMod(modName string) error { -// removed := false -// if modName == "" { -// return errors.New("No mod name provided.") -// } -// // Get list of installed mods -// installedMods, err := listInstalledMods(config.FactorioModsDir) -// if err != nil { -// log.Printf("Error in remove mod list: %s", err) -// return err -// } -// -// // Check if provided mod matches one thats installed else return err -// for _, mod := range installedMods { -// if strings.Contains(mod, modName) { -// log.Printf("Removing mod: %s", mod) -// err := os.Remove(filepath.Join(config.FactorioModsDir, mod)) -// if err != nil { -// log.Printf("Error removing mod %s: %s", mod, err) -// return err -// } -// removed = true -// log.Printf("Removed mod: %s", mod) -// } -// } -// -// if !removed { -// log.Printf("Did not remove mod: %s", modName) -// return errors.New(fmt.Sprintf("Did not remove mod: %s", modName)) -// } -// -// return nil -//} -// -//func rmModPack(modpack string) error { -// removed := false -// if modpack == "" { -// return errors.New("No mod pack name provided.") -// } -// // Get list of modpacks -// modpacks, err := listModPacks(filepath.Join(config.FactorioDir, "modpacks")) -// if err != nil { -// log.Printf("Error listing modpacks in rmModPack: %s", err) -// return err -// } -// -// for _, m := range modpacks { -// if strings.Contains(m, modpack) { -// log.Printf("Removing modpack: %s", m) -// err := os.Remove(filepath.Join(config.FactorioDir, "modpacks", m)) -// if err != nil { -// log.Printf("Error trying to remove modpack: %s: %s", m, err) -// return err -// } -// removed = true -// log.Printf("Removed modpack: %s", m) -// } -// } -// -// if !removed { -// log.Printf("Did not remove modpack: %s", modpack) -// return errors.New(fmt.Sprintf("Did not remove modpack: %s", modpack)) -// } -// -// return nil -//} -// -//func createModPackDir() error { -// err := os.Mkdir(filepath.Join(config.FactorioDir, "modpacks"), 0775) -// if err != nil && !os.IsExist(err) { -// log.Printf("Could not create modpacks directory: %s", err) -// return err -// } -// -// return nil -//} -// -//// Create's modpack zip file from provided title, mods parameter is a string of mod filenames -//func createModPack(title string, mods ...string) error { -// zipfile, err := os.Create(filepath.Join(config.FactorioDir, "modpacks", title+".zip")) -// if err != nil { -// log.Printf("Error creating zipfile: %s, error: %s", title, err) -// } -// defer zipfile.Close() -// // Create Zip writer -// z := zip.NewWriter(zipfile) -// defer z.Close() -// -// for _, mod := range mods { -// // Process mod file, add to zipfile -// f, err := os.Open(filepath.Join(config.FactorioDir, "mods", mod)) -// if err != nil { -// log.Printf("Error creating modpack file %s for archival: ", mod, err) -// return err -// } -// // Read contents of mod to be compressed -// modfile, err := ioutil.ReadAll(f) -// if err != nil { -// log.Printf("Error reading modfile contents: %s", err) -// continue -// } -// // Add file to zip archive -// fmt.Println(mod) -// zip, err := z.Create(mod) -// if err != nil { -// log.Printf("Error adding file: %s to zip: %s", f.Name, err) -// continue -// } -// // Write file contents to zip archive -// _, err = zip.Write(modfile) -// if err != nil { -// log.Printf("Error writing to zipfile: %s", err) -// continue -// } -// } -// -// err = z.Close() -// if err != nil { -// log.Printf("Error trying to zip: %s, error: %s", title, err) -// } -// -// return nil -//} -// -//func listModPacks(modDir string) ([]string, error) { -// result := []string{} -// -// files, err := ioutil.ReadDir(modDir) -// if err != nil { -// log.Printf("Error listing modpacks: %s", err) -// return result, err -// } -// for _, f := range files { -// result = append(result, f.Name()) -// } -// -// return result, nil -//} -// -//// Parses mod-list.json file in factorio/mods -//// returns ModList struct -//func parseModList() (ModList, error) { -// var mods ModList -// modListFile := filepath.Join(config.FactorioModsDir, "mod-list.json") -// -// modList, err := ioutil.ReadFile(modListFile) -// if err != nil { -// log.Printf("Error reading mod-list.json file: %s", err) -// return mods, err -// } -// -// err = json.Unmarshal(modList, &mods) -// if err != nil { -// log.Printf("Error parsing mod-list.json JSON: %s", err) -// return mods, err -// } -// -// return mods, nil -//} -// -//// Toggles Enabled boolean for mod specified in name parameter in mod-list.json file -//func (m *ModList) toggleMod(name string) error { -// found := false -// status := false -// -// for i := range m.Mods { -// if m.Mods[i].Name == name { -// found = true -// if m.Mods[i].Enabled == true { -// m.Mods[i].Enabled = false -// } else { -// m.Mods[i].Enabled = true -// status = true -// } -// } -// } -// -// if found { -// err := m.save() -// if err != nil { -// log.Printf("Error saving changes to mod-list-.json file: %s", err) -// return err -// } -// log.Printf("Mod: %s was toggled to %v", name, status) -// } -// -// return nil -//} -// -//// Saves ModList object to mod-list.json file -//// Overwrites old file -//func (m ModList) save() error { -// modListFile := filepath.Join(config.FactorioModsDir, "mod-list.json") -// b, _ := json.MarshalIndent(m, "", " ") -// -// err := ioutil.WriteFile(modListFile, b, 0644) -// if err != nil { -// log.Printf("Error writing to mod-list.json file: %s", err) -// return err -// } -// -// return nil -//} -// -////TODO Add method to allow downloading all installed mods in zip file diff --git a/src/routes.go b/src/routes.go index ce9be05..a512c9e 100644 --- a/src/routes.go +++ b/src/routes.go @@ -304,6 +304,11 @@ var apiRoutes = Routes{ "/mods/packs/load", LoadModPackHandler, }, { + "ModPackToggleMod", + "POST", + "/mods/packs/mod/toggle", + ModPackToggleModHandler, + } ,{ "GetServerSettings", "GET", "/settings", diff --git a/ui/App/components/Mods/packs/ModPackOverview.jsx b/ui/App/components/Mods/packs/ModPackOverview.jsx index 5eddd16..51e4993 100644 --- a/ui/App/components/Mods/packs/ModPackOverview.jsx +++ b/ui/App/components/Mods/packs/ModPackOverview.jsx @@ -10,6 +10,7 @@ class ModPackOverview extends React.Component { this.createModPack = this.createModPack.bind(this); this.deleteModPack = this.deleteModPack.bind(this); this.loadModPack = this.loadModPack.bind(this); + this.modPackToggleModHandler = this.modPackToggleModHandler.bind(this); this.state = { listPacks: [] @@ -27,7 +28,6 @@ class ModPackOverview extends React.Component { method: "GET", dataType: "JSON", success: (data) => { - console.log(data); this.setState({ listPacks: data.data.mod_packs }); @@ -159,7 +159,7 @@ class ModPackOverview extends React.Component { }); this_class.props.modContentClass.setState({ - installedMods: data.data + installedMods: data.data.mods }); }, error: (jqXHR, status, err) => { @@ -182,6 +182,37 @@ class ModPackOverview extends React.Component { e.stopPropagation(); } + modPackToggleModHandler(e) { + e.preventDefault(); + let $button = $(e.target); + let $row = $button.parents("tr"); + let mod_name = $row.data("mod-name"); + let mod_pack = $row.parents(".single-modpack").find("h3").html(); + + $.ajax({ + url: "/api/mods/packs/mod/toggle", + method: "POST", + data: { + mod_name: mod_name, + mod_pack: mod_pack + }, + dataType: "JSON", + success: (data) => { + this.setState({ + listPacks: data.data.mod_packs + }); + }, + error: (jqXHR, status, err) => { + console.log('api/mods/packs/mod/toggle', status, err.toString()); + swal({ + title: "Toggle Mod went wrong", + text: err.toString(), + type: "error" + }); + } + }); + } + test() { console.log("test called"); } @@ -194,7 +225,7 @@ class ModPackOverview extends React.Component { this.state.listPacks.map( (modpack, index) => { return( -
+

{modpack.name}

@@ -216,7 +247,7 @@ class ModPackOverview extends React.Component {
diff --git a/ui/App/components/ModsContent.jsx b/ui/App/components/ModsContent.jsx index 6c1dd45..8c7db8a 100644 --- a/ui/App/components/ModsContent.jsx +++ b/ui/App/components/ModsContent.jsx @@ -320,7 +320,7 @@ class ModsContent extends React.Component { toggleUpdateStatus(); removeVersionAvailableStatus(); this_class.setState({ - installedMods: data.data + installedMods: data.data.mods }); }, error: (jqXHR, status, err) => {