Browse Source

[Improved] Generify of minecraft servers

master
Paul Glaß 3 years ago
parent
commit
1242c85663
6 changed files with 160 additions and 99 deletions
  1. +3
    -15
      app/src/main/java/de/yannicpunktdee/yoshibot/main/YoshiBot.java
  2. +10
    -8
      app/src/main/java/de/yannicpunktdee/yoshibot/utils/Resources.java
  3. +25
    -76
      app/src/main/java/de/yannicpunktdee/yoshibot/utils/StatusProvider.java
  4. +99
    -0
      app/src/main/java/de/yannicpunktdee/yoshibot/utils/StatusProviderFactory.java
  5. +1
    -0
      rsc/Config.properties
  6. +22
    -0
      rsc/mcservers.json

+ 3
- 15
app/src/main/java/de/yannicpunktdee/yoshibot/main/YoshiBot.java View File

@ -110,31 +110,19 @@ public final class YoshiBot {
jdaBuilder.setStatus(OnlineStatus.ONLINE);
System.out.println("YoshiBot online.");
Logger.logInfo("YoshiBot online.");
commandLineThread = new CommandLine();
commandLineThread.start();
allProvides.add(
new StatusProvider("Kreativ - 1.17", "status_message_kreativ", guild, Resources.getStatus_update(),
25565));
allProvides.add(
new StatusProvider("Enigmatica 6: Expert 1.0.0", "status_message_modded", guild,
Resources.getStatus_update(),
25566));
allProvides.add(new StatusProvider("Vanilla - 1.18", "status_message_eighteen_vanilla", guild,
Resources.getStatus_update(), 25567));
allProvides.add(new StatusProvider("MCMuffing™®㋏ Inc.", "status_message_selina", guild,
Resources.getStatus_update(), 25568));
StatusProviderFactory.createStatusProviders(Resources.getMcserver_config_file(), allProvides);
//SauceProvider.init(300);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(YoshiBot::setRandomActivity, 0, 10, TimeUnit.HOURS);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
YoshiBot.getInstance().stop();
}));
Runtime.getRuntime().addShutdownHook(new Thread(() -> YoshiBot.getInstance().stop()));
joinVoiceChannelWithMostMembers();
}


+ 10
- 8
app/src/main/java/de/yannicpunktdee/yoshibot/utils/Resources.java View File

