Skip to content

Commit ff399d7

Browse files
committed
Feat: FTB Server Pack Installation.
1 parent 4cb0530 commit ff399d7

1 file changed

Lines changed: 119 additions & 2 deletions

File tree

RemotelyAgent/main.go

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
"gopkg.in/yaml.v3"
2323
)
2424

25-
const agentVersion = "1.1.0"
25+
const agentVersion = "1.2.0"
2626

2727
type RemoteIndex struct {
2828
GeneratedAt int64 `json:"generatedAt"`
@@ -429,6 +429,7 @@ func cmdCheckZipType(args []string) {
429429

430430
hasManifest := false
431431
hasServerFiles := false
432+
hasFTBInstaller := false
432433

433434
startScripts := []string{"run.sh", "install.sh", "start.sh", "run.bat", "install.bat", "start.bat"}
434435
dirsToCheck := []string{"mods/", "config/", "libraries/", "serverpack/"}
@@ -437,6 +438,9 @@ func cmdCheckZipType(args []string) {
437438
if f.Name == "manifest.json" {
438439
hasManifest = true
439440
}
441+
if zipFileContainsFTBInstallerReference(f) {
442+
hasFTBInstaller = true
443+
}
440444

441445
for _, script := range startScripts {
442446
if f.Name == script {
@@ -457,7 +461,9 @@ func cmdCheckZipType(args []string) {
457461
}
458462
}
459463

460-
if hasManifest {
464+
if hasFTBInstaller {
465+
fmt.Println("ftb-preconfigured")
466+
} else if hasManifest {
461467
fmt.Println("manifest")
462468
} else if hasServerFiles {
463469
fmt.Println("preconfigured")
@@ -636,6 +642,14 @@ func processFlattenPack(zipPath string, targetDir string, executeInstallScript b
636642
}
637643
}
638644

645+
ftbBootstrap, err := findFTBInstallerBootstrap(targetDir)
646+
if err != nil {
647+
return err
648+
}
649+
if ftbBootstrap != "" {
650+
return installFTBServerPack(ftbBootstrap, targetDir)
651+
}
652+
639653
startScripts := []string{"run.sh", "install.sh", "start.sh"}
640654
var scriptsFound []string
641655
for _, scriptName := range startScripts {
@@ -665,6 +679,109 @@ func processFlattenPack(zipPath string, targetDir string, executeInstallScript b
665679
return nil
666680
}
667681

682+
func zipFileContainsFTBInstallerReference(file *zip.File) bool {
683+
name := strings.ToLower(filepath.Base(filepath.ToSlash(file.Name)))
684+
if name != "install.sh" && name != "install.bat" {
685+
return false
686+
}
687+
rc, err := file.Open()
688+
if err != nil {
689+
return false
690+
}
691+
defer rc.Close()
692+
content, err := io.ReadAll(io.LimitReader(rc, 256*1024))
693+
if err != nil {
694+
return false
695+
}
696+
return containsFTBInstallerReference(string(content))
697+
}
698+
699+
func containsFTBInstallerReference(content string) bool {
700+
normalized := strings.ToLower(content)
701+
return strings.Contains(normalized, "ftbteam/ftb-server-installer") || strings.Contains(normalized, "ftb-server-installer_") || strings.Contains(normalized, "ftb-server-")
702+
}
703+
704+
func findFTBInstallerBootstrap(targetDir string) (string, error) {
705+
bootstrap := ""
706+
err := filepath.WalkDir(targetDir, func(path string, entry os.DirEntry, err error) error {
707+
if err != nil {
708+
return err
709+
}
710+
if entry.IsDir() {
711+
relative, relativeErr := filepath.Rel(targetDir, path)
712+
if relativeErr == nil && relative != "." && strings.Count(filepath.ToSlash(relative), "/") >= 2 {
713+
return filepath.SkipDir
714+
}
715+
return nil
716+
}
717+
if !strings.EqualFold(entry.Name(), "install.sh") {
718+
return nil
719+
}
720+
content, readErr := os.ReadFile(path)
721+
if readErr != nil {
722+
return readErr
723+
}
724+
if containsFTBInstallerReference(string(content)) {
725+
bootstrap = path
726+
return io.EOF
727+
}
728+
return nil
729+
})
730+
if err != nil && err != io.EOF {
731+
return "", err
732+
}
733+
return bootstrap, nil
734+
}
735+
736+
func installFTBServerPack(bootstrapPath string, targetDir string) error {
737+
bootstrapDir := filepath.Dir(bootstrapPath)
738+
bootstrap := exec.Command("/bin/sh", "./"+filepath.Base(bootstrapPath))
739+
bootstrap.Dir = bootstrapDir
740+
if output, err := bootstrap.CombinedOutput(); err != nil {
741+
return fmt.Errorf("FTB installer bootstrap failed: %w\n%s", err, string(output))
742+
}
743+
744+
entries, err := os.ReadDir(bootstrapDir)
745+
if err != nil {
746+
return err
747+
}
748+
installerPath := ""
749+
for _, entry := range entries {
750+
name := strings.ToLower(entry.Name())
751+
if !entry.IsDir() && strings.HasPrefix(name, "ftb-server-installer") && !strings.HasSuffix(name, ".log") {
752+
installerPath = filepath.Join(bootstrapDir, entry.Name())
753+
break
754+
}
755+
}
756+
if installerPath == "" {
757+
return fmt.Errorf("FTB server installer binary was not downloaded")
758+
}
759+
if err := os.Chmod(installerPath, 0o755); err != nil {
760+
return fmt.Errorf("make FTB server installer executable: %w", err)
761+
}
762+
763+
installer := exec.Command(installerPath, "-auto", "-force", "-no-colours", "-dir", targetDir)
764+
installer.Dir = bootstrapDir
765+
installer.Stdout = os.Stdout
766+
installer.Stderr = os.Stderr
767+
if err := installer.Run(); err != nil {
768+
return fmt.Errorf("FTB server installer failed: %w", err)
769+
}
770+
771+
startupPath := filepath.Join(targetDir, "run.sh")
772+
if info, err := os.Stat(startupPath); err != nil || info.IsDir() {
773+
return fmt.Errorf("FTB server installer completed without creating run.sh")
774+
}
775+
manifestPath := filepath.Join(targetDir, ".manifest.json")
776+
if info, err := os.Stat(manifestPath); err != nil || info.IsDir() {
777+
return fmt.Errorf("FTB server installer completed without creating .manifest.json")
778+
}
779+
if err := os.Chmod(startupPath, 0o755); err != nil {
780+
return fmt.Errorf("make FTB startup script executable: %w", err)
781+
}
782+
return nil
783+
}
784+
668785
func fetchAll(mf FetchManifest) error {
669786
sem := make(chan struct{}, mf.Concurrency)
670787
var wg sync.WaitGroup

0 commit comments

Comments
 (0)