From 0c1aaecc7337d5aa0dcd8d20f1ede1c2cdd9e845 Mon Sep 17 00:00:00 2001
From: Stalitsa <40505549+Stalitsa@users.noreply.github.com>
Date: Sat, 2 Oct 2021 20:41:04 +0100
Subject: [PATCH] Update JDA version.

Added TopCommand.

Remove invalid properties from discord to avoid confusion.
---
 .../custom/service/discord/DiscordBot.java    |   2 +
 .../service/discord/commands/TopCommand.java  | 275 ++++++++++++++++++
 2 files changed, 277 insertions(+)
 create mode 100644 src/main/java/com/l2jserver/datapack/custom/service/discord/commands/TopCommand.java

diff --git a/src/main/java/com/l2jserver/datapack/custom/service/discord/DiscordBot.java b/src/main/java/com/l2jserver/datapack/custom/service/discord/DiscordBot.java
index 479bc2f13f..d71d7a8129 100644
--- a/src/main/java/com/l2jserver/datapack/custom/service/discord/DiscordBot.java
+++ b/src/main/java/com/l2jserver/datapack/custom/service/discord/DiscordBot.java
@@ -19,6 +19,7 @@
 package com.l2jserver.datapack.custom.service.discord;
 
 import com.l2jserver.datapack.custom.service.discord.commands.OnlineCommand;
+import com.l2jserver.datapack.custom.service.discord.commands.TopCommand;
 import com.l2jserver.datapack.custom.service.discord.commands.moderation.AbortCommand;
 import com.l2jserver.datapack.custom.service.discord.commands.moderation.AnnounceCommand;
 import com.l2jserver.datapack.custom.service.discord.commands.moderation.RestartCommand;
