commit 49003a8a80f000962d6aa86871b08f6a786e7944 Author: ALEX Date: Fri May 10 19:48:59 2024 +0000 first commit diff --git a/IAts0Hp2MbUGw/data/serverip.json b/IAts0Hp2MbUGw/data/serverip.json new file mode 100644 index 0000000..91b4ce3 --- /dev/null +++ b/IAts0Hp2MbUGw/data/serverip.json @@ -0,0 +1,5 @@ +{ + "Origin": "craserver.xfcloud.org:25565", + "America": "server4.xfcloud.org:25565", + "Common": "115.238.185.57:26000" +} \ No newline at end of file diff --git a/IAts0Hp2MbUGw/files/mods.zip b/IAts0Hp2MbUGw/files/mods.zip new file mode 100644 index 0000000..c47a8ec Binary files /dev/null and b/IAts0Hp2MbUGw/files/mods.zip differ diff --git a/IAts0Hp2MbUGw/server.json b/IAts0Hp2MbUGw/server.json new file mode 100644 index 0000000..e400043 --- /dev/null +++ b/IAts0Hp2MbUGw/server.json @@ -0,0 +1,5 @@ +{ + "mods-version": "v1.0", + "mods-version-update": "mods-url", + "mods-url": "https://xfcloud.org/mods.zip" +} \ No newline at end of file diff --git a/api/servers.json b/api/servers.json new file mode 100644 index 0000000..0a13eab --- /dev/null +++ b/api/servers.json @@ -0,0 +1,3 @@ +{ + "IAts0Hp2MbUGw": "CRA-MC Server MTR" +} \ No newline at end of file diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..2e49682 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,233 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func IsExist(f string) bool { + _, err := os.Stat(f) + return err == nil || os.IsExist(err) +} + +func apirequest_post(w http.ResponseWriter, req *http.Request) { + var serverID = req.PathValue("id") + if !IsExist("./" + serverID) { + w.WriteHeader(403) + fmt.Printf("Requesting ServerID: %s does not exist\n", serverID) + return + } + file, err := os.Open("./" + serverID + "/server.json") + if err != nil { + w.WriteHeader(403) + fmt.Printf("Requesting ServerID: %s file does not exist\n", serverID) + return + } + defer file.Close() + file_decoder := json.NewDecoder(file) + var configs map[string]string + file_decoder.Decode(&configs) + + decoder := json.NewDecoder(req.Body) + var params map[string]string + var resp string + decoder.Decode(¶ms) + for key, one := range params { + // fmt.Printf("%s key's value %s\n", key, one) + if value, ok := configs[key]; ok { + if value != one { + if addr, ok := configs[key+"-update"]; ok { + if resp != "" { + resp += "," + } + resp += "{\"" + key + "\":\"" + value + "\",\"" + addr + "\":\"" + configs[addr] + "\"}" + } else { + w.WriteHeader(500) + fmt.Printf("%s key update not found\n", key) + return + } + } else { + // fmt.Printf("%s's request %s equals %s\n", key, one, value) + } + } else { + w.WriteHeader(404) + fmt.Printf("Requesting ServerID: %s, key:%s not found\n", serverID, key) + return + } + } + w.Write([]byte(resp)) +} + +func apirequest_get(w http.ResponseWriter, req *http.Request) { + var serverID = req.PathValue("id") + if !IsExist("./" + serverID) { + w.WriteHeader(403) + fmt.Printf("Requesting ServerID: %s does not exist\n", serverID) + return + } + var fileid = req.PathValue("file") + file, err := os.ReadFile("./" + serverID + "/data/" + fileid + ".json") + fmt.Printf("requesting %s\n", "./"+serverID+"/data/"+fileid+".json") + if err != nil { + w.WriteHeader(403) + fmt.Printf("Requesting ServerID: %s file %s does not exist\n", serverID, "./"+serverID+"/data/"+fileid+".json") + return + } + w.WriteHeader(http.StatusOK) + w.Write(file) +} + +func apirequest_file(w http.ResponseWriter, req *http.Request) { + var serverID = req.PathValue("id") + if !IsExist("./" + serverID) { + w.WriteHeader(403) + fmt.Printf("Requesting ServerID: %s does not exist\n", serverID) + return + } + var fileid = req.PathValue("file") + file, err := os.ReadFile("./" + serverID + "/files/" + fileid) + fmt.Printf("requesting %s\n", "./"+serverID+"/files/"+fileid) + if err != nil { + w.WriteHeader(403) + fmt.Printf("Requesting ServerID: %s file %s does not exist\n", serverID, "./"+serverID+"/files/"+fileid) + return + } + w.WriteHeader(http.StatusOK) + w.Write(file) +} + +func apirequest_info_post(w http.ResponseWriter, req *http.Request) { + file, err := os.Open("./info.json") + if err != nil { + w.WriteHeader(403) + fmt.Println("Requesting info.json file does not exist") + return + } + defer file.Close() + file_decoder := json.NewDecoder(file) + var configs map[string]string + file_decoder.Decode(&configs) + + decoder := json.NewDecoder(req.Body) + var params map[string]string + var resp string + decoder.Decode(¶ms) + for key, one := range params { + // fmt.Printf("%s key's value %s\n", key, one) + if value, ok := configs[key]; ok { + if value != one { + if addr, ok := configs[key+"-update"]; ok { + if new_info, ok := configs[key+"-info"]; ok { + if resp != "" { + resp += "," + } + resp += "{\"" + key + "\":\"" + value + "\",\"" + addr + "\":\"" + configs[addr] + "\",\"" + key + "-info\":\"" + new_info + "\"}" + } else { + w.WriteHeader(500) + fmt.Printf("info's %s key update not found\n", key) + return + } + } else { + w.WriteHeader(500) + fmt.Printf("info's %s key update not found\n", key) + return + } + } else { + // fmt.Printf("%s's request %s equals %s\n", key, one, value) + } + } else { + w.WriteHeader(404) + fmt.Printf("Requesting info key:%s not found\n", key) + return + } + } + w.Write([]byte(resp)) +} + +var cfgFile string +var v bool +var servername string +var port string + +func apirequest_info_get(w http.ResponseWriter, req *http.Request) { + var fileid = req.PathValue("request") + file, err := os.ReadFile("./api" + fileid + ".json") + fmt.Printf("requesting %s\n", "./api"+fileid+".json") + if err != nil { + w.WriteHeader(403) + fmt.Printf("Requesting file %s does not exist\n", "./api"+fileid+".json") + return + } + w.WriteHeader(http.StatusOK) + w.Write(file) +} +func runServer() { + if v { + versionPrint() + os.Exit(0) + } + + fmt.Println("config file:" + cfgFile) + if cfgFile != "" { + viper.SetConfigFile(cfgFile) + viper.SetConfigType("yaml") + } else { + viper.SetConfigFile("./craapi.config") + viper.SetConfigType("yaml") + } + + if err := viper.ReadInConfig(); err != nil { + fmt.Println("Can't read config:", err) + os.Exit(1) + } + + http.HandleFunc("POST /api/server/{id}", apirequest_post) + http.HandleFunc("GET /api/server/{id}/{file}", apirequest_get) + http.HandleFunc("/api/file/{id}/{file}", apirequest_file) + http.HandleFunc("GET /api/info/{request}", apirequest_info_get) + http.HandleFunc("POST /api/info", apirequest_info_post) + fmt.Println("API Server is tring to run at:", viper.GetString("servername")+":"+viper.GetString("port")) + err := http.ListenAndServe(viper.GetString("servername")+":"+viper.GetString("port"), nil) + if err != nil { + fmt.Println("HTTP SERVER failed,err:", err) + return + } + fmt.Println("API server started successfully") +} + +var rootCmd = &cobra.Command{ + Use: "craapi", + Short: "CRA-MC API is a minecraft servers API", + Long: `CRA-MC API is a minecraft servers API which can manage mutiple minecraft servers' mods version or files + `, + Run: func(cmd *cobra.Command, args []string) { + runServer() + }, +} + +func init() { + cobra.OnInitialize(initConfig) + rootCmd.Flags().StringVarP(&cfgFile, "config", "c", "./craapi.config", "config file") + rootCmd.Flags().StringVarP(&servername, "servername", "s", "", "servername (domain or ip address)") + rootCmd.Flags().StringVarP(&port, "port", "p", "", "port number") + viper.BindPFlag("servername", rootCmd.Flags().Lookup("servername")) + viper.BindPFlag("port", rootCmd.Flags().Lookup("port")) + rootCmd.Flags().BoolVarP(&v, "version", "v", false, "version") + viper.SetDefault("servername", "") + viper.SetDefault("port", "19999") +} + +func initConfig() { +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/cmd/version.go b/cmd/version.go new file mode 100644 index 0000000..9327e6b --- /dev/null +++ b/cmd/version.go @@ -0,0 +1,24 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func versionPrint() { + fmt.Println("CRAAPI static version: v0.2") +} + +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print the version number of craapi", + Long: `All software has versions.`, + Run: func(cmd *cobra.Command, args []string) { + versionPrint() + }, +} + +func init() { + rootCmd.AddCommand(versionCmd) +} diff --git a/craapi b/craapi new file mode 100755 index 0000000..beaed4d Binary files /dev/null and b/craapi differ diff --git a/craapi.config b/craapi.config new file mode 100644 index 0000000..802a135 --- /dev/null +++ b/craapi.config @@ -0,0 +1,2 @@ +servername: +port: 19999 \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..01337bf --- /dev/null +++ b/go.mod @@ -0,0 +1,29 @@ +module craapi + +go 1.22.2 + +require ( + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + honnef.co/go/tools v0.4.7 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2cd885a --- /dev/null +++ b/go.sum @@ -0,0 +1,61 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs= +honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= diff --git a/info.json b/info.json new file mode 100644 index 0000000..ca38491 --- /dev/null +++ b/info.json @@ -0,0 +1,6 @@ +{ + "launcher-version": "v0.0", + "launcher-version-update": "launcher-url", + "launcher-url": "", + "launcher-version-info": "" +} \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..c580da0 --- /dev/null +++ b/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "craapi/cmd" +) + +func main() { + cmd.Execute() +}