Skip to content

Commit

Permalink
Merge pull request #116 from knoxfighter/feature/install-mods-from-save
Browse files Browse the repository at this point in the history
Feature/install mods from save
  • Loading branch information
mroote authored Aug 4, 2018
2 parents 7e97976 + 8bf495f commit 9addd24
Show file tree
Hide file tree
Showing 7 changed files with 771 additions and 3 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ go build

* **Mitch Roote** - [roote.ca](https://roote.ca)

## Special Thanks
- **mickael9** for reverseengineering the factorio-save-file: https://forums.factorio.com/viewtopic.php?f=5&t=8568#

## License

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
149 changes: 146 additions & 3 deletions src/mods_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,28 @@ import (
"net/http"
"os"
"path/filepath"
"factorioSave"
"time"
)

type ModPortalStruct struct {
DownloadsCount int `json:"downloads_count"`
Name string `json:"name"`
Owner string `json:"owner"`
Releases []struct {
DownloadURL string `json:"download_url"`
FileName string `json:"file_name"`
InfoJSON struct {
FactorioVersion string `json:"factorio_version"`
} `json:"info_json"`
ReleasedAt time.Time `json:"released_at"`
Sha1 string `json:"sha1"`
Version string `json:"version"`
} `json:"releases"`
Summary string `json:"summary"`
Title string `json:"title"`
}

// Returns JSON response of all mods installed in factorio/mods
func listInstalledModsHandler(w http.ResponseWriter, r *http.Request) {
var err error
Expand Down Expand Up @@ -211,7 +231,7 @@ func ModPortalInstallHandler(w http.ResponseWriter, r *http.Request) {
}

if err != nil {
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
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)
Expand All @@ -227,6 +247,90 @@ func ModPortalInstallHandler(w http.ResponseWriter, r *http.Request) {
}
}

func ModPortalInstallMultipleHandler(w http.ResponseWriter, r *http.Request) {
var err error
resp := JSONResponse{
Success: false,
}

w.Header().Set("Content-Type", "application/json;charset=UTF-8")
r.ParseForm()

modsList := make([]string, 0)
versionsList := make([]string, 0)

//Parse incoming data
for key, values := range r.PostForm {
if key == "mod_name" {
for _, v := range values {
modsList = append(modsList, v)
}
} else if key == "mod_version" {
for _, v := range values {
versionsList = append(versionsList, v)
}
}
}

mods, err := newMods(config.FactorioModsDir)
if err != nil {
log.Printf("error creating mods: %s", err)

w.WriteHeader(http.StatusInternalServerError)
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)
}
return
}

for modIndex, mod := range modsList {
var err error

//get details of mod
modDetails, err, statusCode := getModDetails(mod)
if err != nil {
w.WriteHeader(statusCode)
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)
}
return
}

modDetailsArray := []byte(modDetails)
var modDetailsStruct ModPortalStruct

//read mod-data into Struct
err = json.Unmarshal(modDetailsArray, &modDetailsStruct)
if err != nil {
log.Printf("error reading modPortalDetails: %s", err)

w.WriteHeader(http.StatusInternalServerError)
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)
}
return
}

//find correct mod-version
for _, release := range modDetailsStruct.Releases {
if release.Version == versionsList[modIndex] {
mods.downloadMod(release.DownloadURL, release.FileName, modDetailsStruct.Name)
break
}
}
}

resp.Data = mods.listInstalledMods()

resp.Success = true
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Error in ToggleModHandler: %s", err)
}
}

func ToggleModHandler(w http.ResponseWriter, r *http.Request) {
var err error
resp := JSONResponse{
Expand All @@ -244,7 +348,7 @@ func ToggleModHandler(w http.ResponseWriter, r *http.Request) {
}

if err != nil {
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
resp.Data = fmt.Sprintf("Error in listInstalledModsByFolder: %s", err)
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Error in listInstalledModsByFolder: %s", err)
Expand Down Expand Up @@ -276,7 +380,7 @@ func DeleteModHandler(w http.ResponseWriter, r *http.Request) {
}

if err != nil {
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
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)
Expand Down Expand Up @@ -455,6 +559,45 @@ func DownloadModsHandler(w http.ResponseWriter, r *http.Request) {
writerHeader.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", "all_installed_mods.zip"))
}

//Returns JSON response with the found mods
func LoadModsFromSaveHandler(w http.ResponseWriter, r *http.Request) {
var err error
resp := JSONResponse{
Success: false,
}

w.Header().Set("Content-Type", "application/json;charset=UTF-8")

//Get Data out of the request
SaveFile := r.FormValue("saveFile")

SaveFileComplete := filepath.Join(config.FactorioSavesDir, SaveFile)
resp.Data, err = factorioSave.ReadHeader(SaveFileComplete)

if err == factorioSave.ErrorIncompatible {
w.WriteHeader(http.StatusInternalServerError)
resp.Data = fmt.Sprintf("%s<br>Only can read 0.16.x save files", err)
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Error in loadModsFromSave: %s", err)
}
return
}
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err)
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Error in loadModsFromSave: %s", err)
}
return
}

resp.Success = true

if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Error in LoadModsFromSave: %s", err)
}
}

func ListModPacksHandler(w http.ResponseWriter, r *http.Request) {
var err error
resp := JSONResponse{
Expand Down
10 changes: 10 additions & 0 deletions src/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ var apiRoutes = Routes{
"POST",
"/mods/install",
ModPortalInstallHandler,
}, {
"ModPortalInstallMultiple",
"POST",
"/mods/install/multiple",
ModPortalInstallMultipleHandler,
}, {
"ToggleMod",
"POST",
Expand Down Expand Up @@ -213,6 +218,11 @@ var apiRoutes = Routes{
"GET",
"/mods/download",
DownloadModsHandler,
}, {
"LoadModsFromSave",
"POST",
"/mods/save/load",
LoadModsFromSaveHandler,
}, {
"ListSaves",
"GET",
Expand Down
Loading

0 comments on commit 9addd24

Please sign in to comment.