Decouple extractors from manager logic

This commit is contained in:
kayomn 2022-12-03 18:27:53 +00:00
parent 21b999e6eb
commit 3b92ee1421
2 changed files with 116 additions and 116 deletions

102
main.go
View File

@ -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)

View File

@ -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
},
}