@ -22,15 +22,15 @@ public final class Resources {
private static boolean greetings_and_byebyes_on;
@Getter
private static int status_update;
private static int statusUpdate;
@Getter
private static long guild_id;
@Getter
private static String resourcePath, configPath, audioPath, tempPath, activitiesPath, greetingsPath, byebyesPath,
sauceConfigPath, ttsPath, patPngPath, imagePath, bonkPngPath, jda_builder_string, mc_server, status_channel,
path_to_mcstatus, comebacksPath, departsPath;
sauceConfigPath, ttsPath, patPngPath, imagePath, bonkPngPath, jda_builder_string, status_channel,
path_to_mcstatus, comebacksPath, departsPath, mcserver_config_file;
private static List<String> greetings, byebyes, departs, comebacks;
@ -288,12 +288,14 @@ public final class Resources {
}
private static boolean initStatusMessage() {
if (propertiesFile.containsKey("mc_server") && propertiesFile.containsKey("status_channel")) {
mc_server = propertiesFile.getProperty("mc_server");
status_channel = propertiesFile.getProperty("status_channel");
path_to_mcstatus = propertiesFile.getProperty("path_to_mcstatus");
if (propertiesFile.containsKey("path_to_mcstatus") &&
propertiesFile.containsKey("status_channel") &&
propertiesFile.containsKey("path_to_status_json")) {
status_channel = propertiesFile.getProperty("status_channel");
path_to_mcstatus = propertiesFile.getProperty("path_to_mcstatus");
mcserver_config_file = propertiesFile.getProperty("path_to_status_json");
try {
status_update = Integer.parseInt(propertiesFile.getProperty("status_update"));
statusUpdate = Integer.parseInt(propertiesFile.getProperty("status_update"));
} catch (NumberFormatException e) {
return false;
}


+ 25
- 76
app/src/main/java/de/yannicpunktdee/yoshibot/utils/StatusProvider.java View File

@ -1,25 +1,15 @@
package de.yannicpunktdee.yoshibot.utils;
import de.yannicpunktdee.yoshibot.main.YoshiBot;
import lombok.SneakyThrows;
import lombok.Getter;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import org.apache.commons.io.FileUtils;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@ -33,64 +23,31 @@ public class StatusProvider implements Provider {
private int lastPlayersOnline = -1;
private volatile String messageId = null;
private final int serverPort;
@Getter
private final String ip;
private final String desc;
private LocalDateTime timestampLastPlayerOnline;
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss E, dd.MM.yyyy",
Locale.GERMANY);
private final ProcessBuilder mcstatus = new ProcessBuilder();
@SneakyThrows
@SuppressWarnings("empty")
public StatusProvider(String desc, String messageIdKey, Guild guild, int secondsPerTime,
int serverPort) {
TextChannel statusChannel = guild.getTextChannelById(Resources.getStatus_channel());
this.desc = desc;
this.messageId = StatusProvider.ensureMessageId(statusChannel, messageIdKey, guild);
this.serverPort = serverPort;
this.mcstatus.command(Resources.getPath_to_mcstatus(), Resources.getMc_server() + ":" + serverPort, "json");
public StatusProvider(String desc, int secondsPerTime, String ip, LocalDateTime timestamp) {
this.timestampLastPlayerOnline = timestamp;
this.desc = desc;
this.ip = ip;
this.mcstatus.command(Resources.getPath_to_mcstatus(), ip, "json");
File timeStampSave = new File(String.format("%s/%d.txt", Resources.getResourcePath(), serverPort));
timestampLastPlayerOnline = null;
if (!timeStampSave.createNewFile()) {
List<String> contents = Files.readAllLines(timeStampSave.toPath());
if (contents.size() > 0) {
timestampLastPlayerOnline = LocalDateTime.parse(contents.get(0), TIME_FORMATTER);
}
}
statusScheduler.scheduleAtFixedRate(() -> updateStatusMessage(statusChannel), 0, secondsPerTime,
statusScheduler.scheduleAtFixedRate(this::updateStatusMessage, 0, secondsPerTime,
TimeUnit.SECONDS);
}
private synchronized static String ensureMessageId(TextChannel statusChannel, String messageIdKey, Guild guild) {
if (Resources.getProperty(messageIdKey) != null) {
return Resources.getProperty(messageIdKey);
} else {
assert statusChannel != null;
MessageBuilder mb = new MessageBuilder();
mb.append("ServerInformation");
Message msg = mb.build();
statusChannel.sendMessage(msg).complete();
Resources.setProperty(messageIdKey, statusChannel.getLatestMessageId());
return statusChannel.getLatestMessageId();
}
}
@SuppressWarnings("unchecked")
public void updateStatusMessage(TextChannel statusChannel) {
public void updateStatusMessage() {
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle(desc);
eb.addField("IP", Resources.getMc_server() + ":" + serverPort, false);
eb.addField("IP", ip, false);
try {
Map<String, Object> serverInfo = getPlayersOnline();
@ -99,30 +56,27 @@ public class StatusProvider implements Provider {
eb.addField("Server still Starting", "True", false);
} else {
int newPlayersOnline = (int) serverInfo.get("playerCount");
if (newPlayersOnline == lastPlayersOnline) return;
else {
if (timestampLastPlayerOnline == null && newPlayersOnline == 0 && lastPlayersOnline != -1) {
timestampLastPlayerOnline = LocalDateTime.now();
} else if (timestampLastPlayerOnline != null && newPlayersOnline > 0) {
timestampLastPlayerOnline = null;
}
lastPlayersOnline = newPlayersOnline;
}
eb.addField("Version", (String) serverInfo.get("version"), true);
eb.addField("MOTD", (String) serverInfo.get("motd"), true);
eb.addField("Spieler online", lastPlayersOnline + " / " + serverInfo.get("playerMax"), false);
if (timestampLastPlayerOnline != null) {
eb.addField("Zuletzt gesehen", TIME_FORMATTER.format(timestampLastPlayerOnline), false);
}
if (lastPlayersOnline > 0) {
eb.addField("Spieler online", newPlayersOnline + " / " + serverInfo.get("playerMax"), false);
if (newPlayersOnline == 0) {
if (lastPlayersOnline > newPlayersOnline) {
timestampLastPlayerOnline = LocalDateTime.now();
StatusProviderFactory.updateTimestamp(this, timestampLastPlayerOnline);
}
eb.addField("Zuletzt gesehen",
StatusProviderFactory.TIME_FORMATTER.format(timestampLastPlayerOnline), false);
} else {
eb.addField("Spieler:", String.join(", ", (List<String>) serverInfo.get("playerNames")), false);
}
lastPlayersOnline = newPlayersOnline;
}
} else {
eb.addField("Offline", "", false);
}
statusChannel.editMessageById(this.messageId, eb.build()).queue();
StatusProviderFactory.updateStatus(this, eb.build());
} catch (IOException e) {
Logger.logError(e.toString());
}
@ -138,7 +92,7 @@ public class StatusProvider implements Provider {
e.printStackTrace();
}
if (process.exitValue() != 0) {
Logger.logError("MCStatus on port " + serverPort + " exited with errorcode " + process.exitValue());
Logger.logError("MCStatus on IP " + ip + " exited with errorcode " + process.exitValue());
}
String output = new BufferedReader(new InputStreamReader(process.getInputStream())).lines()
@ -175,13 +129,8 @@ public class StatusProvider implements Provider {
return result;
}
@SneakyThrows
@Override
public void onStop() {
Logger.logInfo(String.format("Stopping StatusProvider for \"%s\" on Port %d", desc, serverPort));
if (timestampLastPlayerOnline != null) {
FileUtils.writeStringToFile(new File(Resources.getResourcePath() + "/" + serverPort + ".txt"),
TIME_FORMATTER.format(timestampLastPlayerOnline), "UTF" + "-8");
}
StatusProviderFactory.updateTimestamp(this, timestampLastPlayerOnline);
}
}

+ 99
- 0
app/src/main/java/de/yannicpunktdee/yoshibot/utils/StatusProviderFactory.java View File

@ -0,0 +1,99 @@
package de.yannicpunktdee.yoshibot.utils;
import de.yannicpunktdee.yoshibot.main.YoshiBot;
import lombok.NonNull;
import lombok.SneakyThrows;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
public abstract class StatusProviderFactory {
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss E, dd.MM.yyyy",
Locale.GERMANY);
private static final Map<StatusProvider, Long> providers = new HashMap<>();
private static final Map<StatusProvider, JSONObject> providerJSON = new HashMap<>();
private static JSONObject rootJSON;
private static File configFile;
@NonNull
private static final TextChannel statusChannel =
Objects.requireNonNull(YoshiBot.getInstance().getGuild().getTextChannelById(Resources.getStatus_channel()));
@SneakyThrows
public static void createStatusProviders(String configFilePath, Set<Provider> allProviders) {
configFile = new File(configFilePath);
rootJSON = new JSONObject(String.join("\n", Files.readAllLines(configFile.toPath())));
final JSONArray servers = rootJSON.getJSONArray("servers");
for (int i = 0; i < servers.length(); i++) {
final JSONObject server = servers.getJSONObject(i);
final String ip = server.getString("ip");
final String name = server.getString("name");
if (!server.has("timestamp")) {
server.put("timestamp", TIME_FORMATTER.format(LocalDateTime.now()));
}
final LocalDateTime timestamp = LocalDateTime.parse(server.getString("timestamp"), TIME_FORMATTER);
if (!server.has("message")) {
server.put("message", -1);
}
final long msg = ensureMessageId(server.getLong("message"));
server.put("message", msg);
StatusProvider provider = new StatusProvider(name, Resources.getStatusUpdate(), ip, timestamp);
providers.put(provider, msg);
providerJSON.put(provider, servers.getJSONObject(i));
}
allProviders.addAll(providers.keySet());
writeJSON();
}
public static void updateStatus(StatusProvider provider, MessageEmbed msg) {
statusChannel.editMessageById(providers.get(provider), msg).queue();
}
public static void updateTimestamp(StatusProvider provider, LocalDateTime timestamp) {
providerJSON.get(provider).put("timestamp", TIME_FORMATTER.format(timestamp));
writeJSON();
}
@SneakyThrows
private static void writeJSON() {
BufferedWriter bw = new BufferedWriter(new FileWriter(configFile));
bw.write(rootJSON.toString(2));
bw.flush();
}
private static long createStatusMessage() {
Logger.logInfo("Creating new Status Message!");
return StatusProviderFactory.statusChannel.sendMessage(
new MessageBuilder()
.append("ServerInformation")
.build())
.complete().getIdLong();
}
private static long ensureMessageId(long messageId) {
try {
Message msg = StatusProviderFactory.statusChannel.retrieveMessageById(messageId).complete();
return msg.getIdLong();
} catch (ErrorResponseException e) {
return createStatusMessage();
}
}
}

+ 1
- 0
rsc/Config.properties View File

@ -11,3 +11,4 @@ status_message_modded=952638124197040139
status_message_kreativ=952638123324616735
status_update=30
path_to_mcstatus=/home/paul/.local/bin/mcstatus
path_to_status_json=/home/paul/gits/YoshiBot/rsc/mcservers.json

+ 22
- 0
rsc/mcservers.json View File

@ -0,0 +1,22 @@
{
"servers": [
{
"ip": "85.214.148.23:25568",
"name": "MCMuffing™®㋏ Inc.",
"message": 960979835361046558,
"timestamp": "21:16:35 Di, 05.04.2022"
},
{
"ip": "85.214.148.23:25566",
"name": "Enigmatica 6: Expert 1.0.0",
"message": 960970269051191386,
"timestamp": "20:15:36 Di, 05.04.2022"
},
{
"ip": "85.214.148.23:25570",
"name": "Medieval Minecraft 1.16.5 v52",
"message": 960970288194002954,
"timestamp": "20:15:36 Di, 05.04.2022"
}
]
}

Loading…
Cancel
Save