diff --git a/cmd/root.go b/cmd/root.go index db72ec8..59fd5a3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,9 +5,9 @@ import ( "github.com/nothub/mrpack-install/modrinth/mrpack" "github.com/nothub/mrpack-install/requester" "github.com/nothub/mrpack-install/server" + "github.com/nothub/mrpack-install/util" "github.com/spf13/cobra" "log" - "net/url" "os" "path" "path/filepath" @@ -75,10 +75,10 @@ var rootCmd = &cobra.Command{ } archivePath := "" - if isFilePath(input) { + if util.FileExists(input) { archivePath = input - } else if isUrl(input) { + } else if util.IsValidUrl(input) { log.Println("Downloading mrpack file from", args) file, err := requester.DefaultHttpClient.DownloadFile(input, serverDir, "") if err != nil { @@ -138,31 +138,25 @@ var rootCmd = &cobra.Command{ log.Fatalln(err) } log.Println("Installing:", index.Name) - - log.Printf("Loader dependencies: %+v\n", index.Dependencies) + log.Printf("Flavor dependencies: %+v\n", index.Dependencies) // download server if not present - if serverFile != "" && !isFilePath(path.Join(serverDir, serverFile)) { + if serverFile != "" && !util.FileExists(path.Join(serverDir, serverFile)) { // Determine server platform - var supplier server.DownloadSupplier = nil + var provider server.Provider = nil if index.Dependencies.Fabric != "" { - supplier = &server.Fabric{ + provider = &server.Fabric{ MinecraftVersion: index.Dependencies.Minecraft, FabricVersion: index.Dependencies.Fabric, } } else if index.Dependencies.Quilt != "" || index.Dependencies.Forge != "" { - log.Fatalln("Automatic server deployment not yet implemented for this platform! Supply the path to an existing server jar file with the --server-dir and --server-file flags.") + log.Fatalln("Automatic server deployment not yet implemented for this flavor! Supply the path to an existing server jar file with the --server-dir and --server-file flags.") } else { // TODO: vanilla server download } // Download server - u, err := supplier.GetUrl() - if err != nil { - log.Fatalln(err) - } - log.Println("Downloading server file from", u) - _, err = requester.DefaultHttpClient.DownloadFile(u, serverDir, serverFile) + err := provider.Provide(serverDir, serverFile) if err != nil { log.Fatalln(err) } @@ -204,22 +198,6 @@ var rootCmd = &cobra.Command{ }, } -func isFilePath(s string) bool { - _, err := os.Stat(s) - return err == nil -} - -func isUrl(s string) bool { - u, err := url.Parse(s) - if err != nil { - return false - } - if u.Scheme == "" { - return false - } - return true -} - func Execute() { if rootCmd.Execute() != nil { os.Exit(1) diff --git a/cmd/server.go b/cmd/server.go index a488845..6622c34 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -1,24 +1,21 @@ package cmd import ( - "fmt" "github.com/nothub/mrpack-install/mojang" - "github.com/nothub/mrpack-install/requester" "github.com/nothub/mrpack-install/server" "github.com/spf13/cobra" "log" - "os" ) func init() { serverCmd.Flags().String("minecraft-version", "latest", "Minecraft version") - serverCmd.Flags().String("loader-version", "latest", "Mod loader version") + serverCmd.Flags().String("flavor-version", "latest", "Flavor build version") serverCmd.Flags().String("server-dir", "mc", "Server directory path") serverCmd.Flags().String("server-file", "", "Server jar file name") /* TODO: eula flag TODO: ops flag - TODO: whitelist flag + TODO: whitelist flags */ rootCmd.AddCommand(serverCmd) } @@ -34,7 +31,7 @@ var serverCmd = &cobra.Command{ if err != nil { log.Fatalln(err) } - loaderVersion, err := cmd.Flags().GetString("loader-version") + flavorVersion, err := cmd.Flags().GetString("flavor-version") if err != nil { log.Fatalln(err) } @@ -55,50 +52,42 @@ var serverCmd = &cobra.Command{ minecraftVersion = latestMinecraftVersion } - var supplier server.DownloadSupplier = nil + var provider server.Provider = nil switch args[0] { case "vanilla": - log.Fatalln("Not yet implemented!") + provider = &server.Vanilla{ + MinecraftVersion: minecraftVersion, + } case "fabric": - supplier = &server.Fabric{ + provider = &server.Fabric{ MinecraftVersion: minecraftVersion, - FabricVersion: loaderVersion, + FabricVersion: flavorVersion, } - case "forge": - log.Fatalln("Not yet implemented!") case "quilt": - err = os.MkdirAll("work/quilt", 0755) - if err != nil { - log.Fatalln(err) + provider = &server.Quilt{ + MinecraftVersion: minecraftVersion, + QuiltVersion: flavorVersion, + } + case "forge": + provider = &server.Forge{ + MinecraftVersion: minecraftVersion, + ForgeVersion: flavorVersion, } - // download https://maven.quiltmc.org/repository/release/org/quiltmc/quilt-installer/latest/quilt-installer-latest.jar - // java -jar quilt-installer-latest.jar install server ${minecraftVersion} --download-server - log.Fatalln("Not yet implemented!") case "paper": - supplier = &server.Paper{ + provider = &server.Paper{ MinecraftVersion: minecraftVersion, - PaperVersion: loaderVersion, + PaperVersion: flavorVersion, } case "spigot": - err = os.MkdirAll("work/spigot", 0755) - if err != nil { - log.Fatalln(err) + provider = &server.Spigot{ + MinecraftVersion: minecraftVersion, + SpigotVersion: flavorVersion, } - // download https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar - // git config --global --unset core.autocrlf - // java -jar BuildTools.jar --rev ${minecraftVersion} - log.Fatalln("Not yet implemented!") } - url, err := supplier.GetUrl() + err = provider.Provide(serverDir, serverFile) if err != nil { log.Fatalln(err) } - - file, err := requester.DefaultHttpClient.DownloadFile(url, serverDir, serverFile) - if err != nil { - return - } - fmt.Println("Server jar downloaded to:", file) }, } diff --git a/server/fabric.go b/server/fabric.go index cf19114..d8cbf89 100644 --- a/server/fabric.go +++ b/server/fabric.go @@ -2,6 +2,7 @@ package server import ( "errors" + "fmt" "github.com/nothub/mrpack-install/requester" "net/url" ) @@ -11,28 +12,34 @@ type Fabric struct { FabricVersion string } -func (supplier *Fabric) GetUrl() (string, error) { +func (supplier *Fabric) Provide(serverDir string, serverFile string) error { loaderVersion := supplier.FabricVersion if loaderVersion == "" || loaderVersion == "latest" { latestLoaderVersion, err := latestFabricLoaderVersion(supplier.MinecraftVersion) if err != nil { - return "", err + return err } loaderVersion = latestLoaderVersion } installerVersion, err := latestFabricInstallerVersion() if err != nil { - return "", err + return err } versionTriple := supplier.MinecraftVersion + "/" + loaderVersion + "/" + installerVersion u, err := url.Parse("https://meta.fabricmc.net/v2/versions/loader/" + versionTriple + "/server/jar") if err != nil { - return "", err + return err + } + + file, err := requester.DefaultHttpClient.DownloadFile(u.String(), serverDir, serverFile) + if err != nil { + return err } - return u.String(), nil + fmt.Println("Server jar downloaded to:", file) + return nil } func latestFabricLoaderVersion(mcVer string) (string, error) { diff --git a/server/fabric_test.go b/server/fabric_test.go deleted file mode 100644 index 50998f1..0000000 --- a/server/fabric_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package server - -import ( - "regexp" - "testing" -) - -const fabricUrlPattern string = "https://meta\\.fabricmc\\.net/v2/versions/loader/\\d+\\.\\d+\\.\\d+/\\d+\\.\\d+\\.\\d+/\\d+\\.\\d+\\.\\d+/server/jar" - -func Test_Fabric_latest(t *testing.T) { - t.Parallel() - - var supplier DownloadSupplier - supplier = &Fabric{ - MinecraftVersion: "1.18.2", - FabricVersion: "latest", - } - url, err := supplier.GetUrl() - if err != nil { - t.Fatal(err) - } - if !regexp.MustCompile(fabricUrlPattern).MatchString(url) { - t.Fatal("wrong url!") - } -} - -func Test_Fabric_specific(t *testing.T) { - t.Parallel() - var supplier DownloadSupplier - supplier = &Fabric{ - MinecraftVersion: "1.19.2", - FabricVersion: "0.14.9", - } - url, err := supplier.GetUrl() - if err != nil { - t.Fatal(err) - } - if !regexp.MustCompile(fabricUrlPattern).MatchString(url) { - t.Fatal("wrong url!") - } -} - -func Test_Fabric_Empty_Version(t *testing.T) { - t.Parallel() - var supplier DownloadSupplier - supplier = &Fabric{ - MinecraftVersion: "1.16.5", - } - url, err := supplier.GetUrl() - if err != nil { - t.Fatal(err) - } - if !regexp.MustCompile(fabricUrlPattern).MatchString(url) { - t.Fatal("wrong url!") - } -} diff --git a/server/forge.go b/server/forge.go new file mode 100644 index 0000000..975a8d4 --- /dev/null +++ b/server/forge.go @@ -0,0 +1,12 @@ +package server + +import "errors" + +type Forge struct { + MinecraftVersion string + ForgeVersion string +} + +func (supplier *Forge) Provide(serverDir string, serverFile string) error { + return errors.New("forge provider not yet implemented") +} diff --git a/server/interface.go b/server/interface.go index 00ccfb7..64d14be 100644 --- a/server/interface.go +++ b/server/interface.go @@ -1,5 +1,5 @@ package server -type DownloadSupplier interface { - GetUrl() (string, error) +type Provider interface { + Provide(serverDir string, serverFile string) error } diff --git a/server/paper.go b/server/paper.go index dcb23b2..5b097ab 100644 --- a/server/paper.go +++ b/server/paper.go @@ -2,6 +2,7 @@ package server import ( "errors" + "fmt" "github.com/nothub/mrpack-install/requester" "strconv" ) @@ -11,7 +12,7 @@ type Paper struct { PaperVersion string } -func (supplier *Paper) GetUrl() (string, error) { +func (supplier *Paper) Provide(serverDir string, serverFile string) error { var response struct { Builds []struct { Id int `json:"build"` @@ -26,13 +27,21 @@ func (supplier *Paper) GetUrl() (string, error) { } err := requester.DefaultHttpClient.GetJson("https://api.papermc.io/v2/projects/paper/versions/"+supplier.MinecraftVersion+"/builds", &response, nil) if err != nil { - return "", err + return err } for i := range response.Builds { i = len(response.Builds) - 1 - i - if response.Builds[i].Channel == "default" { - return "https://api.papermc.io/v2/projects/paper/versions/" + supplier.MinecraftVersion + "/builds/" + strconv.Itoa(response.Builds[i].Id) + "/downloads/" + response.Builds[i].Downloads.Application.Name, nil + b := response.Builds[i] + if b.Channel == "default" { + u := "https://api.papermc.io/v2/projects/paper/versions/" + supplier.MinecraftVersion + "/builds/" + strconv.Itoa(b.Id) + "/downloads/" + b.Downloads.Application.Name + file, err := requester.DefaultHttpClient.DownloadFile(u, serverDir, serverFile) + if err != nil { + return err + } + + fmt.Println("Server jar downloaded to:", file) + return nil } } - return "", errors.New("no stable paper release found") + return errors.New("no stable paper release found") } diff --git a/server/paper_test.go b/server/paper_test.go deleted file mode 100644 index d3717b8..0000000 --- a/server/paper_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package server - -import ( - "regexp" - "testing" -) - -const paperUrlPattern string = "https://api\\.papermc\\.io/v2/projects/paper/versions/\\d+\\.\\d+\\.\\d+/builds/\\d+/downloads/paper-\\d+\\.\\d+\\.\\d+-\\d+\\.jar" - -func Test_Paper_latest(t *testing.T) { - t.Parallel() - - var supplier DownloadSupplier - supplier = &Paper{ - MinecraftVersion: "1.18.2", - PaperVersion: "latest", - } - url, err := supplier.GetUrl() - if err != nil { - t.Fatal(err) - } - if !regexp.MustCompile(paperUrlPattern).MatchString(url) { - t.Fatal("wrong url!") - } -} - -func Test_Paper_specific(t *testing.T) { - t.Parallel() - var supplier DownloadSupplier - supplier = &Paper{ - MinecraftVersion: "1.12.2", - PaperVersion: "1619", - } - url, err := supplier.GetUrl() - if err != nil { - t.Fatal(err) - } - if !regexp.MustCompile(paperUrlPattern).MatchString(url) { - t.Fatal("wrong url!") - } -} - -func Test_Paper_Empty_Version(t *testing.T) { - t.Parallel() - var supplier DownloadSupplier - supplier = &Paper{ - MinecraftVersion: "1.9001.42", - } - _, err := supplier.GetUrl() - if err.Error() != "http status 404" { - t.Fatal("wrong status!") - } -} diff --git a/server/quilt.go b/server/quilt.go new file mode 100644 index 0000000..6d555ac --- /dev/null +++ b/server/quilt.go @@ -0,0 +1,24 @@ +package server + +import ( + "errors" + "log" + "os" +) + +type Quilt struct { + MinecraftVersion string + QuiltVersion string +} + +func (supplier *Quilt) Provide(serverDir string, serverFile string) error { + err := os.MkdirAll("work/quilt", 0755) + if err != nil { + log.Fatalln(err) + } + + // TODO: download https://maven.quiltmc.org/repository/release/org/quiltmc/quilt-installer/latest/quilt-installer-latest.jar + // TODO: java -jar quilt-installer-latest.jar install server ${minecraftVersion} --download-server + + return errors.New("quilt provider not yet implemented") +} diff --git a/server/spigot.go b/server/spigot.go new file mode 100644 index 0000000..7e72749 --- /dev/null +++ b/server/spigot.go @@ -0,0 +1,25 @@ +package server + +import ( + "errors" + "log" + "os" +) + +type Spigot struct { + MinecraftVersion string + SpigotVersion string +} + +func (supplier *Spigot) Provide(serverDir string, serverFile string) error { + err := os.MkdirAll("work/spigot", 0755) + if err != nil { + log.Fatalln(err) + } + + // TODO: download https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar + // TODO: git config --global --unset core.autocrlf + // TODO: java -jar BuildTools.jar --rev ${minecraftVersion} + + return errors.New("spigot provider not yet implemented") +} diff --git a/server/vanilla.go b/server/vanilla.go new file mode 100644 index 0000000..49cef79 --- /dev/null +++ b/server/vanilla.go @@ -0,0 +1,11 @@ +package server + +import "errors" + +type Vanilla struct { + MinecraftVersion string +} + +func (supplier *Vanilla) Provide(serverDir string, serverFile string) error { + return errors.New("vanilla provider not yet implemented") +} diff --git a/util/file.go b/util/file.go new file mode 100644 index 0000000..473a8b1 --- /dev/null +++ b/util/file.go @@ -0,0 +1,8 @@ +package util + +import "os" + +func FileExists(path string) bool { + _, err := os.Stat(path) + return err == nil +} diff --git a/util/url.go b/util/url.go new file mode 100644 index 0000000..07c90d3 --- /dev/null +++ b/util/url.go @@ -0,0 +1,14 @@ +package util + +import "net/url" + +func IsValidUrl(s string) bool { + u, err := url.Parse(s) + if err != nil { + return false + } + if u.Scheme == "" { + return false + } + return true +}