aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/api/api.go
blob: 3aba92465d03a9ba52f07089d5f25533a1281ada (plain) (blame)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package api

import (
	"context"
	"encoding/json"
	"log/slog"
	"net/http"
	"nonsense-time/util"
	"os"
	"strconv"
	"time"

	"github.com/docker/docker/pkg/stdcopy"
)

type ServerStatus struct {
	Online    bool      `json:"online"`
	Site      string    `json:"url"`
	Timestamp time.Time `json:"timestamp"`
}

var Logger *slog.Logger

const VTT_URL string = "https://dnd.jpappel.xyz/foundry"

func remoteOnline(ctx context.Context, url string) ServerStatus {
	status := ServerStatus{Site: url, Timestamp: time.Now()}
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		panic(err)
	}

	_, err = http.DefaultClient.Do(req)
	if err != nil {
		status.Online = false
	} else {
		status.Online = true
	}

	return status
}

func respondOnline(w http.ResponseWriter, status ServerStatus) {
	jsonData, err := json.Marshal(status)
	if err != nil {
		http.Error(w, "Error constructing response", http.StatusInternalServerError)
		Logger.Error("Error marshalling site status data", slog.Any("err", err))
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonData)
}

func VttOnline(w http.ResponseWriter, req *http.Request) {
	status := vttStatus(req.Context())

	if !status.Online {
		Logger.DebugContext(req.Context(), "Foundry VTT is offline")
	}
	respondOnline(w, status)
}

func VttRedirect(w http.ResponseWriter, req *http.Request) {
	http.Redirect(w, req, VTT_URL, http.StatusMovedPermanently)
}

func VttStart(w http.ResponseWriter, req *http.Request) {
	if startVtt(req.Context()) != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
}
func VttStop(w http.ResponseWriter, req *http.Request) {
	if stopVtt(req.Context()) != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
}
func VttRestart(w http.ResponseWriter, req *http.Request) {
	if restartVtt(req.Context()) != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
}

func VttLogs(w http.ResponseWriter, req *http.Request) {
	var lines uint = 0

	linesParam := req.URL.Query().Get("lines")
	if linesParam != "" {
		lines_64, err := strconv.ParseUint(linesParam, 10, 0)
		if err != nil {
			Logger.ErrorContext(req.Context(), "Invalid line count in vtt logs request", slog.Any("err", err))
			http.Error(w, "Invalid line count in request", http.StatusBadRequest)
			return
		}

		lines = uint(lines_64)
	}

	logReader, err := vttLogs(req.Context(), lines)
	if err != nil {
		http.Error(w, "Error occured while getting logs", http.StatusInternalServerError)
		return
	}
	defer logReader.Close()

	filteredWriter := util.NewAnsiFilterWriter(w)
	n, err := stdcopy.StdCopy(filteredWriter, filteredWriter, logReader)
	if err != nil {
		Logger.Error("Error occured while writting logs to response", slog.Any("err", err), slog.Any("request", req))
		Logger.Error("", slog.Int64("written", n))
		http.Error(w, "Error occured while writting logs", http.StatusInternalServerError)
		return
	}
}

func init() {
	Logger = slog.New(slog.NewTextHandler(os.Stdout, nil))
}