| @ -1,80 +1,103 @@ | |||||
| package de.yannicpunktdee.yoshibot.utils; | package de.yannicpunktdee.yoshibot.utils; | ||||
| import lombok.SneakyThrows; | |||||
| import net.dv8tion.jda.api.EmbedBuilder; | import net.dv8tion.jda.api.EmbedBuilder; | ||||
| import net.dv8tion.jda.api.entities.Guild; | import net.dv8tion.jda.api.entities.Guild; | ||||
| import net.dv8tion.jda.api.entities.TextChannel; | import net.dv8tion.jda.api.entities.TextChannel; | ||||
| import org.json.JSONArray; | |||||
| import org.json.JSONObject; | |||||
| import java.io.DataInputStream; | |||||
| import java.io.DataOutputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.*; | |||||
| import java.net.Socket; | import java.net.Socket; | ||||
| import java.net.UnknownHostException; | import java.net.UnknownHostException; | ||||
| import java.time.LocalDateTime; | |||||
| import java.time.format.DateTimeFormatter; | |||||
| import java.util.*; | |||||
| import java.util.concurrent.Executors; | import java.util.concurrent.Executors; | ||||
| import java.util.concurrent.ScheduledExecutorService; | import java.util.concurrent.ScheduledExecutorService; | ||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||
| import java.util.stream.Collectors; | |||||
| import java.util.stream.StreamSupport; | |||||
| public class StatusProvider { | public class StatusProvider { | ||||
| private static final ScheduledExecutorService statusScheduler = Executors.newScheduledThreadPool(1); | |||||
| private static int lastPlayersOnline = -1; | |||||
| public static void provide(int secondsPerTime, Guild guild){ | |||||
| TextChannel statusChannel = guild.getTextChannelById(Resources.getStatus_channel()); | |||||
| statusScheduler.scheduleAtFixedRate(() -> { | |||||
| try { | |||||
| updateStatusMessage(statusChannel); | |||||
| } catch (IOException e) { | |||||
| Logger.logError("Konnte Status nicht richtig abfragen."); | |||||
| } | |||||
| }, 0, secondsPerTime, TimeUnit.SECONDS); | |||||
| } | |||||
| public static void updateStatusMessage(TextChannel statusChannel) throws IOException { | |||||
| int newPlayersOnline = getPlayersOnline(); | |||||
| if(newPlayersOnline == lastPlayersOnline) return; | |||||
| else lastPlayersOnline = newPlayersOnline; | |||||
| EmbedBuilder eb = new EmbedBuilder(); | |||||
| eb.setTitle("Status"); | |||||
| eb.addField("Minecraft-Server, Spieler online: ", Integer.toString(lastPlayersOnline), false); | |||||
| statusChannel.editMessageById(Resources.getStatus_message(), eb.build()).queue(); | |||||
| } | |||||
| private static int getPlayersOnline() throws IOException { | |||||
| Socket socket = null; | |||||
| DataOutputStream out = null; | |||||
| DataInputStream in = null; | |||||
| try { | |||||
| socket = new Socket(Resources.getMc_server(), 25565); | |||||
| out = new DataOutputStream(socket.getOutputStream()); | |||||
| in = new DataInputStream(socket.getInputStream()); | |||||
| } catch (UnknownHostException e) { | |||||
| System.err.println("Don't know about host: " + Resources.getMc_server()); | |||||
| } catch (IOException e) { | |||||
| System.err.println("Couldn't get I/O for " + "the connection to:" + Resources.getMc_server()); | |||||
| } | |||||
| out.write(0xFE); | |||||
| byte[] b = new byte[241]; | |||||
| in.read(b, 0, 241); | |||||
| StringBuffer buffer = new StringBuffer(); | |||||
| for (int i = 4; i < b.length; i++) { | |||||
| if (b[i] != 0) { | |||||
| buffer.append((char) b[i]); | |||||
| } | |||||
| } | |||||
| String[] split = buffer.toString().split(String.valueOf((char) -89)); | |||||
| out.close(); | |||||
| in.close(); | |||||
| socket.close(); | |||||
| return Integer.parseInt(split[1]); | |||||
| } | |||||
| private static final ScheduledExecutorService statusScheduler = Executors.newScheduledThreadPool(1); | |||||
| private int lastPlayersOnline = -1; | |||||
| private final String message_id; | |||||
| private final int serverPort; | |||||
| private final String desc; | |||||
| private LocalDateTime timestampLastPlayerOnline = null; | |||||
| private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss E, dd.MM.yyyy", | |||||
| Locale.GERMANY); | |||||
| private final ProcessBuilder mcstatus = new ProcessBuilder(); | |||||
| public StatusProvider(String desc, String messageId, Guild guild, int secondsPerTime, int serverPort) { | |||||
| this.desc = desc; | |||||
| this.message_id = messageId; | |||||
| this.serverPort = serverPort; | |||||
| this.mcstatus.command(Resources.getPath_to_mcstatus(), Resources.getMc_server() + ":" + serverPort, "json"); | |||||
| TextChannel statusChannel = guild.getTextChannelById(Resources.getStatus_channel()); | |||||
| statusScheduler.scheduleAtFixedRate(() -> updateStatusMessage(statusChannel), 0, secondsPerTime, | |||||
| TimeUnit.SECONDS); | |||||
| } | |||||
| @SuppressWarnings("unchecked") | |||||
| @SneakyThrows | |||||
| public void updateStatusMessage(TextChannel statusChannel) { | |||||
| Map<String, Object> serverInfo = getPlayersOnline(); | |||||
| 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; | |||||
| } | |||||
| EmbedBuilder eb = new EmbedBuilder(); | |||||
| eb.setTitle(desc); | |||||
| eb.addField("IP", Resources.getMc_server() + ":" + serverPort, false); | |||||
| 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:", String.join(", ", (List<String>) serverInfo.get("playerNames")), false); | |||||
| } | |||||
| statusChannel.editMessageById(this.message_id, "Serverinformation").queue(); | |||||
| statusChannel.editMessageById(this.message_id, eb.build()).queue(); | |||||
| } | |||||
| private Map<String, Object> getPlayersOnline() throws IOException { | |||||
| Process process = mcstatus.start(); | |||||
| String output = new BufferedReader(new InputStreamReader(process.getInputStream())).lines().collect( | |||||
| Collectors.joining()); | |||||
| Map<String, Object> result = new HashMap<>(); | |||||
| JSONObject obj = new JSONObject(output); | |||||
| result.put("playerCount", obj.get("player_count")); | |||||
| result.put("playerMax", obj.get("player_max")); | |||||
| result.put("playerNames", | |||||
| StreamSupport.stream(obj.getJSONArray("players").spliterator(), false) | |||||
| .map(jsonobj -> ((JSONObject) jsonobj).getString("name")).sorted().collect( | |||||
| Collectors.toList())); | |||||
| return result; | |||||
| } | |||||
| } | } | ||||