package fr.Alphart.BAT.Modules.Mute;
import static fr.Alphart.BAT.I18n.I18n._;
import static fr.Alphart.BAT.I18n.I18n.__;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import lombok.Getter;
import net.cubespace.Yamler.Config.Comment;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ChatEvent;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.ServerConnectedEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.scheduler.ScheduledTask;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
import fr.Alphart.BAT.BAT;
import fr.Alphart.BAT.Modules.BATCommand;
import fr.Alphart.BAT.Modules.CommandHandler;
import fr.Alphart.BAT.Modules.IModule;
import fr.Alphart.BAT.Modules.ModuleConfiguration;
import fr.Alphart.BAT.Modules.Core.Core;
import fr.Alphart.BAT.Utils.FormatUtils;
import fr.Alphart.BAT.Utils.UUIDNotFoundException;
import fr.Alphart.BAT.Utils.Utils;
import fr.Alphart.BAT.database.DataSourceHandler;
import fr.Alphart.BAT.database.SQLQueries;
/**
* This module handles all the mute.<br>
* The mute data of online players are <b>cached</b> in order to avoid lag.
*/
public class Mute implements IModule, Listener {
private final String name = "mute";
private ConcurrentHashMap<String, PlayerMuteData> mutedPlayers;
private CommandHandler commandHandler;
private ScheduledTask task;
private final MuteConfig config;
public Mute() {
config = new MuteConfig();
}
@Override
public List<BATCommand> getCommands() {
return commandHandler.getCmds();
}
@Override
public String getMainCommand() {
return "mute";
}
@Override
public ModuleConfiguration getConfig() {
return config;
}
@Override
public String getName() {
return name;
}
@Override
public boolean load() {
// Init table
Statement statement = null;
try (Connection conn = BAT.getConnection()) {
statement = conn.createStatement();
if (DataSourceHandler.isSQLite()) {
for (final String query : SQLQueries.Mute.SQLite.createTable) {
statement.executeUpdate(query);
}
} else {
statement.executeUpdate(SQLQueries.Mute.createTable);
}
statement.close();
} catch (final SQLException e) {
DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement);
}
// Register commands
commandHandler = new MuteCommand(this);
commandHandler.loadCmds();
mutedPlayers = new ConcurrentHashMap<String, PlayerMuteData>();
final MuteTask muteTask = new MuteTask(this);
task = ProxyServer.getInstance().getScheduler().schedule(BAT.getInstance(), muteTask, 0, 10, TimeUnit.SECONDS);
return true;
}
@Override
public boolean unload() {
task.cancel();
mutedPlayers.clear();
return true;
}
public class MuteConfig extends ModuleConfiguration {
public MuteConfig() {
init(name);
}
@Comment("Forbidden commands when a player is mute")
@Getter
private List<String> forbiddenCmds = new ArrayList<String>(){
private static final long serialVersionUID = 1L;
{
add("msg");
}};
}
public void loadMuteMessage(final String pName, final String server){
if(!mutedPlayers.containsKey(pName)){
return;
}
String reason = "";
Timestamp expiration = null;
Timestamp begin = null;
String staff = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try (Connection conn = BAT.getConnection()) {
statement = conn.prepareStatement(DataSourceHandler.isSQLite()
? SQLQueries.Mute.SQLite.getMuteMessage
: SQLQueries.Mute.getMuteMessage);
try{
statement.setString(1, Core.getUUID(pName));
statement.setString(2, Core.getPlayerIP(pName));
statement.setString(3, server);
}catch(final UUIDNotFoundException e){
BAT.getInstance().getLogger().severe("Error during retrieving of the UUID of " + pName + ". Please report this error :");
e.printStackTrace();
}
resultSet = statement.executeQuery();
if(resultSet.next()) {
if(DataSourceHandler.isSQLite()){
begin = new Timestamp(resultSet.getLong("strftime('%s',mute_begin)") * 1000);
String endStr = resultSet.getString("mute_end");
expiration = (endStr == null) ? null : new Timestamp(Long.parseLong(endStr));
}else{
begin = resultSet.getTimestamp("mute_begin");
expiration = resultSet.getTimestamp("mute_end");
}
reason = (resultSet.getString("mute_reason") != null) ? resultSet.getString("mute_reason") : IModule.NO_REASON;
staff = resultSet.getString("mute_staff");
}else{
throw new SQLException("No active mute found.");
}
} catch (final SQLException e) {
DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement, resultSet);
}
if(expiration != null){
mutedPlayers.get(pName).setMuteMessage(_("isMuteTemp",
new String[]{ reason , "{expiration}", Core.defaultDF.format(begin), staff }), expiration);
}else{
mutedPlayers.get(pName).setMuteMessage(_("isMute",
new String[]{ reason, Core.defaultDF.format(begin), staff }), null);
}
}
/**
* Check if both ip and name of this player are muted<br>
* Use <b>cached data</b>
*
* @param player
* @param server
* @return <ul>
* <li>1 if the player is muted from this server</li>
* <li>0 if he's not muted from this server</li>
* <li>-1 if the data are loading</li>
* </ul>
*/
public int isMute(final ProxiedPlayer player, final String server) {
final PlayerMuteData pMuteData = mutedPlayers.get(player.getName());
if (pMuteData != null) {
if (pMuteData.isMute(server)) {
return 1;
}
return 0;
}
return -1;
}
/**
* Check if this entity (player or ip) is muted<br>
* <b>Use uncached data. Use {@link #isMute(ProxiedPlayer, String)} instead
* of this method if the player is available</b>
*
* @param mutedEntity
* | can be an ip or a player name
* @param server
* | if server equals to (any) check if the player is mute on a
* server
* @param forceUseUncachedData
* | use uncached data, for example to handle player or player's
* ip related mute
* @return
*/
public boolean isMute(final String mutedEntity, final String server, final boolean forceUseUncachedData) {
// Check if the entity is an online player, in this case we're going to
// use the cached method
final ProxiedPlayer player = ProxyServer.getInstance().getPlayer(mutedEntity);
if (!forceUseUncachedData && player != null) {
final int result = isMute(player, server);
// If the data aren't loading
if (result != -1) {
return (result == 1);
}
}
PreparedStatement statement = null;
ResultSet resultSet = null;
try (Connection conn = BAT.getConnection()) {
// If this is an ip which may be muted
if (Utils.validIP(mutedEntity)) {
final String ip = mutedEntity;
statement = conn.prepareStatement((ANY_SERVER.equals(server)) ? SQLQueries.Mute.isMuteIP
: SQLQueries.Mute.isMuteServerIP);
statement.setString(1, ip);
if (!ANY_SERVER.equals(server)) {
statement.setString(2, server);
}
}
// If this is a player which may be muted
else {
final String pName = mutedEntity;
statement = conn.prepareStatement((ANY_SERVER.equals(server)) ? SQLQueries.Mute.isMute
: SQLQueries.Mute.isMuteServer);
statement.setString(1, Core.getUUID(pName));
if (!ANY_SERVER.equals(server)) {
statement.setString(2, server);
}
}
resultSet = statement.executeQuery();
// If there are a result
if (resultSet.next()) {
return true;
}
} catch (final SQLException e) {
DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement, resultSet);
}
return false;
}
/**
* Mute this entity (player or ip) <br>
*
* @param mutedEntity
* | can be an ip or a player name
* @param server
* ; set to "(global)", to global mute
* @param staff
* @param expirationTimestamp
* ; set to 0 for mute def
* @param reason
* | optional
* @return
*/
public String mute(final String mutedEntity, final String server, final String staff,
final long expirationTimestamp, final String reason) {
PreparedStatement statement = null;
try (Connection conn = BAT.getConnection()) {
if (Utils.validIP(mutedEntity)) {
final String ip = mutedEntity;
statement = conn.prepareStatement(SQLQueries.Mute.createMuteIP);
statement.setString(1, ip);
statement.setString(2, staff);
statement.setString(3, server);
statement.setTimestamp(4, (expirationTimestamp > 0) ? new Timestamp(expirationTimestamp) : null);
statement.setString(5, (NO_REASON.equals(reason)) ? null : reason);
statement.executeUpdate();
statement.close();
if (BAT.getInstance().getRedis().isRedisEnabled()) {
for (UUID pUUID : RedisBungee.getApi().getPlayersOnline()) {
if (RedisBungee.getApi().getPlayerIp(pUUID).equals(ip)) {
// The mute task timer will add the player to the bungeecord instance's cache if needed.
if(server.equals(GLOBAL_SERVER) || RedisBungee.getApi().getServerFor(pUUID).getName().equalsIgnoreCase(server)) {
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(pUUID);
if (player != null) {
player.sendMessage(__("wasMutedNotif", new String[] { reason }));
} else {
BAT.getInstance().getRedis().sendMessagePlayer(pUUID, TextComponent.toLegacyText(__("wasMutedNotif", new String[] { reason })));
}
}
}
}
} else {
for (final ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
if (Utils.getPlayerIP(player).equals(ip)) {
if (server.equals(GLOBAL_SERVER)) {
mutedPlayers.get(player.getName()).setGlobal();
} else {
mutedPlayers.get(player.getName()).addServer(server);
}
if (server.equals(GLOBAL_SERVER) || player.getServer().getInfo().getName().equalsIgnoreCase(server)) {
player.sendMessage(__("wasMutedNotif", new String[] { reason }));
}
}
}
}
if (expirationTimestamp > 0) {
return _("muteTempBroadcast", new String[] { ip, FormatUtils.getDuration(expirationTimestamp),
staff, server, reason });
} else {
return _("muteBroadcast", new String[] { ip, staff, server, reason });
}
}
// Otherwise it's a player
else {
final String pName = mutedEntity;
final ProxiedPlayer player = ProxyServer.getInstance().getPlayer(pName);
statement = conn.prepareStatement(SQLQueries.Mute.createMute);
statement.setString(1, Core.getUUID(pName));
statement.setString(2, staff);
statement.setString(3, server);
statement.setTimestamp(4, (expirationTimestamp > 0) ? new Timestamp(expirationTimestamp) : null);
statement.setString(5, (NO_REASON.equals(reason)) ? null : reason);
statement.executeUpdate();
statement.close();
if (player != null) {
updateMuteData(player.getName());
if(server.equals(GLOBAL_SERVER) || player.getServer().getInfo().getName().equalsIgnoreCase(server)){
player.sendMessage(__("wasMutedNotif", new String[] { reason }));
}
} else if (BAT.getInstance().getRedis().isRedisEnabled()) {
//Need to implement a function to get an UUID object instead of a string one.
final UUID pUUID = Core.getUUIDfromString(Core.getUUID(pName));
BAT.getInstance().getRedis().sendMuteUpdatePlayer(pUUID, server);
BAT.getInstance().getRedis().sendMessagePlayer(pUUID, TextComponent.toLegacyText(__("wasMutedNotif", new String[] { reason })));
}
if (expirationTimestamp > 0) {
return _("muteTempBroadcast", new String[] { pName, FormatUtils.getDuration(expirationTimestamp),
staff, server, reason });
} else {
return _("muteBroadcast", new String[] { pName, staff, server, reason });
}
}
} catch (final SQLException e) {
return DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement);
}
}
/**
* Mute the ip of an online player
*
* @param server
* ; set to "(global)", to global mute
* @param staff
* @param duration
* ; set to 0 for mute def
* @param reason
* | optional
* @param ip
*/
public String muteIP(final ProxiedPlayer player, final String server, final String staff,
final long expirationTimestamp, final String reason) {
mute(Utils.getPlayerIP(player), server, staff, expirationTimestamp, reason);
return _("muteBroadcast", new String[] { player.getName() + "'s IP", staff, server, reason });
}
/**
* Unmute an entity (player or ip)
*
* @param mutedEntity
* | can be an ip or a player name
* @param server
* | if equals to (any), unmute from all servers | if equals to
* (global), remove global mute
* @param staff
* @param reason
* @param unMuteIP
*/
public String unMute(final String mutedEntity, final String server, final String staff, final String reason) {
PreparedStatement statement = null;
try (Connection conn = BAT.getConnection()) {
// If the mutedEntity is an ip
if (Utils.validIP(mutedEntity)) {
final String ip = mutedEntity;
if (ANY_SERVER.equals(server)) {
statement = (DataSourceHandler.isSQLite()) ? conn.prepareStatement(SQLQueries.Mute.SQLite.unMuteIP)
: conn.prepareStatement(SQLQueries.Mute.unMuteIP);
statement.setString(1, reason);
statement.setString(2, staff);
statement.setString(3, ip);
} else {
statement = (DataSourceHandler.isSQLite()) ? conn
.prepareStatement(SQLQueries.Mute.SQLite.unMuteIPServer) : conn
.prepareStatement(SQLQueries.Mute.unMuteIPServer);
statement.setString(1, reason);
statement.setString(2, staff);
statement.setString(3, ip);
statement.setString(4, server);
}
statement.executeUpdate();
statement.close();
return _("unmuteBroadcast", new String[] { ip, staff, server, reason });
}
// Otherwise it's a player
else {
final String pName = mutedEntity;
if (ANY_SERVER.equals(server)) {
statement = (DataSourceHandler.isSQLite()) ? conn.prepareStatement(SQLQueries.Mute.SQLite.unMute)
: conn.prepareStatement(SQLQueries.Mute.unMute);
statement.setString(1, reason);
statement.setString(2, staff);
statement.setString(3, Core.getUUID(pName));
} else {
statement = (DataSourceHandler.isSQLite()) ? conn
.prepareStatement(SQLQueries.Mute.SQLite.unMuteServer) : conn
.prepareStatement(SQLQueries.Mute.unMuteServer);
statement.setString(1, reason);
statement.setString(2, staff);
statement.setString(3, Core.getUUID(pName));
statement.setString(4, server);
}
statement.executeUpdate();
statement.close();
final ProxiedPlayer player = ProxyServer.getInstance().getPlayer(pName);
if (player != null) {
updateMuteData(player.getName());
if(ANY_SERVER.equals(server) || GLOBAL_SERVER.equals(server) || player.getServer().getInfo().getName().equalsIgnoreCase(server)){
player.sendMessage(__("wasUnmutedNotif", new String[] { reason }));
}
} else if (BAT.getInstance().getRedis().isRedisEnabled()) {
final UUID pUUID = Core.getUUIDfromString(Core.getUUID(pName));
ServerInfo pServer = RedisBungee.getApi().getServerFor(pUUID);
if (ANY_SERVER.equals(server) || GLOBAL_SERVER.equals(server) || (pServer != null && pServer.getName().equalsIgnoreCase(server))){
BAT.getInstance().getRedis().sendMuteUpdatePlayer(pUUID, server);
BAT.getInstance().getRedis().sendMessagePlayer(pUUID, TextComponent.toLegacyText(__("wasUnmutedNotif", new String[] { reason })));
}
}
return _("unmuteBroadcast", new String[] { pName, staff, server, reason });
}
} catch (final SQLException e) {
return DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement);
}
}
/**
* Unmute the ip of this entity
*
* @param entity
* @param server
* | if equals to (any), unmute from all servers | if equals to
* (global), remove global mute
* @param staff
* @param reason
* | optional
* @param duration
* ; set to 0 for mute def
*/
public String unMuteIP(final String entity, final String server, final String staff, final String reason) {
if (Utils.validIP(entity)) {
return unMute(entity, server, staff, reason);
} else {
unMute(Core.getPlayerIP(entity), server, staff, reason);
updateMuteData(entity);
return _("unmuteBroadcast", new String[] { entity + "'s IP", staff, server, reason });
}
}
/**
* Get all mute data of an entity <br>
* <b>Should be run async to optimize performance</b>
*
* @param entity
* | can be an ip or a player name
* @return List of MuteEntry of the entity
*/
public List<MuteEntry> getMuteData(final String entity) {
final List<MuteEntry> muteList = new ArrayList<MuteEntry>();
PreparedStatement statement = null;
ResultSet resultSet = null;
try (Connection conn = BAT.getConnection()) {
// If the entity is an ip
if (Utils.validIP(entity)) {
statement = conn.prepareStatement((DataSourceHandler.isSQLite())
? SQLQueries.Mute.SQLite.getMuteIP
: SQLQueries.Mute.getMuteIP);
statement.setString(1, entity);
resultSet = statement.executeQuery();
}
// Otherwise if it's a player
else {
statement = conn.prepareStatement((DataSourceHandler.isSQLite())
? SQLQueries.Mute.SQLite.getMute
: SQLQueries.Mute.getMute);
statement.setString(1, Core.getUUID(entity));
resultSet = statement.executeQuery();
}
while (resultSet.next()) {
final Timestamp beginDate;
final Timestamp endDate;
final Timestamp unmuteDate;
if(DataSourceHandler.isSQLite()){
beginDate = new Timestamp(resultSet.getLong("strftime('%s',mute_begin)") * 1000);
final String endStr = resultSet.getString("mute_end");
endDate = (endStr == null) ? null : new Timestamp(Long.parseLong(endStr));
final long unbanLong = resultSet.getLong("strftime('%s',mute_unmutedate)") * 1000;
unmuteDate = (unbanLong == 0) ? null : new Timestamp(unbanLong);
}else{
beginDate = resultSet.getTimestamp("mute_begin");
endDate = resultSet.getTimestamp("mute_end");
unmuteDate = resultSet.getTimestamp("mute_unmutedate");
}
final String server = resultSet.getString("mute_server");
String reason = resultSet.getString("mute_reason");
if(reason == null){
reason = NO_REASON;
}
final String staff = resultSet.getString("mute_staff");
final boolean active = (resultSet.getBoolean("mute_state") ? true : false);
String unmuteReason = resultSet.getString("mute_unmutereason");
if(unmuteReason == null){
unmuteReason = NO_REASON;
}
final String unmuteStaff = resultSet.getString("mute_unmutestaff");
muteList.add(new MuteEntry(entity, server, reason, staff, beginDate, endDate, unmuteDate, unmuteReason, unmuteStaff, active));
}
} catch (final SQLException e) {
DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement, resultSet);
}
return muteList;
}
/**
* This class is used to cache the mute data of a player.
*/
public static class PlayerMuteData {
private final String pName;
private final List<String> servers;
private boolean globalMute = false;
private Map.Entry<String, Timestamp> muteMessage;
public PlayerMuteData(final String pName, final List<String> servers) {
this.pName = pName;
// Override the arraylist implementation to make used methods non-case sensitive
this.servers = new ArrayList<String>(){
@Override
public void add(int index, String element) {
super.add(index, element.toLowerCase());
}
@Override
public boolean add(String e) {
return super.add(e.toLowerCase());
}
@Override
public boolean contains(Object o) {
if(o instanceof String){
return super.contains(((String)o).toLowerCase());
}
return super.contains(o);
}
};
for(final String server : servers){
servers.add(server);
}
}
public void setGlobal() {
globalMute = true;
}
public void unsetGlobal() {
globalMute = false;
}
public void addServer(final String server) {
if (!servers.contains(server)) {
servers.add(server);
}
}
public void removeServer(final String server) {
servers.remove(server);
}
public void clearServers() {
servers.clear();
}
public boolean isMute(final String server) {
if (globalMute) {
return true;
}else if( (ANY_SERVER.equals(server) && !servers.isEmpty()) ){
return true;
}else if(servers.contains(server)){
return true;
}
return false;
}
public BaseComponent[] getMuteMessage(final Mute module){
if(muteMessage != null){
if(muteMessage.getValue() != null){
if(muteMessage.getValue().getTime() >= System.currentTimeMillis()){
return BAT.__(muteMessage.getKey().replace("{expiration}", FormatUtils.getDuration(muteMessage.getValue().getTime())));
}
// If it's not synchronized with the db, force the update of mute data
else{
Statement statement = null;
try (Connection conn = BAT.getConnection()) {
statement = conn.createStatement();
if (DataSourceHandler.isSQLite()) {
statement.executeUpdate(SQLQueries.Mute.SQLite.updateExpiredMute);
} else {
statement.executeUpdate(SQLQueries.Mute.updateExpiredMute);
}
} catch (final SQLException e) {
DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement);
}
module.updateMuteData(pName);
}
}
else{
return BAT.__(muteMessage.getKey());
}
}
return __("wasUnmutedNotif", new String[]{ NO_REASON });
}
public void setMuteMessage(final String messagePattern, final Timestamp expiration){
muteMessage = new AbstractMap.SimpleEntry<String, Timestamp>(messagePattern, expiration);
}
}
public void updateMuteData(final String pName) {
final ProxiedPlayer player = ProxyServer.getInstance().getPlayer(pName);
if (player == null) {
return;
}
PlayerMuteData pMuteData;
if (mutedPlayers.containsKey(pName)) {
pMuteData = mutedPlayers.get(pName);
pMuteData.clearServers();
pMuteData.unsetGlobal();
} else {
pMuteData = new PlayerMuteData(pName, new ArrayList<String>());
}
PreparedStatement statement = null;
ResultSet resultSet = null;
try (Connection conn = BAT.getConnection()) {
statement = conn.prepareStatement("SELECT mute_server FROM `BAT_mute` WHERE UUID = ? AND mute_state = 1;");
statement.setString(1, Core.getUUID(pName));
resultSet = statement.executeQuery();
while (resultSet.next()) {
final String server = resultSet.getString("mute_server");
if (GLOBAL_SERVER.equals(server)) {
pMuteData.setGlobal();
} else {
pMuteData.addServer(server);
}
}
resultSet.close();
statement.close();
statement = conn
.prepareStatement("SELECT mute_server FROM `BAT_mute` WHERE mute_ip = ? AND mute_state = 1;");
statement.setString(1, Core.getPlayerIP(pName));
resultSet = statement.executeQuery();
while (resultSet.next()) {
final String server = resultSet.getString("mute_server");
if (GLOBAL_SERVER.equals(server)) {
pMuteData.setGlobal();
} else {
pMuteData.addServer(server);
}
}
} catch (final SQLException e) {
DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement, resultSet);
}
mutedPlayers.put(pName, pMuteData);
if(pMuteData.isMute(GLOBAL_SERVER)){
loadMuteMessage(pName, GLOBAL_SERVER);
}else if(player.getServer() != null && pMuteData.isMute(player.getServer().getInfo().getName())){
loadMuteMessage(pName, player.getServer().getInfo().getName());
}
}
public List<MuteEntry> getManagedMute(final String staff){
final List<MuteEntry> muteList = new ArrayList<MuteEntry>();
PreparedStatement statement = null;
ResultSet resultSet = null;
try (Connection conn = BAT.getConnection()) {
statement = conn.prepareStatement((DataSourceHandler.isSQLite())
? SQLQueries.Mute.SQLite.getManagedMute
: SQLQueries.Mute.getManagedMute);
statement.setString(1, staff);
statement.setString(2, staff);
resultSet = statement.executeQuery();
while (resultSet.next()) {
final Timestamp beginDate;
final Timestamp endDate;
final Timestamp unmuteDate;
if(DataSourceHandler.isSQLite()){
beginDate = new Timestamp(resultSet.getLong("strftime('%s',mute_begin)") * 1000);
String endStr = resultSet.getString("mute_end");
endDate = (endStr == null) ? null : new Timestamp(Long.parseLong(endStr));
long unmuteLong = resultSet.getLong("strftime('%s',mute_unmutedate)") * 1000;
unmuteDate = (unmuteLong == 0) ? null : new Timestamp(unmuteLong);
}else{
beginDate = resultSet.getTimestamp("mute_begin");
endDate = resultSet.getTimestamp("mute_end");
unmuteDate = resultSet.getTimestamp("mute_unmutedate");
}
// Make it compatible with sqlite (date: get an int with the sfrt and then construct a tiemstamp)
final String server = resultSet.getString("mute_server");
String reason = resultSet.getString("mute_reason");
if(reason == null){
reason = NO_REASON;
}
String entity = (resultSet.getString("mute_ip") != null)
? resultSet.getString("mute_ip")
: Core.getPlayerName(resultSet.getString("UUID"));
// If the UUID search failed
if(entity == null){
entity = "UUID:" + resultSet.getString("UUID");
}
final boolean active = (resultSet.getBoolean("mute_state") ? true : false);
String unmuteReason = resultSet.getString("mute_unmutereason");
if(unmuteReason == null){
unmuteReason = NO_REASON;
}
final String unmuteStaff = resultSet.getString("mute_unmutestaff");
muteList.add(new MuteEntry(entity, server, reason, staff, beginDate, endDate, unmuteDate, unmuteReason, unmuteStaff, active));
}
} catch (final SQLException e) {
DataSourceHandler.handleException(e);
} finally {
DataSourceHandler.close(statement, resultSet);
}
return muteList;
}
public void unloadMuteData(final ProxiedPlayer player) {
mutedPlayers.remove(player.getName());
}
// Event Listener
@EventHandler
public void onServerConnect(final ServerConnectedEvent e) {
final ProxiedPlayer player = e.getPlayer();
final String pName = player.getName();
final int muteState = isMute(player, e.getServer().getInfo().getName());
if (muteState == -1) {
// Load mute data with a little bit of delay to handle server switching operations which may take some time
BAT.getInstance().getProxy().getScheduler().schedule(BAT.getInstance(), new Runnable() {
@Override
public void run() {
updateMuteData(pName);
}
}, 250, TimeUnit.MILLISECONDS);
} else if (muteState == 1) {
PlayerMuteData pMuteData = mutedPlayers.get(pName);
if(pMuteData.isMute(GLOBAL_SERVER)){
loadMuteMessage(pName, GLOBAL_SERVER);
}else if(pMuteData.isMute(e.getServer().getInfo().getName())){
loadMuteMessage(pName, e.getServer().getInfo().getName());
}
player.sendMessage(pMuteData.getMuteMessage(this));
}
}
@EventHandler
public void onPlayerDisconnect(final PlayerDisconnectEvent e) {
unloadMuteData(e.getPlayer());
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerChat(final ChatEvent e) {
if(!(e.getSender() instanceof ProxiedPlayer) || ((ProxiedPlayer) e.getSender()).getServer() == null){
return;
}
final ProxiedPlayer player = (ProxiedPlayer) e.getSender();
final int muteState = isMute(player, player.getServer().getInfo().getName());
if (muteState == 0) {
return;
}
if (e.isCommand()) {
final String command = e.getMessage().replaceAll("/", "").toLowerCase() + " ";
// There is a bug when overriding the contains method of the arraylist, so we do the contains here
boolean contains = false;
for(final String forbiddenCmd : config.getForbiddenCmds()){
// Add a space because if we block "/r", we don't want to block "/replay"
if(command.startsWith(forbiddenCmd.toLowerCase() + " ")){
contains = true;
break;
}
}
if (!contains) {
return;
}
}
if (muteState == 1) {
player.sendMessage(mutedPlayers.get(player.getName()).getMuteMessage(this));
e.setCancelled(true);
} else if (muteState == -1) {
player.sendMessage(__("loadingMutedata"));
e.setCancelled(true);
}
}
}