Support SRV records in net.Dial and bot.PingAndListContext

This commit is contained in:
Tnze
2022-03-06 00:28:46 +08:00
parent 23bcf9149a
commit cf25807f68
5 changed files with 240 additions and 133 deletions

View File

@ -1,10 +1,7 @@
# mcping
Ping tool for Minecraft: Java Edition.
Just for example. Not recommended for daily use. Use [github.com/go-mc/mcping](github.com/go-mc/mcping) instead, which including SRV parse.
A ping tool for Minecraft: Java Edition.
适用于Minecraft: Java Edition的ping工具。
只起示例作用,日常使用建议使用完整版[github.com/go-mc/mcping](github.com/go-mc/mcping)包含SRV解析等功能。
Install with go tools:
```go get -u github.com/Tnze/go-mc/cmd/mcping```
@ -13,5 +10,5 @@ Install with go tools:
Install with Homebrew:
```brew tap Tnze/tap && brew install mcping```
Useage:
Usage:
```mcping <hostname>[:port]```

View File

@ -4,18 +4,25 @@ package main
import (
"encoding/base64"
"encoding/json"
"errors"
"flag"
"fmt"
"image"
_ "image/jpeg"
"image/png"
"os"
"strings"
"text/template"
"time"
"github.com/google/uuid"
"github.com/Tnze/go-mc/bot"
"github.com/Tnze/go-mc/chat"
"github.com/google/uuid"
)
var protocol = flag.Int("p", 578, "The protocol version number sent during ping")
var favicon = flag.String("f", "", "If specified, the server's icon will be save to")
type status struct {
Description chat.Message
Players struct {
@ -39,50 +46,15 @@ type status struct {
// and prepended with "data:image/png;base64,".
type Icon string
var IconFormatErr = errors.New("data format error")
var IconAbsentErr = errors.New("icon not present")
// ToPNG decode base64-icon, return a PNG image
// Take care of there is no safety check, image may contain malicious code.
func (i Icon) ToPNG() ([]byte, error) {
func (i Icon) ToImage() (icon image.Image, err error) {
const prefix = "data:image/png;base64,"
if i == "" {
return nil, IconAbsentErr
}
if !strings.HasPrefix(string(i), prefix) {
return nil, IconFormatErr
return nil, fmt.Errorf("server icon should prepended with %q", prefix)
}
return base64.StdEncoding.DecodeString(strings.TrimPrefix(string(i), prefix))
}
func main() {
addr := getAddr()
fmt.Printf("MCPING (%s):", addr)
resp, delay, err := bot.PingAndList(addr)
if err != nil {
fmt.Printf("ping and list server fail: %v", err)
os.Exit(1)
}
var s status
err = json.Unmarshal(resp, &s)
if err != nil {
fmt.Print("unmarshal resp fail:", err)
os.Exit(1)
}
s.Delay = delay
fmt.Print(&s)
}
func getAddr() string {
const usage = "Usage: mcping <hostname>[:port]"
if len(os.Args) < 2 {
fmt.Println("no host name.", usage)
os.Exit(1)
}
return os.Args[1]
base64png := strings.TrimPrefix(string(i), prefix)
r := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64png))
icon, err = png.Decode(r)
return
}
var outTemp = template.Must(template.New("output").Parse(`
@ -102,3 +74,36 @@ func (s *status) String() string {
}
return sb.String()
}
func usage() {
_, _ = fmt.Fprintf(flag.CommandLine.Output(), "Usage:\n%s [-f] [-p] <address>[:port]\n", os.Args[0])
flag.PrintDefaults()
}
func main() {
flag.Parse()
flag.Usage = usage
addr := flag.Arg(0)
if addr == "" {
fmt.Println("")
flag.Usage()
os.Exit(2)
}
fmt.Printf("MCPING (%s):", addr)
resp, delay, err := bot.PingAndList(addr)
if err != nil {
fmt.Printf("Ping and list server fail: %v", err)
os.Exit(1)
}
var s status
err = json.Unmarshal(resp, &s)
if err != nil {
fmt.Print("Parse json response fail:", err)
os.Exit(1)
}
s.Delay = delay
fmt.Print(&s)
}