| @ -1,80 +1,103 @@ | |||
| package de.yannicpunktdee.yoshibot.utils; | |||
| import lombok.SneakyThrows; | |||
| import net.dv8tion.jda.api.EmbedBuilder; | |||
| import net.dv8tion.jda.api.entities.Guild; | |||
| 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.UnknownHostException; | |||
| import java.time.LocalDateTime; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.*; | |||
| import java.util.concurrent.Executors; | |||
| import java.util.concurrent.ScheduledExecutorService; | |||
| import java.util.concurrent.TimeUnit; | |||
| import java.util.stream.Collectors; | |||
| import java.util.stream.StreamSupport; | |||
| 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; | |||
| } | |||
| } | |||