From 61dec0e4b7e463febc78974d107231c56b48c5b7 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Sun, 1 Dec 2024 12:38:38 +0200 Subject: [PATCH] add haschatreference query to activechats endpoint --- .../org/qortal/api/resource/ChatResource.java | 12 ++-- .../api/websocket/ActiveChatsWebSocket.java | 20 +++++- .../org/qortal/repository/ChatRepository.java | 2 +- .../hsqldb/HSQLDBChatRepository.java | 62 +++++++++++++------ .../java/org/qortal/test/RepositoryTests.java | 11 +++- 5 files changed, 81 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/qortal/api/resource/ChatResource.java b/src/main/java/org/qortal/api/resource/ChatResource.java index 66a2bd46..df2ca399 100644 --- a/src/main/java/org/qortal/api/resource/ChatResource.java +++ b/src/main/java/org/qortal/api/resource/ChatResource.java @@ -234,17 +234,21 @@ public class ChatResource { } ) @ApiErrors({ApiError.INVALID_CRITERIA, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) - public ActiveChats getActiveChats(@PathParam("address") String address, @QueryParam("encoding") Encoding encoding) { + public ActiveChats getActiveChats( + @PathParam("address") String address, + @QueryParam("encoding") Encoding encoding, + @QueryParam("haschatreference") Boolean hasChatReference + ) { if (address == null || !Crypto.isValidAddress(address)) throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); - + try (final Repository repository = RepositoryManager.getRepository()) { - return repository.getChatRepository().getActiveChats(address, encoding); + return repository.getChatRepository().getActiveChats(address, encoding, hasChatReference); } catch (DataException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); } } - + @POST @Operation( summary = "Build raw, unsigned, CHAT transaction", diff --git a/src/main/java/org/qortal/api/websocket/ActiveChatsWebSocket.java b/src/main/java/org/qortal/api/websocket/ActiveChatsWebSocket.java index b92fb19f..ca3ef2b3 100644 --- a/src/main/java/org/qortal/api/websocket/ActiveChatsWebSocket.java +++ b/src/main/java/org/qortal/api/websocket/ActiveChatsWebSocket.java @@ -77,7 +77,9 @@ public class ActiveChatsWebSocket extends ApiWebSocket { } try (final Repository repository = RepositoryManager.getRepository()) { - ActiveChats activeChats = repository.getChatRepository().getActiveChats(ourAddress, getTargetEncoding(session)); + Boolean hasChatReference = getHasChatReference(session); + + ActiveChats activeChats = repository.getChatRepository().getActiveChats(ourAddress, getTargetEncoding(session), hasChatReference); StringWriter stringWriter = new StringWriter(); @@ -103,4 +105,20 @@ public class ActiveChatsWebSocket extends ApiWebSocket { return Encoding.valueOf(encoding); } + private Boolean getHasChatReference(Session session) { + Map> queryParams = session.getUpgradeRequest().getParameterMap(); + List hasChatReferenceList = queryParams.get("haschatreference"); + + // Return null if not specified + if (hasChatReferenceList != null && hasChatReferenceList.size() == 1) { + String value = hasChatReferenceList.get(0).toLowerCase(); + if (value.equals("true")) { + return true; + } else if (value.equals("false")) { + return false; + } + } + return null; // Ignored if not present + } + } diff --git a/src/main/java/org/qortal/repository/ChatRepository.java b/src/main/java/org/qortal/repository/ChatRepository.java index d046fe6b..bd636fe3 100644 --- a/src/main/java/org/qortal/repository/ChatRepository.java +++ b/src/main/java/org/qortal/repository/ChatRepository.java @@ -22,6 +22,6 @@ public interface ChatRepository { public ChatMessage toChatMessage(ChatTransactionData chatTransactionData, Encoding encoding) throws DataException; - public ActiveChats getActiveChats(String address, Encoding encoding) throws DataException; + public ActiveChats getActiveChats(String address, Encoding encoding, Boolean hasChatReference) throws DataException; } diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBChatRepository.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBChatRepository.java index 571a587d..80865739 100644 --- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBChatRepository.java +++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBChatRepository.java @@ -23,7 +23,7 @@ public class HSQLDBChatRepository implements ChatRepository { public HSQLDBChatRepository(HSQLDBRepository repository) { this.repository = repository; } - + @Override public List getMessagesMatchingCriteria(Long before, Long after, Integer txGroupId, byte[] referenceBytes, byte[] chatReferenceBytes, Boolean hasChatReference, List involving, String senderAddress, @@ -176,14 +176,14 @@ public class HSQLDBChatRepository implements ChatRepository { } @Override - public ActiveChats getActiveChats(String address, Encoding encoding) throws DataException { - List groupChats = getActiveGroupChats(address, encoding); - List directChats = getActiveDirectChats(address); + public ActiveChats getActiveChats(String address, Encoding encoding, Boolean hasChatReference) throws DataException { + List groupChats = getActiveGroupChats(address, encoding, hasChatReference); + List directChats = getActiveDirectChats(address, hasChatReference); return new ActiveChats(groupChats, directChats); } - - private List getActiveGroupChats(String address, Encoding encoding) throws DataException { + + private List getActiveGroupChats(String address, Encoding encoding, Boolean hasChatReference) throws DataException { // Find groups where address is a member and potential latest message details String groupsSql = "SELECT group_id, group_name, latest_timestamp, sender, sender_name, signature, data " + "FROM GroupMembers " @@ -194,11 +194,19 @@ public class HSQLDBChatRepository implements ChatRepository { + "JOIN Transactions USING (signature) " + "LEFT OUTER JOIN Names AS SenderNames ON SenderNames.owner = sender " // NOTE: We need to qualify "Groups.group_id" here to avoid "General error" bug in HSQLDB v2.5.0 - + "WHERE tx_group_id = Groups.group_id AND type = " + TransactionType.CHAT.value + " " - + "ORDER BY created_when DESC " + + "WHERE tx_group_id = Groups.group_id AND type = " + TransactionType.CHAT.value + " "; + + if (hasChatReference != null) { + if (hasChatReference) { + groupsSql += "AND chat_reference IS NOT NULL "; + } else { + groupsSql += "AND chat_reference IS NULL "; + } + } + groupsSql += "ORDER BY created_when DESC " + "LIMIT 1" - + ") AS LatestMessages ON TRUE " - + "WHERE address = ?"; + + ") AS LatestMessages ON TRUE " + + "WHERE address = ?"; List groupChats = new ArrayList<>(); try (ResultSet resultSet = this.repository.checkedExecute(groupsSql, address)) { @@ -230,8 +238,16 @@ public class HSQLDBChatRepository implements ChatRepository { + "JOIN Transactions USING (signature) " + "LEFT OUTER JOIN Names AS SenderNames ON SenderNames.owner = sender " + "WHERE tx_group_id = 0 " - + "AND recipient IS NULL " - + "ORDER BY created_when DESC " + + "AND recipient IS NULL "; + + if (hasChatReference != null) { + if (hasChatReference) { + grouplessSql += "AND chat_reference IS NOT NULL "; + } else { + grouplessSql += "AND chat_reference IS NULL "; + } + } + grouplessSql += "ORDER BY created_when DESC " + "LIMIT 1"; try (ResultSet resultSet = this.repository.checkedExecute(grouplessSql)) { @@ -259,7 +275,7 @@ public class HSQLDBChatRepository implements ChatRepository { return groupChats; } - private List getActiveDirectChats(String address) throws DataException { + private List getActiveDirectChats(String address, Boolean hasChatReference) throws DataException { // Find chat messages involving address String directSql = "SELECT other_address, name, latest_timestamp, sender, sender_name " + "FROM (" @@ -275,11 +291,21 @@ public class HSQLDBChatRepository implements ChatRepository { + "NATURAL JOIN Transactions " + "LEFT OUTER JOIN Names AS SenderNames ON SenderNames.owner = sender " + "WHERE (sender = other_address AND recipient = ?) " - + "OR (sender = ? AND recipient = other_address) " - + "ORDER BY created_when DESC " - + "LIMIT 1" - + ") AS LatestMessages " - + "LEFT OUTER JOIN Names ON owner = other_address"; + + "OR (sender = ? AND recipient = other_address) "; + + // Apply hasChatReference filter + if (hasChatReference != null) { + if (hasChatReference) { + directSql += "AND chat_reference IS NOT NULL "; + } else { + directSql += "AND chat_reference IS NULL "; + } + } + + directSql += "ORDER BY created_when DESC " + + "LIMIT 1" + + ") AS LatestMessages " + + "LEFT OUTER JOIN Names ON owner = other_address"; Object[] bindParams = new Object[] { address, address, address, address }; diff --git a/src/test/java/org/qortal/test/RepositoryTests.java b/src/test/java/org/qortal/test/RepositoryTests.java index 0d07be4b..1b0a0e52 100644 --- a/src/test/java/org/qortal/test/RepositoryTests.java +++ b/src/test/java/org/qortal/test/RepositoryTests.java @@ -411,13 +411,20 @@ public class RepositoryTests extends Common { } } - /** Specifically test LATERAL() usage in Chat repository */ + /** Specifically test LATERAL() usage in Chat repository with hasChatReference */ @Test public void testChatLateral() { try (final HSQLDBRepository hsqldb = (HSQLDBRepository) RepositoryManager.getRepository()) { String address = Crypto.toAddress(new byte[32]); - hsqldb.getChatRepository().getActiveChats(address, ChatMessage.Encoding.BASE58); + // Test without hasChatReference + hsqldb.getChatRepository().getActiveChats(address, ChatMessage.Encoding.BASE58, null); + + // Test with hasChatReference = true + hsqldb.getChatRepository().getActiveChats(address, ChatMessage.Encoding.BASE58, true); + + // Test with hasChatReference = false + hsqldb.getChatRepository().getActiveChats(address, ChatMessage.Encoding.BASE58, false); } catch (DataException e) { fail("HSQLDB bug #1580"); }