Wrote standalone chatsnap handler and implemented required changes in Core.

This commit is contained in:
Keir 2015-12-04 23:30:27 +00:00
parent c19baf5750
commit ddf6037fc4
10 changed files with 226 additions and 14 deletions

View File

@ -5,6 +5,7 @@
<module fileurl="file://$PROJECT_DIR$/Classpath.Dummy/Classpath.Dummy.iml" filepath="$PROJECT_DIR$/Classpath.Dummy/Classpath.Dummy.iml" group="Core" />
<module fileurl="file://$PROJECT_DIR$/JedisTest/JedisTest.iml" filepath="$PROJECT_DIR$/JedisTest/JedisTest.iml" />
<module fileurl="file://$PROJECT_DIR$/Mineplex.Bungee.Mineplexer/Mineplex.Bungee.Mineplexer.iml" filepath="$PROJECT_DIR$/Mineplex.Bungee.Mineplexer/Mineplex.Bungee.Mineplexer.iml" group="Bungee" />
<module fileurl="file://$PROJECT_DIR$/Mineplex.ChatSnapManager/Mineplex.ChatSnapManager.iml" filepath="$PROJECT_DIR$/Mineplex.ChatSnapManager/Mineplex.ChatSnapManager.iml" group="Core" />
<module fileurl="file://$PROJECT_DIR$/Mineplex.Core/Mineplex.Core.iml" filepath="$PROJECT_DIR$/Mineplex.Core/Mineplex.Core.iml" group="Core" />
<module fileurl="file://$PROJECT_DIR$/Mineplex.Core.Common/Mineplex.Core.Common.iml" filepath="$PROJECT_DIR$/Mineplex.Core.Common/Mineplex.Core.Common.iml" group="Core" />
<module fileurl="file://$PROJECT_DIR$/Mineplex.Database/Mineplex.Database.iml" filepath="$PROJECT_DIR$/Mineplex.Database/Mineplex.Database.iml" group="Core" />

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: mineplex.chatsnap.ChatSnapManager

View File

@ -0,0 +1,49 @@
package mineplex.chatsnap;
import java.io.File;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* @author iKeirNez
*/
public class ChatSnapManager
{
public static final String CHANNEL_DEPLOY = "chatsnap:deploy";
public static final String CHANNEL_DESTROY = "chatsnap:destroy";
public static void main(String[] args)
{
new ChatSnapManager(new JedisPool(new JedisPoolConfig(), "host", 6379)); // TODO host
}
private JedisPool _jedisPool;
private File dataDirectory = new File("data");
public ChatSnapManager(JedisPool jedisPool)
{
_jedisPool = jedisPool;
if (dataDirectory.exists() && !dataDirectory.isDirectory())
{
throw new RuntimeException("Not a directory: " + dataDirectory.getPath());
}
if (!dataDirectory.exists() && !dataDirectory.mkdir())
{
throw new RuntimeException("Unable to create directory: " + dataDirectory.getPath());
}
registerHandler();
}
private void registerHandler()
{
try (Jedis jedis = _jedisPool.getResource())
{
jedis.subscribe(new JedisPubSubHandler(dataDirectory), CHANNEL_DEPLOY, CHANNEL_DESTROY);
}
}
}

View File

@ -0,0 +1,97 @@
package mineplex.chatsnap;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import redis.clients.jedis.JedisPubSub;
/**
* @author iKeirNez
*/
public class JedisPubSubHandler extends JedisPubSub
{
private File _directory;
private Gson _gson = new GsonBuilder()
.setPrettyPrinting()
.create();
public JedisPubSubHandler(File directory)
{
_directory = directory;
if (!directory.isDirectory())
{
throw new IllegalArgumentException("Not a directory.");
}
}
@Override
public void onMessage(String channel, String dataString)
{
if (channel.equals(ChatSnapManager.CHANNEL_DEPLOY))
{
JsonObject data = _gson.fromJson(dataString, JsonObject.class);
String token = data.get("token").getAsString();
JsonArray snapshotArray = data.get("snapshots").getAsJsonArray();
File target = new File(_directory, token + ".json");
String json = _gson.toJson(snapshotArray);
try
{
Files.write(target.toPath(), Arrays.asList(json.split("\n")));
}
catch (IOException e)
{
e.printStackTrace();
}
}
else if (channel.equals(ChatSnapManager.CHANNEL_DESTROY))
{
// dataString = token
File target = new File(_directory, dataString + ".json");
if (target.exists() && !target.delete())
{
System.out.println("Failed to delete: " + target.getPath());
}
}
}
@Override
public void onPMessage(String s, String s1, String s2)
{
}
@Override
public void onSubscribe(String s, int i)
{
}
@Override
public void onUnsubscribe(String s, int i)
{
}
@Override
public void onPUnsubscribe(String s, int i)
{
}
@Override
public void onPSubscribe(String s, int i)
{
}
}

View File