@@ -57,6 +58,7 @@ public class DiscordBot {
 		new AbortCommand(),
 		new AnnounceCommand(),
 		new OnlineCommand(),
+		new TopCommand(),
 		new RestartCommand(),
 		new ShutdownCommand(),
 		new ChatListener(),
diff --git a/src/main/java/com/l2jserver/datapack/custom/service/discord/commands/TopCommand.java b/src/main/java/com/l2jserver/datapack/custom/service/discord/commands/TopCommand.java
new file mode 100644
index 0000000000..e7ca68bec1
--- /dev/null
+++ b/src/main/java/com/l2jserver/datapack/custom/service/discord/commands/TopCommand.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright © 2004-2021 L2J DataPack
+ *
+ * This file is part of L2J DataPack.
+ *
+ * L2J DataPack is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * L2J DataPack is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.datapack.custom.service.discord.commands;
+
+import com.l2jserver.commons.database.ConnectionFactory;
+import com.l2jserver.datapack.custom.service.discord.AbstractCommand;
+import com.l2jserver.gameserver.data.sql.impl.ClanTable;
+import com.l2jserver.gameserver.instancemanager.CastleManager;
+import com.l2jserver.gameserver.model.L2Clan;
+import com.l2jserver.gameserver.model.L2World;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.entity.Castle;
+import java.awt.*;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.text.DecimalFormat;
+import java.util.List;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import net.dv8tion.jda.api.EmbedBuilder;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.ReadyEvent;
+import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
+
+import static com.l2jserver.gameserver.config.Configuration.discord;
+
+/**
+ * Top Command.
+ * @author Stalitsa
+ * @version 2.6.3.0
+ */
+public class TopCommand extends AbstractCommand {
+	private static final String NoClansMsg = "This server does not have any clans yet";
+	private static final String NoPlayersMsg = "This server does not have any players yet";
+	private static final DecimalFormat DECIMAL_FORMATTER = new DecimalFormat("#,###");
+
+	/**
+	 * When the choice is players these are the parameters that the user can specify to get the info for.
+	 */
+	private final String[] params = {
+		"pvp",
+		"pk",
+		"adena",
+		"online"
+	};
+
+	/**
+	 * The choice of information that the user wants to see.
+	 */
+	private final String[] choice = {
+		"players",
+		"clans"
+	};
+
+	private static final String[] COMMANDS = {
+		"top",
+		"tp"
+	};
+
+	@Override
+	public String[] getCommands() {
+		return COMMANDS;
+	}
+
+	@Override
+	public void executeCommand(MessageReceivedEvent event, String[] args) {
+		EmbedBuilder eb = new EmbedBuilder().setColor(Color.ORANGE);
+		if (args.length == 1 || !Arrays.asList(choice).contains(args[1])) {
+			eb.setColor(Color.RED).setDescription("Wrong Arguments.");
+			eb.addField(discord().getPrefix() + " " + String.join(", ", getCommands()) + " <choice>", "Choice: \n```css\n" + String.join(", ", choice) + "```", false);
+			event.getTextChannel().sendMessageEmbeds(eb.build()).queue(message -> message.delete().queueAfter(30, TimeUnit.SECONDS));
+			event.getMessage().addReaction("\u274C").queue();
+			return;
+		}
+
+		switch (args[1]) {
+			case "players" -> {
+				if (args.length == 2 || args.length > 3 || !Arrays.asList(params).contains(args[2])) {
+					eb.setColor(Color.RED).setDescription("Wrong Arguments.");
+					eb.addField("Example:", discord().getPrefix() + " top players \nParams: \n```css\n" + String.join(", ", params) + "```", false);
+					event.getTextChannel().sendMessageEmbeds(eb.build()).queue(message -> message.delete().queueAfter(30, TimeUnit.SECONDS));
+					event.getMessage().addReaction("\u274C").queue();
+					return;
+				}
+				eb.setDescription("***___TOP 10 " + args[2].toUpperCase() + " PLAYERS___***");
+				int count = 0;
+				switch (args[2]) {
+					case "pvp" -> {
+						List<PlayerHolder> topPvP = getAllPlayers().stream().sorted(Comparator.comparing(PlayerHolder::getPvps).reversed()).collect(Collectors.toList());
+						for (PlayerHolder pl : topPvP) {
+							int level = pl.getLevel();
+							String playerName = pl.getName();
+							String msg = "`\n***Level:*** `" + level + "`\n***PvP:*** `" + pl.getPvps() + "`\n***Pk:*** `" + pl.getPks() + "`";
+							if (count < 10) {
+								count++;
+								eb.addField(count + ". " + playerName, msg, true);
+							}
+						}
+					}
+					case "pk" -> {
+						List<PlayerHolder> topPk = getAllPlayers().stream().sorted(Comparator.comparing(PlayerHolder::getPks).reversed()).collect(Collectors.toList());
+						for (PlayerHolder pl : topPk) {
+							int level = pl.getLevel();
+							String playerName = pl.getName();
+							String msg = "`\n***Level:*** `" + level + "`\n***PvP:*** `" + pl.getPvps() + "`\n***Pk:*** `" + pl.getPks() + "`";
+							if (count < 10) {
+								count++;
+								eb.addField(count + ". " + playerName, msg, true);
+							}
+						}
+					}
+					case "online" -> {
+						List<PlayerHolder> topOnlineTime = getAllPlayers().stream().sorted(Comparator.comparing(PlayerHolder::getOnlineTime).reversed()).collect(Collectors.toList());
+						for (PlayerHolder pl : topOnlineTime) {
+							int level = pl.getLevel();
+							String playerName = pl.getName();
+							String msg = "`\n***Level:*** `" + level + "`\n***PvP:*** `" + pl.getPvps() + "`\n***Pk:*** `" + pl.getPks() + "`\n***Online:*** `" + pl.getOnlineTime() + "`";
+							if (count < 10) {
+								count++;
+								eb.addField(count + ". " + playerName, msg, true);
+							}
+						}
+					}
+					case "adena" -> {
+						List<PlayerHolder> topAdena = getAllPlayers().stream().sorted(Comparator.comparing(PlayerHolder::getAdena).reversed()).collect(Collectors.toList());
+						for (PlayerHolder pl : topAdena) {
+							String adena = DECIMAL_FORMATTER.format(pl.getAdena());
+							int level = pl.getLevel();
+							String playerName = pl.getName();
+							String msg = "`\n***Level:*** `" + level + "`\n***PvP:*** `" + pl.getPvps() + "`\n***Pk:*** `" + pl.getPks() + "`\n***Online:*** `" + pl.getOnlineTime() + "`\n***Adena:*** `" + adena + "` ";
+							if (count < 10) {
+								count++;
+								eb.addField(count + ". " + playerName, msg, true);
+							}
+						}
+					}
+				}
+				if (getAllPlayers().isEmpty()) {
+					eb.addField("No Players", NoPlayersMsg, true);
+				} else {
+					eb.setFooter("Total Players: " + getAllPlayers().size(), event.getGuild().getIconUrl());
+				}
+				eb.setThumbnail(event.getGuild().getIconUrl());
+				event.getMessage().addReaction("\u2705").queue();
+				event.getChannel().sendMessageEmbeds(eb.build()).queue(message -> message.delete().queueAfter(60, TimeUnit.SECONDS));
+			}
+			case "clans" -> {
+				if (args.length > 2) {
+					eb.setColor(Color.RED).setDescription("Wrong Arguments.");
+					eb.addField(discord().getPrefix() + " " + String.join(", ", getCommands()) + " <choice>", "Choice: \n```css\n" + String.join(", ", choice) + "```", false);
+					event.getTextChannel().sendMessageEmbeds(eb.build()).queue(message -> message.delete().queueAfter(30, TimeUnit.SECONDS));
+					event.getMessage().addReaction("\u274C").queue();
+					return;
+				}
+				eb.setDescription("***___TOP 10 CLANS___***");
+				List<L2Clan> clans = ClanTable.getInstance().getClans().stream().sorted(Comparator.comparing(L2Clan::getLevel).reversed()).collect(Collectors.toList());
+				int count = 0;
+				for (L2Clan clan : clans) {
+					int clanID = clan.getId();
+					int clanLevel = clan.getLevel();
+					String reputation = DECIMAL_FORMATTER.format(clan.getReputationScore());
+					String castleName = "[No-Castle]";
+					String allyStatus = "[No-ally]";
+					String clanName = clan.getName();
+					String allyName = clan.getAllyId() > 0 ? clan.getAllyName() : "[No-ally]";
+					String leaderName = clan.getLeaderName();
+					for (Castle castle : CastleManager.getInstance().getCastles()) {
+						if (castle.getOwnerId() == clan.getId()) {
+							castleName = castle.getName();
+						}
+					}
+					if (clan.getAllyId() != 0) {
+						allyStatus = clan.getAllyId() == clanID ? "Alliance Leader" : "Affiliated Clan";
+					}
+					String msg = "***Leader:*** `" + leaderName + "`\n***Clan Level:*** `" + clanLevel + "`\n***Reputation:*** `" + reputation + "`\n***Castle:*** `" + castleName + "`\n***Ally Name:*** `" + allyName + "`\n***Ally Status:*** `" + allyStatus + "` " + "\n***Clan Wars:*** `" + clan.getWarList().size() + "`";
+					if (count < 10) {
+						count++;
+						eb.addField(clanName, msg, true);
+					}
+				}
+				if (clans.isEmpty()) {
+					eb.addField("No Clans", NoClansMsg, true);
+				} else {
+					eb.setFooter("Total Clans: " + ClanTable.getInstance().getClans().size(), event.getGuild().getIconUrl());
+				}
+				eb.setThumbnail(event.getGuild().getIconUrl());
+				event.getMessage().addReaction("\u2705").queue();
+				event.getChannel().sendMessageEmbeds(eb.build()).queue(message -> message.delete().queueAfter(60, TimeUnit.SECONDS));
+			}
+		}
+	}
+
+	/**
+	 * We had to do a sql query to get all players online and offline.
+	 * We could use {L2World.getInstance().getPlayers();} but it only returns the online players.
+	 */
+	private List<PlayerHolder> getAllPlayers() {
+		List<PlayerHolder> players = new ArrayList<>();
+		try (Connection con = ConnectionFactory.getInstance().getConnection()) {
+			String selectPlayers = "SELECT char_name, pvpkills, pkkills, onlinetime, level, items.item_id, items.count FROM characters INNER JOIN items ON items.owner_id = characters.charId WHERE characters.accesslevel = 0 AND items.item_id=57";
+			try (PreparedStatement st = con.prepareStatement(selectPlayers)) {
+				ResultSet rs = st.executeQuery();
+				while (rs.next()) {
+					PlayerHolder p = new PlayerHolder();
+					p.adena = rs.getInt("count");
+					p.pks = rs.getInt("pkkills");
+					p.pvps = rs.getInt("pvpkills");
+					p.name = rs.getString("char_name");
+					p.onlineTime = rs.getInt("onlinetime");
+					p.level = rs.getInt("level");
+					players.add(p);
+				}
+			}
+		} catch (SQLException e) {
+			e.printStackTrace();
+		}
+		return players;
+	}
+
+	/**
+	 * A data holder for the sql query above. We store the info that we need to show on the top list.
+	 */
+	private static class PlayerHolder {
+		public String getName() {
+			return name;
+		}
+
+		public int getPvps() {
+			return pvps;
+		}
+
+		public int getPks() {
+			return pks;
+		}
+
+		public int getAdena() {
+			return adena;
+		}
+
+		public int getOnlineTime() {
+			return onlineTime;
+		}
+
+		public int getLevel() {
+			return level;
+		}
+
+		String name;
+		int pvps;
+		int pks;
+		int adena;
+		int onlineTime;
+		int level;
+	}
+}
-- 
GitLab