Remove widget code
This commit is contained in:
BIN
src/Ubuntu-B.ttf
BIN
src/Ubuntu-B.ttf
Binary file not shown.
BIN
src/Ubuntu-R.ttf
BIN
src/Ubuntu-R.ttf
Binary file not shown.
Binary file not shown.
@@ -12,7 +12,6 @@ func init() {
|
||||
app.Get("/ping", PingHandler)
|
||||
app.Get("/status/java/:address", JavaStatusHandler)
|
||||
app.Get("/status/bedrock/:address", BedrockStatusHandler)
|
||||
app.Get("/widget/java/:address", JavaWidgetHandler)
|
||||
app.Get("/icon", DefaultIconHandler)
|
||||
app.Get("/icon/:address", IconHandler)
|
||||
app.Use(NotFoundHandler)
|
||||
@@ -52,33 +51,6 @@ func JavaStatusHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.JSON(response)
|
||||
}
|
||||
|
||||
// JavaWidgetHandler returns the widget of the Java Edition server.
|
||||
func JavaWidgetHandler(ctx *fiber.Ctx) error {
|
||||
host, port, err := ParseAddress(ctx.Params("address"), 25565)
|
||||
|
||||
if err != nil {
|
||||
return ctx.Status(http.StatusBadRequest).SendString("Invalid address value")
|
||||
}
|
||||
|
||||
if err = r.Increment(fmt.Sprintf("java-hits:%s-%d", host, port)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
response, _, err := GetJavaStatus(host, port, false)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
widget, err := GenerateJavaWidget(response, ctx.QueryBool("dark", true))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ctx.Type("png").Send(widget)
|
||||
}
|
||||
|
||||
// BedrockStatusHandler returns the status of the Bedrock edition Minecraft server specified in the address parameter.
|
||||
func BedrockStatusHandler(ctx *fiber.Ctx) error {
|
||||
host, port, err := ParseAddress(ctx.Params("address"), 19132)
|
||||
|
||||
111
src/util.go
111
src/util.go
@@ -1,86 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
_ "embed"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/png"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/freetype/truetype"
|
||||
"golang.org/x/image/font"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed icon.png
|
||||
defaultIconBytes []byte
|
||||
defaultIcon image.Image
|
||||
//go:embed Ubuntu-B.ttf
|
||||
ubuntuBoldFontBytes []byte
|
||||
ubuntuBoldFont font.Face
|
||||
//go:embed Ubuntu-R.ttf
|
||||
ubuntuRegularFontBytes []byte
|
||||
ubuntuRegularFont font.Face
|
||||
//go:embed UbuntuMono-R.ttf
|
||||
ubuntuMonoFontBytes []byte
|
||||
ubuntuMonoFont font.Face
|
||||
ubuntuMonoSmallFont font.Face
|
||||
blockedServers *MutexArray = nil
|
||||
ipAddressRegex *regexp.Regexp = regexp.MustCompile(`^\d{1,3}(\.\d{1,3}){3}$`)
|
||||
blockedServers *MutexArray = nil
|
||||
ipAddressRegex *regexp.Regexp = regexp.MustCompile(`^\d{1,3}(\.\d{1,3}){3}$`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
if defaultIcon, err = png.Decode(bytes.NewReader(defaultIconBytes)); err != nil {
|
||||
log.Fatalf("Failed to parse default icon: %v", err)
|
||||
}
|
||||
|
||||
ubuntuBold, err := truetype.Parse(ubuntuBoldFontBytes)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse Ubuntu Bold font: %v", err)
|
||||
}
|
||||
|
||||
ubuntuBoldFont = truetype.NewFace(ubuntuBold, &truetype.Options{
|
||||
Size: 36,
|
||||
})
|
||||
|
||||
ubuntuRegular, err := truetype.Parse(ubuntuRegularFontBytes)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse Ubuntu Regular font: %v", err)
|
||||
}
|
||||
|
||||
ubuntuRegularFont = truetype.NewFace(ubuntuRegular, &truetype.Options{
|
||||
Size: 36,
|
||||
})
|
||||
|
||||
ubuntuMono, err := truetype.Parse(ubuntuMonoFontBytes)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse Ubuntu Mono Regular font: %v", err)
|
||||
}
|
||||
|
||||
ubuntuMonoFont = truetype.NewFace(ubuntuMono, &truetype.Options{
|
||||
Size: 36,
|
||||
})
|
||||
|
||||
ubuntuMonoSmallFont = truetype.NewFace(ubuntuMono, &truetype.Options{
|
||||
Size: 20,
|
||||
})
|
||||
}
|
||||
|
||||
// MutexArray is a thread-safe array for storing and checking values.
|
||||
type MutexArray struct {
|
||||
List []interface{}
|
||||
@@ -185,52 +124,6 @@ func ParseAddress(address string, defaultPort uint16) (string, uint16, error) {
|
||||
return result[0], uint16(port), nil
|
||||
}
|
||||
|
||||
// EncodePNG encodes an image.Image into a byte array.
|
||||
func EncodePNG(img image.Image) ([]byte, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
err := png.Encode(buf, img)
|
||||
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
// GetStatusIcon returns the icon of the server if it exists, or returns the default icon.
|
||||
func GetStatusIcon(response *JavaStatusResponse) (image.Image, error) {
|
||||
if response == nil || !response.Online || response.Icon == nil {
|
||||
return defaultIcon, nil
|
||||
}
|
||||
|
||||
data, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(*response.Icon, "data:image/png;base64,"))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return png.Decode(bytes.NewReader(data))
|
||||
}
|
||||
|
||||
// ScaleImageNearestNeighbor scales an image using the nearest neighbor method.
|
||||
// This method is extremely inefficient, but at the small scaling values we are using the performance hit is almost immeasurable.
|
||||
func ScaleImageNearestNeighbor(img image.Image, sx, sy int) image.Image {
|
||||
s := img.Bounds().Size()
|
||||
|
||||
out := image.NewRGBA(image.Rect(0, 0, s.X*sx, s.Y*sy))
|
||||
|
||||
for ix := 0; ix < s.X; ix++ {
|
||||
for iy := 0; iy < s.Y; iy++ {
|
||||
c := img.At(ix, iy)
|
||||
|
||||
for ox := 0; ox < sx; ox++ {
|
||||
for oy := 0; oy < sy; oy++ {
|
||||
out.Set(ix*sx+ox, iy*sy+oy, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// PointerOf returns a pointer of the argument passed.
|
||||
func PointerOf[T any](v T) *T {
|
||||
return &v
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/fogleman/gg"
|
||||
)
|
||||
|
||||
const (
|
||||
// WidgetWidth is the width of the image of the widget.
|
||||
WidgetWidth = 860
|
||||
// WidgetHeight is the height of the image of the widget.
|
||||
WidgetHeight = 240
|
||||
)
|
||||
|
||||
// GenerateJavaWidget generates a widget image from the Java Edition status response.
|
||||
func GenerateJavaWidget(status *JavaStatusResponse, isDark bool) ([]byte, error) {
|
||||
var statusColor color.Color = color.RGBA{230, 57, 70, 255}
|
||||
var statusText string = "Offline"
|
||||
var players string = "Unknown players"
|
||||
var address string = status.Host
|
||||
|
||||
if status.Online {
|
||||
statusColor = color.RGBA{46, 204, 113, 255}
|
||||
statusText = "Online"
|
||||
|
||||
if status.Players.Online != nil && status.Players.Max != nil {
|
||||
players = fmt.Sprintf("%d/%d players", *status.Players.Online, *status.Players.Max)
|
||||
} else if status.Players.Online != nil {
|
||||
players = fmt.Sprintf("%d players", *status.Players.Online)
|
||||
} else {
|
||||
players = "Unknown players"
|
||||
}
|
||||
}
|
||||
|
||||
if status.Port != 25565 {
|
||||
address += fmt.Sprintf(":%d", status.Port)
|
||||
}
|
||||
|
||||
icon, err := GetStatusIcon(status)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx := gg.NewContext(WidgetWidth, WidgetHeight)
|
||||
|
||||
// Background color
|
||||
if isDark {
|
||||
ctx.SetColor(color.Gray{32})
|
||||
} else {
|
||||
ctx.SetColor(color.White)
|
||||
}
|
||||
ctx.DrawRoundedRectangle(0, 0, WidgetWidth, WidgetHeight, 16)
|
||||
ctx.Fill()
|
||||
|
||||
// Draw server icon
|
||||
ctx.DrawImage(ScaleImageNearestNeighbor(icon, 3, 3), (WidgetHeight-64*3)/2, (WidgetHeight-64*3)/2)
|
||||
|
||||
// Draw status bubble
|
||||
ctx.SetColor(statusColor)
|
||||
ctx.DrawCircle(WidgetHeight+8, WidgetHeight/2-55, 8)
|
||||
ctx.Fill()
|
||||
|
||||
// Draw status text
|
||||
ctx.SetFontFace(ubuntuBoldFont)
|
||||
ctx.DrawString(statusText, WidgetHeight+28, WidgetHeight/2-44)
|
||||
ctx.Stroke()
|
||||
|
||||
// Draw address text
|
||||
if isDark {
|
||||
ctx.SetColor(color.White)
|
||||
} else {
|
||||
ctx.SetColor(color.Black)
|
||||
}
|
||||
|
||||
ctx.SetFontFace(ubuntuMonoFont)
|
||||
ctx.DrawString(address, WidgetHeight, WidgetHeight/2+4)
|
||||
ctx.Stroke()
|
||||
|
||||
// Draw players text
|
||||
ctx.SetColor(color.Gray{127})
|
||||
ctx.SetFontFace(ubuntuRegularFont)
|
||||
ctx.DrawString(players, WidgetHeight, WidgetHeight/2+58)
|
||||
ctx.Stroke()
|
||||
|
||||
// Draw mcstatus.io branding
|
||||
ctx.SetColor(color.Gray{152})
|
||||
ctx.SetFontFace(ubuntuMonoSmallFont)
|
||||
ctx.DrawStringAnchored("© mcstatus.io", WidgetWidth-16, WidgetHeight-38, 1.0, 1.0)
|
||||
ctx.Stroke()
|
||||
|
||||
return EncodePNG(ctx.Image())
|
||||
}
|
||||
Reference in New Issue
Block a user