HTML motd!

This commit is contained in:
Braydon 2024-04-06 20:30:09 -04:00
parent 4cd5369bee
commit e8daa7c904
5 changed files with 150 additions and 6 deletions

@ -0,0 +1,81 @@
package me.braydon.mc.common;
import lombok.NonNull;
import lombok.experimental.UtilityClass;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
* @author Braydon
*/
@UtilityClass
public final class ColorUtils {
private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)§[0-9A-FK-OR]");
private static final Map<Character, String> COLOR_MAP = new HashMap<>();
static {
// Map each color to its corresponding hex code
COLOR_MAP.put('0', "#000000"); // Black
COLOR_MAP.put('1', "#0000AA"); // Dark Blue
COLOR_MAP.put('2', "#00AA00"); // Dark Green
COLOR_MAP.put('3', "#00AAAA"); // Dark Aqua
COLOR_MAP.put('4', "#AA0000"); // Dark Red
COLOR_MAP.put('5', "#AA00AA"); // Dark Purple
COLOR_MAP.put('6', "#FFAA00"); // Gold
COLOR_MAP.put('7', "#AAAAAA"); // Gray
COLOR_MAP.put('8', "#555555"); // Dark Gray
COLOR_MAP.put('9', "#5555FF"); // Blue
COLOR_MAP.put('a', "#55FF55"); // Green
COLOR_MAP.put('b', "#55FFFF"); // Aqua
COLOR_MAP.put('c', "#FF5555"); // Red
COLOR_MAP.put('d', "#FF55FF"); // Light Purple
COLOR_MAP.put('e', "#FFFF55"); // Yellow
COLOR_MAP.put('f', "#FFFFFF"); // White
}
/**
* Strip the color codes
* from the given input.
*
* @param input the input to strip
* @return the stripped input
*/
@NonNull
public static String stripColor(@NonNull String input) {
return STRIP_COLOR_PATTERN.matcher(input).replaceAll("");
}
/**
* Convert the given input into HTML format.
* <p>
* This will replace each color code with
* a span tag with the respective color in
* hex format.
* </p>
*
* @param input the input to convert
* @return the converted input
*/
@NonNull
public static String toHTML(@NonNull String input) {
StringBuilder builder = new StringBuilder();
boolean nextIsColor = false; // Is the next char a color code?
for (char character : input.toCharArray()) {
// Found color symbol, next color is the color
if (character == '§') {
nextIsColor = true;
continue;
}
if (nextIsColor) { // Map the current color to its hex code
String color = COLOR_MAP.getOrDefault(Character.toLowerCase(character), "");
builder.append("<span style=\"color:").append(color).append("\">");
nextIsColor = false;
continue;
}
builder.append(character); // Append the char...
}
return builder.toString();
}
}

@ -1,10 +1,14 @@
package me.braydon.mc.model;
import lombok.*;
import me.braydon.mc.common.ColorUtils;
import me.braydon.mc.model.token.JavaServerStatusToken;
import me.braydon.mc.service.pinger.MinecraftServerPinger;
import me.braydon.mc.service.pinger.impl.BedrockMinecraftServerPinger;
import me.braydon.mc.service.pinger.impl.JavaMinecraftServerPinger;
import java.util.Arrays;
/**
* A model representing a Minecraft server.
*
@ -37,6 +41,24 @@ public class MinecraftServer {
*/
@NonNull private final Players players;
/**
* The MOTD of this server.
*/
@NonNull private final MOTD motd;
/**
* The Base64 encoded icon of this server.
*/
@NonNull private final String icon;
/**
* Is this server on the list
* of blocked servers by Mojang?
*
* @see <a href="https://wiki.vg/Mojang_API#Blocked_Servers">Mojang API</a>
*/
private final boolean mojangBanned;
/**
* Version information for a server.
*/
@ -69,6 +91,43 @@ public class MinecraftServer {
private final int max;
}
/**
* The MOTD for a server.
*/
@AllArgsConstructor @Getter @ToString
public static class MOTD {
/**
* The raw MOTD lines, taken directly from the {@link JavaServerStatusToken}.
*/
@NonNull private final String[] raw;
/**
* The clean MOTD lines (no color codes).
*/
@NonNull private final String[] clean;
/**
* The HTML MOTD lines.
*/
@NonNull private final String[] html;
/**
* Create a new MOTD from a raw string.
*
* @param raw the raw motd string
* @return the new motd
*/
@NonNull
public static MOTD create(@NonNull String raw) {
String[] rawLines = raw.split("\n"); // The raw lines
return new MOTD(
rawLines,
Arrays.stream(rawLines).map(ColorUtils::stripColor).toArray(String[]::new),
Arrays.stream(rawLines).map(ColorUtils::toHTML).toArray(String[]::new)
);
}
}
/**
* A platform a Minecraft
* server can operate on.

@ -9,7 +9,8 @@ import me.braydon.mc.model.MinecraftServer;
* @author Braydon
*/
public final class BedrockMinecraftServer extends MinecraftServer {
private BedrockMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, @NonNull Players players) {
super(hostname, ip, port, version, players);
private BedrockMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version,
@NonNull Players players, @NonNull MOTD motd, @NonNull String icon, boolean mojangBanned) {
super(hostname, ip, port, version, players, motd, icon, mojangBanned);
}
}

@ -10,8 +10,9 @@ import me.braydon.mc.model.token.JavaServerStatusToken;
* @author Braydon
*/
public final class JavaMinecraftServer extends MinecraftServer {
private JavaMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, @NonNull Players players) {
super(hostname, ip, port, version, players);
private JavaMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version,
@NonNull Players players, @NonNull MOTD motd, @NonNull String icon, boolean mojangBanned) {
super(hostname, ip, port, version, players, motd, icon, mojangBanned);
}
/**
@ -25,6 +26,8 @@ public final class JavaMinecraftServer extends MinecraftServer {
*/
@NonNull
public static JavaMinecraftServer create(@NonNull String hostname, String ip, int port, @NonNull JavaServerStatusToken token) {
return new JavaMinecraftServer(hostname, ip, port, token.getVersion(), token.getPlayers());
return new JavaMinecraftServer(hostname, ip, port, token.getVersion(), token.getPlayers(),
MOTD.create(token.getDescription()), token.getFavicon(), false
);
}
}

@ -39,7 +39,7 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger<Ja
InetAddress inetAddress = DNSUtils.resolveA(hostname); // Resolve the hostname to an IP address
String ip = inetAddress == null ? null : inetAddress.getHostAddress(); // Get the IP address
if (ip != null) { // Was the IP resolved?
log.info("Resolved hostname {} to {}", hostname, ip);
log.info("Resolved hostname: {} -> {}", hostname, ip);
}
log.info("Pinging {}:{}...", hostname, port);
long before = System.currentTimeMillis(); // Timestamp before pinging