@ -23,11 +23,6 @@ public class MessageSnapshotManager
.expireAfterWrite(30, TimeUnit.MINUTES)
.build();
public MessageSnapshotManager()
{
}
/**
* Keeps a snapshot in memory temporarily (30 minutes) and then discards it.
* During this time, other modules (such as the Report module) can access it for their own use.

View File

@ -38,7 +38,7 @@ public class MessageSnapshotPlugin extends MiniPlugin
}
@EventHandler(priority = EventPriority.MONITOR)
public void cacheChatMessage(AsyncPlayerChatEvent e)
public void onPlayerChat(AsyncPlayerChatEvent e)
{
_messageSnapshotManager.cacheSnapshot(getMessageSnap(e));
}

View File

@ -6,6 +6,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import mineplex.serverdata.data.Data;
import org.apache.commons.lang3.RandomStringUtils;
public class Report implements Data
{
@ -37,6 +38,8 @@ public class Report implements Data
private long _lastActivity;
public long getLastActivity() { return _lastActivity; }
private String _token = null;
public Report(int reportId, String playerName, String serverName, ReportCategory category)
{
_reportId = reportId;
@ -64,6 +67,28 @@ public class Report implements Data
_lastActivity = System.currentTimeMillis();
}
public boolean hasChatSnapToken()
{
return _token != null;
}
/**
* Gets a token in the format of reportId-randomCharacters.
* Currently this is only used for publishing chat abuse reports.
*
* @return the full token
*/
public String getChatSnapToken()
{
// since we don't always use this, only generate a token when we need it
if (_token == null)
{
_token = RandomStringUtils.randomAlphabetic(8);
}
return _reportId + "-" + _token;
}
@Override
public String getDataId()
{

View File

@ -3,8 +3,14 @@ package mineplex.core.report;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import mineplex.core.account.CoreClient;
import mineplex.core.chatsnap.MessageSnapshot;
import mineplex.core.chatsnap.MessageSnapshotManager;
import mineplex.core.command.CommandCenter;
import mineplex.core.common.Rank;
@ -30,6 +36,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.serverdata.servers.ServerManager;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
@ -43,6 +50,11 @@ import redis.clients.jedis.exceptions.JedisConnectionException;
public class ReportManager {
private static final String NAME = "Report";
private static final String URL_PREFIX = "http://chatsnap.mineplex.com/";
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final String CHANNEL_DEPLOY = "chatsnap:deploy";
public static final String CHANNEL_DESTROY = "chatsnap:destroy";
// statistic constants
private static final String STAT_TOTAL_COUNT = "Global.TotalReportsCount";
@ -53,6 +65,7 @@ public class ReportManager {
private StatsManager _statsManager;
private MessageSnapshotManager _messageSnapshotManager;
private String _serverName;
private JedisPool _jedisPool;
// Holds active/open reports in a synchronized database.
private DataRepository<Report> _reportRepository;
@ -63,13 +76,15 @@ public class ReportManager {
// A mapping of PlayerName(String) to the ReportId(Integer) for all active reports on this server.
private Map<String, Integer> _activeReports;
public ReportManager(JavaPlugin javaPlugin, PreferencesManager preferencesManager, StatsManager statsManager, MessageSnapshotManager messageSnapshotManager, String serverName)
public ReportManager(JavaPlugin javaPlugin, PreferencesManager preferencesManager, StatsManager statsManager,
MessageSnapshotManager messageSnapshotManager, String serverName)
{
_javaPlugin = javaPlugin;
_preferencesManager = preferencesManager;
_statsManager = statsManager;
_messageSnapshotManager = messageSnapshotManager;
_serverName = serverName;
_jedisPool = Utility.generatePool(ServerManager.getMasterConnection()); // TODO is this the best way?
_reportRepository = new RedisDataRepository<Report>(Region.ALL, Report.class, "reports");
_activeReports = new HashMap<String, Integer>();
_reportSqlRepository = new ReportRepository(javaPlugin);
@ -110,6 +125,11 @@ public class ReportManager {
CommandCenter.Instance.OnPlayerCommandPreprocess(
new PlayerCommandPreprocessEvent(reportCloser, "/punish " + playerName + " " + reason));
}
if (report.getCategory() == ReportCategory.CHAT_ABUSE) // only chat abuse reports have chat logs published
{
unpublishChatLog(report.getChatSnapToken());
}
}
}
@ -182,6 +202,7 @@ public class ReportManager {
// only start notifying staff when
if (report.getReporters().size() >= category.getNotifyThreshold())
{
publishChatLog(report.getChatSnapToken(), reportedPlayer.getUniqueId());
int reportId = report.getReportId();
String prefix = getReportPrefix(reportId);
@ -206,11 +227,6 @@ public class ReportManager {
}
else
{
message = message.extra("\n" + F.main(prefix, String.format(
"Type /reportclose %d <reason> to close this report.",
reportId)))
.click(ClickEvent.SUGGEST_COMMAND, "/reportclose " + reportId);
sendHandlerNotification(report, message);
}
}
@ -221,6 +237,34 @@ public class ReportManager {
return null;
}
public String getChatLogUrl(String token)
{
return URL_PREFIX + token;
}
public void publishChatLog(String token, UUID playerUUID)
{
Set<MessageSnapshot> snapshots = _messageSnapshotManager.getSnapshotsFor(playerUUID);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("token", token);
jsonObject.add("snapshots", GSON.toJsonTree(snapshots));
String json = GSON.toJson(snapshots);
try (Jedis jedis = _jedisPool.getResource())
{
jedis.publish(CHANNEL_DEPLOY, json);
}
}
public void unpublishChatLog(String token)
{
try (Jedis jedis = _jedisPool.getResource())
{
jedis.publish(CHANNEL_DESTROY, token);
}
}
public void onPlayerJoin(Player player)
{
if (hasActiveReport(player))

View File

@ -24,7 +24,6 @@ public class ReportCommand extends CommandBase<ReportPlugin>
if(args == null || args.length < 2)
{
UtilPlayer.message(player, F.main(Plugin.getName(), C.cRed + "Your arguments are inappropriate for this command!"));
return;
}
else
{

View File

@ -24,7 +24,6 @@ public class ReportHandleCommand extends CommandBase<ReportPlugin>
if(args == null || args.length < 1)
{
UtilPlayer.message(player, F.main(Plugin.getName(), C.cRed + "Your arguments are inappropriate for this command!"));
return;
}
else
{