Decouple extractors from manager logic
This commit is contained in:
parent
21b999e6eb
commit
3b92ee1421
102
main.go
102
main.go
|
@ -1,9 +1,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
|
@ -28,24 +31,39 @@ var commands = []Command{
|
||||||
return "", fmt.Errorf("expected game name")
|
return "", fmt.Errorf("expected game name")
|
||||||
}
|
}
|
||||||
|
|
||||||
var modsToInstall = arguments[1:]
|
var archivePaths = arguments[1:]
|
||||||
var installedMods = []string{}
|
var processed = 0
|
||||||
|
|
||||||
if gameError := WithGame(arguments[0], func(game *Game) error {
|
if gameError := WithGame(arguments[0], func(game *Game) error {
|
||||||
var installed, installError = game.InstallMods(modsToInstall)
|
for i := range archivePaths {
|
||||||
|
var archivePath = archivePaths[i]
|
||||||
|
var extension = filepath.Ext(archivePath)
|
||||||
|
|
||||||
if installError != nil {
|
if len(extension) == 0 {
|
||||||
return installError
|
continue
|
||||||
|
} else {
|
||||||
|
extension = extension[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
var extractor, extractorExists = extractors[extension]
|
||||||
|
|
||||||
|
if !(extractorExists) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if game.InstallMod(extractor, archivePath) != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
processed += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
installedMods = installed
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}); gameError != nil {
|
}); gameError != nil {
|
||||||
return "", gameError
|
return "", gameError
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprint(len(installedMods), " of ", len(modsToInstall), " installed"), nil
|
return fmt.Sprint(processed, " of ", len(archivePaths), " installed"), nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -161,6 +179,74 @@ var commands = []Command{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var extractors = map[string]Extractor{
|
||||||
|
"zip": func(archivePath string, destinationPath string) error {
|
||||||
|
var zipReader, openReaderError = zip.OpenReader(archivePath)
|
||||||
|
|
||||||
|
if openReaderError != nil {
|
||||||
|
return openReaderError
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if closeError := zipReader.Close(); closeError != nil {
|
||||||
|
panic(closeError.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if mkdirError := os.MkdirAll(destinationPath, 0755); mkdirError != nil {
|
||||||
|
return mkdirError
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range zipReader.File {
|
||||||
|
var file = zipReader.File[i]
|
||||||
|
var fileReader, fileOpenError = file.Open()
|
||||||
|
|
||||||
|
if fileOpenError != nil {
|
||||||
|
return fileOpenError
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if closeError := fileReader.Close(); closeError != nil {
|
||||||
|
panic(closeError.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var path = filepath.Join(destinationPath, file.Name)
|
||||||
|
|
||||||
|
if file.FileInfo().IsDir() {
|
||||||
|
if mkdirError := os.MkdirAll(path, file.Mode()); mkdirError != nil {
|
||||||
|
return mkdirError
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if mkdirError := os.MkdirAll(filepath.Dir(path), file.Mode()); mkdirError != nil {
|
||||||
|
return mkdirError
|
||||||
|
}
|
||||||
|
|
||||||
|
var extractedFile, fileOpenError = os.OpenFile(path,
|
||||||
|
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
|
||||||
|
|
||||||
|
if fileOpenError != nil {
|
||||||
|
return fileOpenError
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if fileOpenError := extractedFile.Close(); fileOpenError != nil {
|
||||||
|
panic(fileOpenError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var _, copyError = io.Copy(extractedFile, fileReader)
|
||||||
|
|
||||||
|
if copyError != nil {
|
||||||
|
return copyError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var formatters = map[string]func(any) ([]byte, error){
|
var formatters = map[string]func(any) ([]byte, error){
|
||||||
"json": func(data any) ([]byte, error) {
|
"json": func(data any) ([]byte, error) {
|
||||||
var marshalledJson, marshalError = json.Marshal(data)
|
var marshalledJson, marshalError = json.Marshal(data)
|
||||||
|
|
130
manager.go
130
manager.go
|
@ -1,10 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -14,53 +12,37 @@ type App struct {
|
||||||
ConfigDirPath string
|
ConfigDirPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Extractor func(string, string) error
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
ID string
|
ID string
|
||||||
Mods map[string]Mod
|
Mods map[string]Mod
|
||||||
HasUpdated bool
|
HasUpdated bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (game *Game) InstallMods(archivePaths []string) ([]string, error) {
|
func (game *Game) InstallMod(extractor Extractor, archivePath string) error {
|
||||||
var processed = 0
|
var gamePath, pathError = game.Path()
|
||||||
|
|
||||||
for i := range archivePaths {
|
if pathError != nil {
|
||||||
var archivePath = archivePaths[i]
|
return pathError
|
||||||
var suffixIndex = strings.LastIndex(archivePath, ".")
|
|
||||||
|
|
||||||
if suffixIndex < 0 {
|
|
||||||
return nil, fmt.Errorf("cannot determine file type of `%s`", archivePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
var extension = archivePath[suffixIndex+1:]
|
|
||||||
var extractor = extractors[extension]
|
|
||||||
|
|
||||||
if extractor == nil {
|
|
||||||
return nil, fmt.Errorf("unsupported file type `%s`", extension)
|
|
||||||
}
|
|
||||||
|
|
||||||
var gamePath, pathError = game.Path()
|
|
||||||
|
|
||||||
if pathError != nil {
|
|
||||||
return nil, pathError
|
|
||||||
}
|
|
||||||
|
|
||||||
var modName = filepath.Base(archivePath[:suffixIndex])
|
|
||||||
|
|
||||||
if extractError := extractor(archivePath, filepath.Join(
|
|
||||||
gamePath, "mods", modName)); extractError != nil {
|
|
||||||
|
|
||||||
return nil, extractError
|
|
||||||
}
|
|
||||||
|
|
||||||
game.Mods[modName] = Mod{
|
|
||||||
IsEnabled: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
game.HasUpdated = true
|
|
||||||
processed += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return archivePaths[0:processed], nil
|
var baseName = filepath.Base(archivePath)
|
||||||
|
var modName = strings.TrimSuffix(baseName, filepath.Ext(baseName))
|
||||||
|
|
||||||
|
if extractError := extractor(archivePath, filepath.Join(
|
||||||
|
gamePath, "mods", modName)); extractError != nil {
|
||||||
|
|
||||||
|
return extractError
|
||||||
|
}
|
||||||
|
|
||||||
|
game.Mods[modName] = Mod{
|
||||||
|
IsEnabled: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
game.HasUpdated = true
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mod struct {
|
type Mod struct {
|
||||||
|
@ -220,71 +202,3 @@ func (game *Game) RenameMod(modName string, newName string) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var extractors = map[string]func(string, string) error{
|
|
||||||
"zip": func(archivePath string, destinationPath string) error {
|
|
||||||
var zipReader, openReaderError = zip.OpenReader(archivePath)
|
|
||||||
|
|
||||||
if openReaderError != nil {
|
|
||||||
return openReaderError
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if closeError := zipReader.Close(); closeError != nil {
|
|
||||||
panic(closeError.Error())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if mkdirError := os.MkdirAll(destinationPath, 0755); mkdirError != nil {
|
|
||||||
return mkdirError
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range zipReader.File {
|
|
||||||
var file = zipReader.File[i]
|
|
||||||
var fileReader, fileOpenError = file.Open()
|
|
||||||
|
|
||||||
if fileOpenError != nil {
|
|
||||||
return fileOpenError
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if closeError := fileReader.Close(); closeError != nil {
|
|
||||||
panic(closeError.Error())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var path = filepath.Join(destinationPath, file.Name)
|
|
||||||
|
|
||||||
if file.FileInfo().IsDir() {
|
|
||||||
if mkdirError := os.MkdirAll(path, file.Mode()); mkdirError != nil {
|
|
||||||
return mkdirError
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if mkdirError := os.MkdirAll(filepath.Dir(path), file.Mode()); mkdirError != nil {
|
|
||||||
return mkdirError
|
|
||||||
}
|
|
||||||
|
|
||||||
var extractedFile, fileOpenError = os.OpenFile(path,
|
|
||||||
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
|
|
||||||
|
|
||||||
if fileOpenError != nil {
|
|
||||||
return fileOpenError
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if fileOpenError := extractedFile.Close(); fileOpenError != nil {
|
|
||||||
panic(fileOpenError)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var _, copyError = io.Copy(extractedFile, fileReader)
|
|
||||||
|
|
||||||
if copyError != nil {
|
|
||||||
return copyError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue