simple api cli
This commit is contained in:
@@ -0,0 +1,130 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BlockedServers() (s []string, err error) {
|
||||||
|
resp, err := http.Get("https://sessionserver.mojang.com/blockedservers")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
d, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s = strings.Split(string(d), "\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProfileProperty struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Signature string `json:"signature,omitempty"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProfileResp struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Legacy bool `json:"legacy"`
|
||||||
|
Properties []ProfileProperty `json:"properties"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasJoined(name, server, ip string) (p ProfileResp, err error) {
|
||||||
|
url := "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" + name + "&serverId=" + server
|
||||||
|
if ip != "" {
|
||||||
|
url += "&ip=" + ip
|
||||||
|
}
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
err = fmt.Errorf("bad status code %v", resp.StatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type MojangPublicKeysResp struct {
|
||||||
|
ProfilePropertyKeys []string `json:"profilePropertyKeys"`
|
||||||
|
PlayerCertificateKeys []string `json:"playerCertificateKeys"`
|
||||||
|
|
||||||
|
// AuthenticationKeys are undocumented by wiki.vg but they exist as of the time of writing so ill include them
|
||||||
|
AuthenticationKeys []string `json:"authenticationKeys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func MojangPublicKeys() (keys MojangPublicKeysResp, err error) {
|
||||||
|
resp, err := http.Get("https://sessionserver.mojang.com/session/minecraft/profile/public_key_by_token")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&keys)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Profile(id string, unsinged bool) (p ProfileResp, err error) {
|
||||||
|
url := "https://sessionserver.mojang.com/session/minecraft/profile/" + id
|
||||||
|
if !unsinged {
|
||||||
|
url += "?unsigned=false"
|
||||||
|
}
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type IdName struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NameToId(name string) (idName IdName, err error) {
|
||||||
|
// may also use these:
|
||||||
|
//https://api.mojang.com/users/profiles/minecraft/<player name>
|
||||||
|
//https://api.minecraftservices.com/minecraft/profile/lookup/name/<player name>
|
||||||
|
//https://api.mojang.com/minecraft/profile/lookup/name/<player name>
|
||||||
|
resp, err := http.Get("https://api.minecraftservices.com/minecraft/profile/lookup/name/" + name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&idName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func NameToIdBulk(names []string) (idNames []IdName, err error) {
|
||||||
|
b := bytes.NewBuffer(nil)
|
||||||
|
err = json.NewEncoder(b).Encode(names)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// may also use these:
|
||||||
|
//https://api.mojang.com/profiles/minecraft
|
||||||
|
//https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname
|
||||||
|
//https://api.mojang.com/minecraft/profile/lookup/bulk/byname
|
||||||
|
r, err := http.NewRequest("POST", "https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname", b)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.Header.Set("Content-Type", "application/json")
|
||||||
|
resp, err := http.DefaultClient.Do(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&idNames)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/admin-else/strom/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cmd = flag.NewFlagSet("api", flag.ContinueOnError)
|
||||||
|
var tokenFlag = cmd.String("token", os.Getenv("MC_TOKEN"), "token to use")
|
||||||
|
|
||||||
|
var renameFlag = cmd.String("rename", "", "rename the player")
|
||||||
|
|
||||||
|
var uuidFlag = cmd.String("uuid", "", "get data about player with uuid")
|
||||||
|
var nameFlag = cmd.String("name", "", "get data about player with name")
|
||||||
|
var unsignedFlag = cmd.Bool("unsigned", true, "use unsigned mode for properties signatures")
|
||||||
|
|
||||||
|
var PleaseProvideArgumentErr = errors.New("please provide an argument")
|
||||||
|
|
||||||
|
func Run(args []string) (err error) {
|
||||||
|
err = cmd.Parse(args)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a := &api.Account{}
|
||||||
|
if *tokenFlag != "" {
|
||||||
|
a, err = api.NewAccountFromYGG(*tokenFlag)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var data any
|
||||||
|
if *renameFlag != "" {
|
||||||
|
data, err = a.ChangeName(*renameFlag)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if *uuidFlag != "" || *nameFlag != "" {
|
||||||
|
if *nameFlag != "" {
|
||||||
|
var idName api.IdName
|
||||||
|
idName, err = api.NameToId(*nameFlag)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*uuidFlag = idName.Id
|
||||||
|
}
|
||||||
|
data, err = api.Profile(*uuidFlag, *unsignedFlag)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = PleaseProvideArgumentErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.NewEncoder(os.Stdout).Encode(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
+3
-1
@@ -8,6 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
|
"github.com/admin-else/strom/cmd/strom/api"
|
||||||
"github.com/admin-else/strom/cmd/strom/offline_uuid"
|
"github.com/admin-else/strom/cmd/strom/offline_uuid"
|
||||||
"github.com/admin-else/strom/cmd/strom/packet_inspector"
|
"github.com/admin-else/strom/cmd/strom/packet_inspector"
|
||||||
"github.com/admin-else/strom/cmd/strom/print_nbt"
|
"github.com/admin-else/strom/cmd/strom/print_nbt"
|
||||||
@@ -22,6 +23,7 @@ var subcommands = map[string]func(args []string) error{
|
|||||||
"print-nbt": print_nbt.Run,
|
"print-nbt": print_nbt.Run,
|
||||||
"status": status.Run,
|
"status": status.Run,
|
||||||
"packet-spy": packet_inspector.Run,
|
"packet-spy": packet_inspector.Run,
|
||||||
|
"api": api.Run,
|
||||||
}
|
}
|
||||||
|
|
||||||
func Help(args []string) (err error) {
|
func Help(args []string) (err error) {
|
||||||
@@ -37,7 +39,7 @@ func mainE() (err error) {
|
|||||||
|
|
||||||
// Debug stuff
|
// Debug stuff
|
||||||
//slog.SetLogLoggerLevel(slog.LevelDebug)
|
//slog.SetLogLoggerLevel(slog.LevelDebug)
|
||||||
//args = []string{"TEST", "status", "-srv", "-addr", "tcpshield.1f2d.net:25565"}
|
args = []string{"TEST", "api", "-name", "Admin_Else"}
|
||||||
|
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
err = ExpectedASubcommandErr
|
err = ExpectedASubcommandErr
|
||||||
|
|||||||
Reference in New Issue
Block a user