diff --git a/Plugins/Mineplex.Cache/src/mineplex/cache/player/PlayerCache.java b/Plugins/Mineplex.Cache/src/mineplex/cache/player/PlayerCache.java index 2409e3be7..e269478b6 100644 --- a/Plugins/Mineplex.Cache/src/mineplex/cache/player/PlayerCache.java +++ b/Plugins/Mineplex.Cache/src/mineplex/cache/player/PlayerCache.java @@ -1,6 +1,7 @@ package mineplex.cache.player; import java.util.UUID; +import java.util.concurrent.TimeUnit; import mineplex.serverdata.Region; import mineplex.serverdata.redis.RedisDataRepository; @@ -32,7 +33,8 @@ public enum PlayerCache ServerManager.getMasterConnection(), ServerManager.getSlaveConnection(), Region.ALL, - "accountid" + "accountid", + (int) TimeUnit.HOURS.toSeconds(6) ); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/disguise/playerdisguise/PlayerDisguiseManager.java b/Plugins/Mineplex.Core/src/mineplex/core/disguise/playerdisguise/PlayerDisguiseManager.java index fd1b44c80..60729ef22 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/disguise/playerdisguise/PlayerDisguiseManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/disguise/playerdisguise/PlayerDisguiseManager.java @@ -462,99 +462,92 @@ public class PlayerDisguiseManager extends MiniPlugin implements IPacketHandler if (!requestedUsername.equalsIgnoreCase(caller.getName())) { - Rank otherRank = Rank.ALL; - CoreClient other = new CoreClient(requestedUsername, requestedProfile.getId()); - try + getClientManager().getOrLoadClient(requestedUsername, other -> { - getClientManager().LoadClient(other, requestedProfile.getId(), caller.getAddress().getAddress().getHostAddress()); - otherRank = other.GetRank(); - } - catch (NullPointerException exception) - { - other = null; - } + Rank otherRank = other != null ? other.GetRank() : Rank.ALL; - if (otherRank.has(Rank.TWITCH)) - { - UtilPlayer.message(caller, F.main("Disguise", "You can't disguise as staff, YouTubers or Twitchers!")); - return; - } - - if (other != null) - { - PunishClient pclient = getPunishManager().GetClient(requestedUsername); - if (pclient != null && (pclient.IsBanned() || pclient.IsMuted())) + if (otherRank.has(Rank.TWITCH)) { - UtilPlayer.message(caller, F.main("Disguise", "You can't disguise as players who are banned/muted!")); + UtilPlayer.message(caller, F.main("Disguise", "You can't disguise as staff, YouTubers or Twitchers!")); return; } - } - callerClient.disguise(requestedUsername, requestedProfile.getId(), otherRank); - - _mapping.put(callerClient.getDisguisedAs().toLowerCase(), callerClient.getName()); - - System.out.println("================="); - System.out.println("Disguising " + caller.getName() + " as:"); - System.out.println(requestedProfile.getName() + " id " + requestedProfile.getId()); - System.out.println("Properties:"); - for (Map.Entry p : requestedProfile.getProperties().entries()) - { - System.out.println("\t" + p.getKey() + " " + p.getValue().getName()); - System.out.println("\t" + p.getValue().getValue()); - System.out.println("\t" + p.getValue().getSignature()); - } - System.out.println("================="); - - DisguisePlayer disguisePlayer = new DisguisePlayer(caller, requestedProfile); - disguisePlayer.showInTabList(true, 0); - allow(caller); - getDisguiseManager().disguise(disguisePlayer, () -> - { - GameProfile callerProfile = ((CraftPlayer) caller).getProfile(); - - require(ScoreboardManager.class).handlePlayerQuit(disguisePlayer.getOriginalProfile().getName()); - - try + if (other != null) { - UtilGameProfile.changeName(callerProfile, disguisePlayer.getProfile().getName()); - UtilGameProfile.changeId(callerProfile, disguisePlayer.getProfile().getId()); - - Field playersByName = PlayerList.class.getDeclaredField("playersByName"); - playersByName.setAccessible(true); - Map map = (Map) playersByName.get(MinecraftServer.getServer().getPlayerList()); - map.remove(disguisePlayer.getOriginalProfile().getName()); - map.put(disguisePlayer.getProfile().getName(), disguisePlayer.getEntity()); - } - catch (Throwable t) - { - t.printStackTrace(); + PunishClient pclient = getPunishManager().GetClient(requestedUsername); + if (pclient != null && (pclient.IsBanned() || pclient.IsMuted())) + { + UtilPlayer.message(caller, F.main("Disguise", "You can't disguise as players who are banned/muted!")); + return; + } } - require(ScoreboardManager.class).handlePlayerJoin(disguisePlayer.getName()); + callerClient.disguise(requestedUsername, requestedProfile.getId(), otherRank); - callerProfile.getProperties().clear(); - callerProfile.getProperties().putAll(disguisePlayer.getProfile().getProperties()); + _mapping.put(callerClient.getDisguisedAs().toLowerCase(), callerClient.getName()); - callerProfile.getProperties().removeAll(ORIGINAL_UUID_KEY); - callerProfile.getProperties().put(ORIGINAL_UUID_KEY, new Property(ORIGINAL_UUID_KEY, caller.getUniqueId().toString())); + System.out.println("================="); + System.out.println("Disguising " + caller.getName() + " as:"); + System.out.println(requestedProfile.getName() + " id " + requestedProfile.getId()); + System.out.println("Properties:"); + for (Map.Entry p : requestedProfile.getProperties().entries()) + { + System.out.println("\t" + p.getKey() + " " + p.getValue().getName()); + System.out.println("\t" + p.getValue().getValue()); + System.out.println("\t" + p.getValue().getSignature()); + } + System.out.println("================="); - require(FriendManager.class).updatePlayerStatus(disguisePlayer.getOriginalProfile().getId(), null); - require(FriendManager.class).updatePlayerStatus(disguisePlayer.getProfile().getId(), new PlayerStatus(disguisePlayer.getProfile().getId(), requestedUsername, _serverName)); + DisguisePlayer disguisePlayer = new DisguisePlayer(caller, requestedProfile); + disguisePlayer.showInTabList(true, 0); + allow(caller); + getDisguiseManager().disguise(disguisePlayer, () -> + { + GameProfile callerProfile = ((CraftPlayer) caller).getProfile(); - getPreferencesManager().handlePlayerJoin(caller, true); + require(ScoreboardManager.class).handlePlayerQuit(disguisePlayer.getOriginalProfile().getName()); - _disguises.put(caller.getUniqueId(), disguisePlayer); + try + { + UtilGameProfile.changeName(callerProfile, disguisePlayer.getProfile().getName()); + UtilGameProfile.changeId(callerProfile, disguisePlayer.getProfile().getId()); - UtilPlayer.message(caller, F.main("Disguise", "Disguise Active: " + ChatColor.RESET + requestedUsername)); + Field playersByName = PlayerList.class.getDeclaredField("playersByName"); + playersByName.setAccessible(true); + Map map = (Map) playersByName.get(MinecraftServer.getServer().getPlayerList()); + map.remove(disguisePlayer.getOriginalProfile().getName()); + map.put(disguisePlayer.getProfile().getName(), disguisePlayer.getEntity()); + } + catch (Throwable t) + { + t.printStackTrace(); + } - UtilServer.CallEvent(new PlayerDisguisedEvent(caller)); + require(ScoreboardManager.class).handlePlayerJoin(disguisePlayer.getName()); - storeDisguiseData(caller, requestedUsername, requestedProfile); + callerProfile.getProperties().clear(); + callerProfile.getProperties().putAll(disguisePlayer.getProfile().getProperties()); - _pendingDisguise.remove(requestedUsername.toLowerCase()); + callerProfile.getProperties().removeAll(ORIGINAL_UUID_KEY); + callerProfile.getProperties().put(ORIGINAL_UUID_KEY, new Property(ORIGINAL_UUID_KEY, caller.getUniqueId().toString())); - _cannotJoin.remove(requestedUsername.toLowerCase()); + require(FriendManager.class).updatePlayerStatus(disguisePlayer.getOriginalProfile().getId(), null); + require(FriendManager.class).updatePlayerStatus(disguisePlayer.getProfile().getId(), new PlayerStatus(disguisePlayer.getProfile().getId(), requestedUsername, _serverName)); + + getPreferencesManager().handlePlayerJoin(caller, true); + + _disguises.put(caller.getUniqueId(), disguisePlayer); + + UtilPlayer.message(caller, F.main("Disguise", "Disguise Active: " + ChatColor.RESET + requestedUsername)); + + UtilServer.CallEvent(new PlayerDisguisedEvent(caller)); + + storeDisguiseData(caller, requestedUsername, requestedProfile); + + _pendingDisguise.remove(requestedUsername.toLowerCase()); + + _cannotJoin.remove(requestedUsername.toLowerCase()); + }); }); } else diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/outfit/OutfitTeam.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/outfit/OutfitTeam.java index 0004420cd..bcda0800d 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/outfit/OutfitTeam.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/outfit/OutfitTeam.java @@ -109,7 +109,7 @@ public class OutfitTeam extends OutfitGadget Player player = event.getPlayer(); - if (!event.getMessage().toLowerCase().startsWith("/team")) + if (!event.getMessage().toLowerCase().startsWith("/team ")) return; event.setCancelled(true); diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakClientInfo.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakClientInfo.java new file mode 100644 index 000000000..95a8b483d --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakClientInfo.java @@ -0,0 +1,31 @@ +package mineplex.core.teamspeak; + +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class TeamspeakClientInfo +{ + private Map _linkedAccounts = new HashMap<>(); + + public TeamspeakClientInfo(Map linkedAccounts) + { + _linkedAccounts = new HashMap<>(linkedAccounts); + } + + public Map getLinkedAccounts() + { + return Collections.unmodifiableMap(_linkedAccounts); + } + + public void unlink(int account) + { + _linkedAccounts.remove(account); + } + + public void link(int id, Date now) + { + _linkedAccounts.put(id, now); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakManager.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakManager.java new file mode 100644 index 000000000..17016e6a1 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakManager.java @@ -0,0 +1,429 @@ +package mineplex.core.teamspeak; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.scheduler.BukkitTask; + +import com.google.common.primitives.Ints; + +import mineplex.core.MiniClientPlugin; +import mineplex.core.ReflectivelyCreateMiniPlugin; +import mineplex.core.account.CoreClient; +import mineplex.core.account.CoreClientManager; +import mineplex.core.account.ILoginProcessor; +import mineplex.core.bonuses.BonusManager; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.teamspeak.commands.TeamspeakCommand; +import mineplex.core.teamspeak.redis.TeamspeakLinkRequest; +import mineplex.core.teamspeak.redis.TeamspeakLinkResponse; +import mineplex.core.teamspeak.redis.TeamspeakUnlinkRequest; +import mineplex.core.teamspeak.redis.TeamspeakUnlinkResponse; +import mineplex.core.teamspeak.redis.TeamspeakUpdateRequest; +import mineplex.serverdata.Region; +import mineplex.serverdata.commands.ServerCommandManager; +import mineplex.serverdata.redis.atomic.RedisStringRepository; +import mineplex.serverdata.servers.ServerManager; + +@ReflectivelyCreateMiniPlugin +public class TeamspeakManager extends MiniClientPlugin implements ILoginProcessor +{ + public static final String TEAMSPEAK_CHANNEL_NAME = "Teamspeak Rank Channel"; + + public static final int MAX_LINKED_ACCOUNTS = 5; + public static final int DELAY_BEFORE_UPDATE = (int) 0; //TimeUnit.DAYS.toMillis(1); + + private final CoreClientManager _clientManager = require(CoreClientManager.class); + private final BonusManager _bonusManager = require(BonusManager.class); + private final TeamspeakRepository _repository = new TeamspeakRepository(); + + private final RedisStringRepository _updateRepository = new RedisStringRepository( + ServerManager.getMasterConnection(), + ServerManager.getSlaveConnection(), + Region.ALL, + "teamspeakUpdates", + (int) TimeUnit.DAYS.toSeconds(10) + ); + + private final Map _requestMap = new HashMap<>(); + + private TeamspeakManager() + { + super("TeamSpeak Manager"); + + ServerCommandManager.getInstance().registerCommandType(TeamspeakLinkResponse.class, response -> + { + BukkitTask task = _requestMap.remove(response.getRequest().getCommandId()); + + if (task == null) + return; + + task.cancel(); + + Player sender = Bukkit.getPlayer(response.getRequest().getCaller()); + + if (sender == null) + return; + + switch (response.getResponse()) + { + case TOKEN_VALID: + Date now = new Date(); + Get(sender).link(response.getId(), now); + runAsync(() -> + { + _repository.save(_clientManager.getAccountId(sender), response.getId(), now); + }); + + UtilPlayer.message(sender, F.main("Teamspeak", "Congrats! You've successfully linked your Teamspeak account!")); + break; + case TOKEN_INVALID: + UtilPlayer.message(sender, F.main("Teamspeak", "Uh oh! That's not the token you were given!")); + break; + } + }); + + ServerCommandManager.getInstance().registerCommandType(TeamspeakUnlinkResponse.class, response -> + { + BukkitTask task = _requestMap.remove(response.getRequest().getCommandId()); + + if (task == null) + return; + + task.cancel(); + + Player sender = Bukkit.getPlayer(response.getRequest().getCaller()); + + if (sender == null) + return; + + switch (response.getResponse()) + { + case UNLINKED: + Get(sender).unlink(response.getRequest().getId()); + runAsync(() -> + { + _repository.delete(_clientManager.getAccountId(sender), response.getRequest().getId()); + }); + + UtilPlayer.message(sender, F.main("Teamspeak", "You've unlinked your Teamspeak account!")); + break; + } + }); + + _clientManager.addStoredProcedureLoginProcessor(this); + } + + @Override + public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException + { + Map dates = new HashMap<>(); + + while (resultSet.next()) + { + int teamspeakId = resultSet.getInt("teamspeakId"); + Date linkDate = resultSet.getDate("linkDate"); + + dates.put(teamspeakId, linkDate); + } + + Set(uuid, new TeamspeakClientInfo(dates)); + } + + @EventHandler + public void onLogin(PlayerJoinEvent event) + { + if (Get(event.getPlayer()).getLinkedAccounts().size() == 0) + return; + + runAsync(() -> + { + String lastLoginString = _updateRepository.get(event.getPlayer().getUniqueId().toString()); + long lastLogin; + try + { + lastLogin = lastLoginString == null ? 0 : Long.parseLong(lastLoginString); + } + catch (NumberFormatException ex) + { + lastLogin = 0; + } + + if (System.currentTimeMillis() - lastLogin > DELAY_BEFORE_UPDATE) + { + _updateRepository.set(event.getPlayer().getUniqueId().toString(), String.valueOf(System.currentTimeMillis())); + + new TeamspeakUpdateRequest( + event.getPlayer().getUniqueId(), + Ints.toArray(Get(event.getPlayer()).getLinkedAccounts().keySet()), + _clientManager.Get(event.getPlayer()).GetRank().name(), + _bonusManager.getPowerPlayClubRepository().getCachedData(event.getPlayer()).isSubscribed() + ).publish(); + } + }); + } + + @Override + public String getQuery(int accountId, String uuid, String name) + { + return String.format(TeamspeakRepository.GET_ALL_PLAYER_IDS, accountId); + } + + @Override + protected TeamspeakClientInfo addPlayer(UUID uuid) + { + return new TeamspeakClientInfo(Collections.emptyMap()); + } + + public void link(Player caller, String token) + { + if (_requestMap.containsKey(caller.getUniqueId())) + { + UtilPlayer.message(caller, F.main("Teamspeak", "Please wait until your current request has been processed")); + return; + } + + TeamspeakClientInfo info = Get(caller); + + if (info.getLinkedAccounts().size() >= MAX_LINKED_ACCOUNTS) + { + UtilPlayer.message(caller, F.main("Teamspeak", "You have too many linked accounts! Please unlink one using /teamspeak unlink")); + return; + } + + CoreClient client = _clientManager.Get(caller); + + UtilPlayer.message(caller, F.main("Teamspeak", "Linking your account...")); + + TeamspeakLinkRequest linkRequest = new TeamspeakLinkRequest( + caller.getUniqueId(), + client.GetRank().name(), + _bonusManager.getPowerPlayClubRepository().getCachedData(caller).isSubscribed(), + token + ); + linkRequest.publish(); + + _requestMap.put(linkRequest.getCommandId(), runSyncLater(() -> + { + if (!caller.isOnline()) + return; + + UtilPlayer.message(caller, F.main("Teamspeak", "It seems something has gone wrong - your request couldn't be processed")); + + _requestMap.remove(linkRequest.getCommandId()); + }, 20L * 5)); + } + + public void unlink(Player caller, String arg) + { + int id; + try + { + id = Integer.parseInt(arg); + } + catch (NumberFormatException ex) + { + UtilPlayer.message(caller, F.main("Teamspeak", F.elem(arg) + " is not a number")); + return; + } + + if (_requestMap.containsKey(caller.getUniqueId())) + { + UtilPlayer.message(caller, F.main("Teamspeak", "Please wait until your current request has been processed")); + return; + } + + TeamspeakClientInfo info = Get(caller); + + if (!info.getLinkedAccounts().containsKey(id)) + { + UtilPlayer.message(caller, F.main("Teamspeak", "You have not linked to that account")); + return; + } + + UtilPlayer.message(caller, F.main("Teamspeak", "Unlinking your account...")); + + TeamspeakUnlinkRequest unlinkRequest = new TeamspeakUnlinkRequest( + caller.getUniqueId(), + id + ); + unlinkRequest.publish(); + + _requestMap.put(unlinkRequest.getCommandId(), runSyncLater(() -> + { + if (!caller.isOnline()) + return; + + UtilPlayer.message(caller, F.main("Teamspeak", "It seems something has gone wrong - your request couldn't be processed")); + + _requestMap.remove(unlinkRequest.getCommandId()); + }, 20L * 5)); + } + + @Override + public void addCommands() + { + addCommand(new TeamspeakCommand(this)); + } + + public void displayUnlinkPrompt(Player caller, String strPage) + { + TeamspeakClientInfo info = Get(caller); + + List> linkedAccounts = new ArrayList<>(info.getLinkedAccounts().entrySet()); + + if (linkedAccounts.size() == 0) + { + UtilPlayer.message(caller, F.main("Teamspeak", "You have no linked Teamspeak accounts!")); + return; + } + + int totalPages = (int) Math.ceil(linkedAccounts.size() / 8.0); + int page; + + try + { + page = Integer.parseInt(strPage); + } + catch (NumberFormatException ex) + { + UtilPlayer.message(caller, F.main("Teamspeak", F.elem(strPage) + " is not a number!")); + return; + } + page = page - 1; + + if (page < 0) + { + UtilPlayer.message(caller, F.main("Teamspeak", "Page numbers must be greater than zero!")); + return; + } + else if (page >= totalPages) + { + UtilPlayer.message(caller, F.main("Teamspeak", "You only have " + F.elem(totalPages) + " pages of linked accounts, that number is too big!")); + return; + } + + String header = "[" + + ChatColor.RESET + C.cWhite + C.Bold + "Teamspeak Accounts (" + (page + 1) + "/" + totalPages + ")" + + ChatColor.RESET + C.cAqua + C.Strike + "]"; + + int headerChars = ChatColor.stripColor(header).length(); + + int numEqualsInHeader = (50 - headerChars) / 2; + header = C.cAqua + C.Strike + StringUtils.repeat("=", numEqualsInHeader) + header + StringUtils.repeat("=", numEqualsInHeader); + + caller.sendMessage(header); + + int start = page * 8; + + List> subList = start < linkedAccounts.size() ? linkedAccounts.subList(start, Math.min(linkedAccounts.size(), start + 8)) : Collections.emptyList(); + + for (Map.Entry data : subList) + { + BaseComponent[] hover = new ComponentBuilder("") + .append("ID: ") + .color(ChatColor.YELLOW) + .append(String.valueOf(data.getKey()), ComponentBuilder.FormatRetention.NONE) + .color(ChatColor.WHITE) + .create(); + + ComponentBuilder builder = new ComponentBuilder("") + .append("Unlink") + .color(ChatColor.RED) + .bold(true) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Click to unlink this account").color(ChatColor.RED).create())) + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/teamspeak unlink " + data.getKey())) + .append(" - ", ComponentBuilder.FormatRetention.NONE) + .color(ChatColor.WHITE) + .append("Account linked on " + UtilTime.date(data.getValue().getTime())) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hover)) + .color(ChatColor.GRAY); + + caller.spigot().sendMessage(builder.create()); + } + + int chars = ChatColor.stripColor(header).length(); + + int numEquals = (chars - 3) / 2; + + ComponentBuilder pageSwitch = new ComponentBuilder("") + .append(StringUtils.repeat("=", numEquals) + "[") + .strikethrough(true) + .color(ChatColor.AQUA) + .append(" ", ComponentBuilder.FormatRetention.NONE) + .append("<", ComponentBuilder.FormatRetention.NONE) + .bold(true); + + if (page > 0) + { + BaseComponent[] prev = new ComponentBuilder("") + .append("Go to page " + page) + .color(ChatColor.GREEN) + .create(); + + pageSwitch + .color(ChatColor.GREEN) + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/teamspeak list " + (page))) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, prev)); + + } + else + { + pageSwitch + .color(ChatColor.GRAY); + } + + pageSwitch.append(" ", ComponentBuilder.FormatRetention.NONE) + .append(">", ComponentBuilder.FormatRetention.NONE) + .bold(true); + + if (page + 1 < totalPages) + { + BaseComponent[] next = new ComponentBuilder("") + .append("Go to page " + (page + 2)) + .color(ChatColor.GREEN) + .create(); + + pageSwitch + .color(ChatColor.GREEN) + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/teamspeak list " + (page + 2))) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, next)); + + } + else + { + pageSwitch + .color(ChatColor.GRAY); + } + + pageSwitch + .append(" ", ComponentBuilder.FormatRetention.NONE) + .append("]" + StringUtils.repeat("=", numEquals), ComponentBuilder.FormatRetention.NONE) + .strikethrough(true) + .color(ChatColor.AQUA); + + caller.spigot().sendMessage(pageSwitch.create()); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakRepository.java new file mode 100644 index 000000000..afe63c069 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/TeamspeakRepository.java @@ -0,0 +1,57 @@ +package mineplex.core.teamspeak; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Date; + +import mineplex.serverdata.database.DBPool; +import mineplex.serverdata.database.RepositoryBase; + +@SuppressWarnings("WeakerAccess") +public class TeamspeakRepository extends RepositoryBase +{ + TeamspeakRepository() + { + super(DBPool.getAccount()); + } + + public static final String GET_ALL_PLAYER_IDS = "SELECT `teamspeakId`, `linkDate` FROM accountTeamspeak WHERE accountId = %s;"; + public static final String SAVE_PLAYER_ID = "INSERT INTO accountTeamspeak (accountId, teamspeakId, linkDate) VALUES (?, ?, ?);"; + public static final String DELETE_PLAYER_ID = "DELETE FROM accountTeamspeak WHERE accountId = ? AND teamspeakId = ?;"; + + public void save(int accountId, int id, Date now) + { + try (Connection connection = getConnection()) + { + try (PreparedStatement statement = connection.prepareStatement(SAVE_PLAYER_ID)) + { + statement.setInt(1, accountId); + statement.setInt(2, id); + statement.setDate(3, new java.sql.Date(now.getTime())); + statement.executeUpdate(); + } + } + catch (SQLException ex) + { + ex.printStackTrace(); + } + } + + public void delete(int accountId, int id) + { + try (Connection connection = getConnection()) + { + try (PreparedStatement statement = connection.prepareStatement(DELETE_PLAYER_ID)) + { + statement.setInt(1, accountId); + statement.setInt(2, id); + statement.executeUpdate(); + } + } + catch (SQLException ex) + { + ex.printStackTrace(); + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/LinkCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/LinkCommand.java new file mode 100644 index 000000000..22157fe0a --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/LinkCommand.java @@ -0,0 +1,29 @@ +package mineplex.core.teamspeak.commands; + +import org.bukkit.entity.Player; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.teamspeak.TeamspeakManager; + +public class LinkCommand extends CommandBase +{ + public LinkCommand(TeamspeakManager plugin) + { + super(plugin, Rank.ALL, "link"); + } + + @Override + public void Execute(Player caller, String[] args) + { + if (args.length == 0) + { + UtilPlayer.message(caller, F.main("Teamspeak", "No token specified. Join the " + F.elem(TeamspeakManager.TEAMSPEAK_CHANNEL_NAME) + " on Teamspeak and type !link to link an account")); + return; + } + + Plugin.link(caller, args[0]); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/ListCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/ListCommand.java new file mode 100644 index 000000000..18b4ebf56 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/ListCommand.java @@ -0,0 +1,23 @@ +package mineplex.core.teamspeak.commands; + +import org.bukkit.entity.Player; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.teamspeak.TeamspeakManager; + +public class ListCommand extends CommandBase +{ + public ListCommand(TeamspeakManager plugin) + { + super(plugin, Rank.ALL, "list"); + } + + @Override + public void Execute(Player caller, String[] args) + { + Plugin.displayUnlinkPrompt(caller, args.length == 0 ? "1" : args[0]); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/TeamspeakCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/TeamspeakCommand.java new file mode 100644 index 000000000..09e7c07ba --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/TeamspeakCommand.java @@ -0,0 +1,25 @@ +package mineplex.core.teamspeak.commands; + +import org.bukkit.entity.Player; + +import mineplex.core.command.MultiCommandBase; +import mineplex.core.common.Rank; +import mineplex.core.teamspeak.TeamspeakManager; + +public class TeamspeakCommand extends MultiCommandBase +{ + public TeamspeakCommand(TeamspeakManager plugin) + { + super(plugin, Rank.ALL, "teamspeak", "ts"); + + AddCommand(new LinkCommand(plugin)); + AddCommand(new ListCommand(plugin)); + AddCommand(new UnlinkCommand(plugin)); + } + + @Override + protected void Help(Player caller, String[] args) + { + + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/UnlinkCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/UnlinkCommand.java new file mode 100644 index 000000000..063b90a80 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/commands/UnlinkCommand.java @@ -0,0 +1,29 @@ +package mineplex.core.teamspeak.commands; + +import org.bukkit.entity.Player; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.teamspeak.TeamspeakManager; + +public class UnlinkCommand extends CommandBase +{ + public UnlinkCommand(TeamspeakManager plugin) + { + super(plugin, Rank.ALL, "unlink"); + } + + @Override + public void Execute(Player caller, String[] args) + { + if (args.length == 0) + { + UtilPlayer.message(caller, F.main("Teamspeak", "No account specified!")); + return; + } + + Plugin.unlink(caller, args[0]); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakLinkRequest.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakLinkRequest.java new file mode 100644 index 000000000..6a2ec2428 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakLinkRequest.java @@ -0,0 +1,27 @@ +package mineplex.core.teamspeak.redis; + +import java.util.UUID; + +import mineplex.serverdata.commands.ServerCommand; + +public class TeamspeakLinkRequest extends ServerCommand +{ + private final UUID _caller; + // Send all the metadata in case it's successful + private final String _callerRank; + private final boolean _powerPlay; + private final String _token; + + public TeamspeakLinkRequest(UUID caller, String callerRank, boolean powerPlay, String token) + { + this._caller = caller; + this._callerRank = callerRank; + this._powerPlay = powerPlay; + this._token = token; + } + + public UUID getCaller() + { + return _caller; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakLinkResponse.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakLinkResponse.java new file mode 100644 index 000000000..e9f59c0b6 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakLinkResponse.java @@ -0,0 +1,42 @@ +package mineplex.core.teamspeak.redis; + +import com.google.gson.annotations.SerializedName; + +import mineplex.serverdata.commands.ServerCommand; + +public class TeamspeakLinkResponse extends ServerCommand +{ + private final Response _response; + private final TeamspeakLinkRequest _request; + private final int _id; + + public TeamspeakLinkResponse(Response response, TeamspeakLinkRequest request, int id) + { + _response = response; + _request = request; + _id = id; + } + + public Response getResponse() + { + return _response; + } + + public TeamspeakLinkRequest getRequest() + { + return _request; + } + + public int getId() + { + return _id; + } + + public enum Response + { + @SerializedName("token-valid") + TOKEN_VALID, + @SerializedName("token-invalid") + TOKEN_INVALID + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUnlinkRequest.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUnlinkRequest.java new file mode 100644 index 000000000..340e89cdc --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUnlinkRequest.java @@ -0,0 +1,27 @@ +package mineplex.core.teamspeak.redis; + +import java.util.UUID; + +import mineplex.serverdata.commands.ServerCommand; + +public class TeamspeakUnlinkRequest extends ServerCommand +{ + private final UUID _caller; + private final int _id; + + public TeamspeakUnlinkRequest(UUID caller, int id) + { + this._caller = caller; + this._id = id; + } + + public UUID getCaller() + { + return _caller; + } + + public int getId() + { + return _id; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUnlinkResponse.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUnlinkResponse.java new file mode 100644 index 000000000..41827f9ee --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUnlinkResponse.java @@ -0,0 +1,33 @@ +package mineplex.core.teamspeak.redis; + +import com.google.gson.annotations.SerializedName; + +import mineplex.serverdata.commands.ServerCommand; + +public class TeamspeakUnlinkResponse extends ServerCommand +{ + private final Response _response; + private final TeamspeakUnlinkRequest _request; + + public TeamspeakUnlinkResponse(Response response, TeamspeakUnlinkRequest request) + { + this._response = response; + this._request = request; + } + + public Response getResponse() + { + return _response; + } + + public TeamspeakUnlinkRequest getRequest() + { + return _request; + } + + public enum Response + { + @SerializedName(value = "unlinked") + UNLINKED + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUpdateRequest.java b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUpdateRequest.java new file mode 100644 index 000000000..f8940cee4 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/teamspeak/redis/TeamspeakUpdateRequest.java @@ -0,0 +1,21 @@ +package mineplex.core.teamspeak.redis; + +import java.util.UUID; + +import mineplex.serverdata.commands.ServerCommand; + +public class TeamspeakUpdateRequest extends ServerCommand +{ + private final UUID _caller; + private final int[] _ids; + private final String _callerRank; + private final boolean _powerPlay; + + public TeamspeakUpdateRequest(UUID caller, int[] ids, String callerRank, boolean powerPlay) + { + _caller = caller; + _ids = ids; + _callerRank = callerRank; + _powerPlay = powerPlay; + } +} diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java index c4f8cdec8..763bbb153 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java @@ -64,6 +64,7 @@ import mineplex.core.sponsorbranding.BrandingManager; import mineplex.core.stats.StatsManager; import mineplex.core.status.ServerStatusManager; import mineplex.core.task.TaskManager; +import mineplex.core.teamspeak.TeamspeakManager; import mineplex.core.teleport.Teleport; import mineplex.core.thank.ThankManager; import mineplex.core.titles.Titles; @@ -234,6 +235,7 @@ public class Hub extends JavaPlugin implements IRelation require(TrackManager.class); require(Titles.class); require(TwoFactorAuth.class); + require(TeamspeakManager.class); } @Override diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/redis/atomic/RedisStringRepository.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/redis/atomic/RedisStringRepository.java index 910d61b38..b637b491d 100644 --- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/redis/atomic/RedisStringRepository.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/redis/atomic/RedisStringRepository.java @@ -5,25 +5,36 @@ import mineplex.serverdata.redis.RedisRepository; import mineplex.serverdata.servers.ConnectionData; import redis.clients.jedis.Jedis; -import redis.clients.jedis.Response; -import redis.clients.jedis.Transaction; -import static mineplex.serverdata.Utility.currentTimeMillis; public class RedisStringRepository extends RedisRepository { private final String _dataKey; + private final int _expiration; - public RedisStringRepository(ConnectionData writeConn, ConnectionData readConn, Region region, String dataKey) + public RedisStringRepository(ConnectionData writeConn, ConnectionData readConn, Region region, String dataKey, int expiryInSeconds) { super(writeConn, readConn, region); this._dataKey = dataKey; + this._expiration = expiryInSeconds; + } + + public RedisStringRepository(ConnectionData writeConn, ConnectionData readConn, Region region, String dataKey) + { + this(writeConn, readConn, region, dataKey, -1); } public void set(String key, String value) { try (Jedis jedis = getResource(true)) { - jedis.set(generateKey(key), value); + if (_expiration == -1) + { + jedis.set(generateKey(key), value); + } + else + { + jedis.setex(generateKey(key), _expiration, value); + } } }