Added chatLookup and commandLookup API methods

This commit is contained in:
Intelli committed 2026-05-05 16:01:14 -06:00
1 parent 7eaa88eb7f
commit 3ffece26a3
4 files changed
+432

No files matched your search

+104
View File
@@ -31,6 +31,14 @@ List<ContainerResult> containerLookup(Location location, int time)
List<ContainerResult> containerLookup(Location location, int time, int radius)
```
- Added `ContainerResult` for reading container transaction data without parsing `String[]` lookup rows.
- Added typed chat and command lookup methods:
```java
List<MessageResult> chatLookup(String user, int time)
List<MessageResult> chatLookup(String user, int time, int radius, Location radius_location)
List<MessageResult> commandLookup(String user, int time)
List<MessageResult> commandLookup(String user, int time, int radius, Location radius_location)
```
- Added `MessageResult` for reading chat and command data without parsing `String[]` lookup rows.
---
@@ -102,6 +110,14 @@ List<ContainerResult> containerLookup(Location location, int time)
List<ContainerResult> containerLookup(Location location, int time, int radius)
List<MessageResult> chatLookup(String user, int time)
List<MessageResult> chatLookup(String user, int time, int radius, Location radius_location)
List<MessageResult> commandLookup(String user, int time)
List<MessageResult> commandLookup(String user, int time, int radius, Location radius_location)
List<String[]> sessionLookup(String user, int time)
List<String[]> queueLookup(Block block)
@@ -259,6 +275,58 @@ Both container lookup methods return `ContainerResult` entries with typed access
---
#### `chatLookup(String user, int time)`
This will perform a chat message lookup for a user. Use `null` or `#global` to search all users.
* **user:** The username to perform the lookup on.
* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds.
---
#### `chatLookup(String user, int time, int radius, Location radius_location)`
This will perform a chat message lookup around a location, similar to running `/co lookup a:chat r:<radius>`.
* **user:** The username to perform the lookup on. Use `null` or `#global` to search all users.
* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds.
* **radius:** Specify the radius to search in the X/Z plane. Set to "0" to search the exact location.
* **radius_location:** Specify the center location to search around.
---
#### `commandLookup(String user, int time)`
This will perform a command lookup for a user. Use `null` or `#global` to search all users.
* **user:** The username to perform the lookup on.
* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds.
---
#### `commandLookup(String user, int time, int radius, Location radius_location)`
This will perform a command lookup around a location, similar to running `/co lookup a:command r:<radius>`.
* **user:** The username to perform the lookup on. Use `null` or `#global` to search all users.
* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds.
* **radius:** Specify the radius to search in the X/Z plane. Set to "0" to search the exact location.
* **radius_location:** Specify the center location to search around.
All chat and command lookup methods return `MessageResult` entries with typed access to the following:
* **getX():** Get the X coordinate of the message or command.
* **getY():** Get the Y coordinate of the message or command.
* **getZ():** Get the Z coordinate of the message or command.
* **getMessage():** Get the message or command text.
* **getPlayer():** Get the username as a string.
* **getTimestamp():** Get the time of the message or command.
* **getActionId():** Get the action ID. (6=chat, 7=command)
* **getActionString():** Get the action as a string. (chat, command)
* **worldName():** The name of the world where the message or command was logged.
---
#### `queueLookup(Block block)`
This will search the consumer queue for changes on a block not yet saved in the database.
@@ -556,6 +624,42 @@ if (CoreProtect != null){ // Ensure we have access to the API
---
- Get the last 60 seconds of chat messages for the user "Notch".
```java
CoreProtectAPI CoreProtect = getCoreProtect();
if (CoreProtect != null){ // Ensure we have access to the API
List<MessageResult> lookup = CoreProtect.chatLookup("Notch", 60);
if (lookup != null){
for (MessageResult result : lookup){
String message = result.getMessage();
int x = result.getX();
int y = result.getY();
int z = result.getZ();
// ...
}
}
}
```
---
- Get the last 60 seconds of commands within 5 blocks of a location.
```java
CoreProtectAPI CoreProtect = getCoreProtect();
if (CoreProtect != null){ // Ensure we have access to the API
List<MessageResult> lookup = CoreProtect.commandLookup(null, 60, 5, location);
if (lookup != null){
for (MessageResult result : lookup){
String command = result.getMessage();
String player = result.getPlayer();
// ...
}
}
}
```
---
- Get the last 1 day of session data for the user "Notch".
```java
CoreProtectAPI CoreProtect = getCoreProtect();
@@ -18,9 +18,11 @@ import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import net.coreprotect.api.BlockAPI;
import net.coreprotect.api.MessageAPI;
import net.coreprotect.api.QueueLookup;
import net.coreprotect.api.SessionLookup;
import net.coreprotect.api.result.ContainerResult;
import net.coreprotect.api.result.MessageResult;
import net.coreprotect.config.Config;
import net.coreprotect.consumer.Queue;
import net.coreprotect.database.Database;
@@ -165,6 +167,78 @@ public class CoreProtectAPI extends Queue {
return SessionLookup.performLookup(user, time);
}
/**
* Performs a chat message lookup for the specified user.
*
* @param user
* The user to look up, or #global/null for all users
* @param time
* Time constraint in seconds
* @return List of results or null if API is disabled
*/
public List<MessageResult> chatLookup(String user, int time) {
if (isEnabled()) {
return MessageAPI.performChatLookup(user, time);
}
return null;
}
/**
* Performs a chat message lookup around the specified location.
*
* @param user
* The user to look up, or #global/null for all users
* @param time
* Time constraint in seconds
* @param radius
* Radius to search in the X/Z plane; 0 searches the exact location
* @param radiusLocation
* Center location for the radius search
* @return List of results or null if API is disabled
*/
public List<MessageResult> chatLookup(String user, int time, int radius, Location radiusLocation) {
if (isEnabled()) {
return MessageAPI.performChatLookup(user, time, radius, radiusLocation);
}
return null;
}
/**
* Performs a command lookup for the specified user.
*
* @param user
* The user to look up, or #global/null for all users
* @param time
* Time constraint in seconds
* @return List of results or null if API is disabled
*/
public List<MessageResult> commandLookup(String user, int time) {
if (isEnabled()) {
return MessageAPI.performCommandLookup(user, time);
}
return null;
}
/**
* Performs a command lookup around the specified location.
*
* @param user
* The user to look up, or #global/null for all users
* @param time
* Time constraint in seconds
* @param radius
* Radius to search in the X/Z plane; 0 searches the exact location
* @param radiusLocation
* Center location for the radius search
* @return List of results or null if API is disabled
*/
public List<MessageResult> commandLookup(String user, int time, int radius, Location radiusLocation) {
if (isEnabled()) {
return MessageAPI.performCommandLookup(user, time, radius, radiusLocation);
}
return null;
}
/**
* Determines if a user has placed a block at the specified location.
*
@@ -0,0 +1,185 @@
package net.coreprotect.api;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import net.coreprotect.api.result.MessageResult;
import net.coreprotect.config.Config;
import net.coreprotect.config.ConfigHandler;
import net.coreprotect.database.Database;
import net.coreprotect.database.statement.UserStatement;
import net.coreprotect.utility.WorldUtils;
/**
* Provides API methods for player chat and command lookups.
*/
public class MessageAPI {
private static final int CHAT_ACTION_ID = 6;
private static final int COMMAND_ACTION_ID = 7;
private MessageAPI() {
throw new IllegalStateException("API class");
}
public static List<MessageResult> performChatLookup(String user, int offset) {
return performLookup("chat", CHAT_ACTION_ID, user, offset, -1, null);
}
public static List<MessageResult> performChatLookup(String user, int offset, int radius, Location location) {
return performLookup("chat", CHAT_ACTION_ID, user, offset, radius, location);
}
public static List<MessageResult> performCommandLookup(String user, int offset) {
return performLookup("command", COMMAND_ACTION_ID, user, offset, -1, null);
}
public static List<MessageResult> performCommandLookup(String user, int offset, int radius, Location location) {
return performLookup("command", COMMAND_ACTION_ID, user, offset, radius, location);
}
private static List<MessageResult> performLookup(String table, int actionId, String user, int offset, int radius, Location location) {
List<MessageResult> result = new ArrayList<>();
if (!Config.getGlobal().API_ENABLED) {
return result;
}
if (location != null && location.getWorld() == null) {
return result;
}
try (Connection connection = Database.getConnection(false, 1000)) {
if (connection == null) {
return result;
}
Integer userId = getUserId(connection, user);
if (userId != null && userId == -1) {
return result;
}
int checkTime = 0;
if (offset > 0) {
checkTime = (int) (System.currentTimeMillis() / 1000L) - offset;
}
StringBuilder query = new StringBuilder("SELECT time,user,wid,x,y,z,message FROM ");
query.append(ConfigHandler.prefix).append(table).append(" ");
if (location != null) {
query.append(WorldUtils.getWidIndex(table));
}
query.append("WHERE time > ?");
if (userId != null) {
query.append(" AND user = ?");
}
if (location != null) {
query.append(" AND wid = ?");
if (radius > 0) {
query.append(" AND x >= ? AND x <= ? AND z >= ? AND z <= ?");
}
else {
query.append(" AND x = ? AND y = ? AND z = ?");
}
}
query.append(" ORDER BY rowid DESC");
try (PreparedStatement statement = connection.prepareStatement(query.toString())) {
int parameterIndex = 1;
statement.setInt(parameterIndex++, checkTime);
if (userId != null) {
statement.setInt(parameterIndex++, userId);
}
if (location != null) {
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
statement.setInt(parameterIndex++, WorldUtils.getWorldId(location.getWorld().getName()));
if (radius > 0) {
statement.setInt(parameterIndex++, clampToInt((long) x - radius));
statement.setInt(parameterIndex++, clampToInt((long) x + radius));
statement.setInt(parameterIndex++, clampToInt((long) z - radius));
statement.setInt(parameterIndex++, clampToInt((long) z + radius));
}
else {
statement.setInt(parameterIndex++, x);
statement.setInt(parameterIndex++, y);
statement.setInt(parameterIndex, z);
}
}
try (ResultSet results = statement.executeQuery()) {
while (results.next()) {
result.add(parseMessageResult(connection, results, actionId));
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return result;
}
private static Integer getUserId(Connection connection, String user) throws Exception {
if (user == null || user.isEmpty() || user.equalsIgnoreCase("#global")) {
return null;
}
Integer cachedId = ConfigHandler.playerIdCache.get(user.toLowerCase(java.util.Locale.ROOT));
if (cachedId != null) {
return cachedId;
}
String collate = Config.getGlobal().MYSQL ? "" : " COLLATE NOCASE";
try (PreparedStatement statement = connection.prepareStatement("SELECT rowid FROM " + ConfigHandler.prefix + "user WHERE user = ?" + collate + " ORDER BY rowid ASC LIMIT 0, 1")) {
statement.setString(1, user);
try (ResultSet results = statement.executeQuery()) {
if (results.next()) {
int id = results.getInt("rowid");
ConfigHandler.playerIdCache.put(user.toLowerCase(java.util.Locale.ROOT), id);
ConfigHandler.playerIdCacheReversed.put(id, user);
return id;
}
}
}
return -1;
}
private static MessageResult parseMessageResult(Connection connection, ResultSet results, int actionId) throws Exception {
int userId = results.getInt("user");
String username = ConfigHandler.playerIdCacheReversed.get(userId);
if (username == null) {
username = UserStatement.loadName(connection, userId);
}
return new MessageResult(
results.getLong("time"), username, WorldUtils.getWorldName(results.getInt("wid")),
results.getInt("x"), results.getInt("y"), results.getInt("z"),
results.getString("message"), actionId
);
}
private static int clampToInt(long value) {
if (value > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
else if (value < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
return (int) value;
}
}
@@ -0,0 +1,69 @@
package net.coreprotect.api.result;
/**
* Represents a logged player chat message or command.
*/
public class MessageResult {
private final long time;
private final String username;
private final String world;
private final int x;
private final int y;
private final int z;
private final String message;
private final int actionId;
public MessageResult(long time, String username, String world, int x, int y, int z, String message, int actionId) {
this.time = time;
this.username = username;
this.world = world;
this.x = x;
this.y = y;
this.z = z;
this.message = message;
this.actionId = actionId;
}
public int getActionId() {
return actionId;
}
public String getActionString() {
switch (actionId) {
case 6:
return "chat";
case 7:
return "command";
default:
return "unknown";
}
}
public String getMessage() {
return message;
}
public String getPlayer() {
return username;
}
public long getTimestamp() {
return time * 1000L;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
public String worldName() {
return world;
}
}