summaryrefslogtreecommitdiff
path: root/yggdrasil/realserver.go
blob: 86f4887dc4dd0cc95aa9797d898719fc3478e25a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package yggdrasil

import (
	"encoding/json"
	"fmt"
	"github.com/imroc/req"
	"github.com/rs/zerolog/log"
	"net/url"
	"time"
)

type realServer struct {
	req       *req.Req
	apiPrefix string
	name      string
}

func (r realServer) Name() string {
	return r.name
}

func (r realServer) HasJoined(username string, serverID string) (*HasJoinedResponse, error) {
	u, err := url.Parse(r.apiPrefix + "/session/minecraft/hasJoined")
	if err != nil {
		return nil, fmt.Errorf("url parse: %w", err)
	}
	q := u.Query()
	q.Set("username", username)
	q.Set("serverId", serverID)
	u.RawQuery = q.Encode()
	url2 := u.String()
	log.Debug().Str("url", url2).Msg("hasJoined request")
	resp, err := r.req.Get(url2)
	if err != nil {
		return nil, fmt.Errorf("http request: %w", err)
	}
	respBytes := resp.Bytes()
	var resp2 HasJoinedResponse
	// decode JSON only if HTTP status code is OK
	if resp.Response().StatusCode == 200 {
		err := json.Unmarshal(respBytes, &resp2)
		if err != nil {
			log.Error().
				Str("body", string(respBytes)).
				Err(err).
				Msg("unmarshal response body JSON failed")
		}
	}
	resp2.StatusCode = resp.Response().StatusCode
	resp2.RawBody = respBytes
	resp2.ServerName = r.name
	log.Debug().
		Int("statusCode", resp2.StatusCode).
		Str("rawBody", string(respBytes)).
		Msg("hasJoined response")
	return &resp2, nil
}

func NewServer(apiPrefix string, opt ...NewServerOptions) (Server, error) {
	name := "<unnamed server>"
	r := req.New()
	if len(opt) > 0 {
		if p := opt[0].Proxy; p != "" {
			err := r.SetProxyUrl(p)
			if err != nil {
				return nil, fmt.Errorf("set proxy url: %w", err)
			}
		}
		if t := opt[0].Timeout; t > 0 {
			r.SetTimeout(t)
		}
		if n := opt[0].Name; n != "" {
			name = n
		}
	}
	return realServer{
		req:       r,
		apiPrefix: apiPrefix,
		name:      name,
	}, nil
}

type NewServerOptions struct {
	Name  string
	Proxy string
	// Timeout is HTTP API request timeout
	Timeout time.Duration
}