Skip to content

Commit

Permalink
add haschatreference query to activechats endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Philreact committed Dec 1, 2024
1 parent 8ffb062 commit 61dec0e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 26 deletions.
12 changes: 8 additions & 4 deletions src/main/java/org/qortal/api/resource/ChatResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -234,17 +234,21 @@ public ChatMessage getMessageBySignature(@PathParam("signature") String signatur
}
)
@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",
Expand Down
20 changes: 19 additions & 1 deletion src/main/java/org/qortal/api/websocket/ActiveChatsWebSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ private void onNotify(Session session, ChatTransactionData chatTransactionData,
}

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();

Expand All @@ -103,4 +105,20 @@ private Encoding getTargetEncoding(Session session) {
return Encoding.valueOf(encoding);
}

private Boolean getHasChatReference(Session session) {
Map<String, List<String>> queryParams = session.getUpgradeRequest().getParameterMap();
List<String> 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
}

}
2 changes: 1 addition & 1 deletion src/main/java/org/qortal/repository/ChatRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ public List<ChatMessage> getMessagesMatchingCriteria(Long before, Long after,

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;

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class HSQLDBChatRepository implements ChatRepository {
public HSQLDBChatRepository(HSQLDBRepository repository) {
this.repository = repository;
}

@Override
public List<ChatMessage> getMessagesMatchingCriteria(Long before, Long after, Integer txGroupId, byte[] referenceBytes,
byte[] chatReferenceBytes, Boolean hasChatReference, List<String> involving, String senderAddress,
Expand Down Expand Up @@ -176,14 +176,14 @@ public ChatMessage toChatMessage(ChatTransactionData chatTransactionData, Encodi
}

@Override
public ActiveChats getActiveChats(String address, Encoding encoding) throws DataException {
List<GroupChat> groupChats = getActiveGroupChats(address, encoding);
List<DirectChat> directChats = getActiveDirectChats(address);
public ActiveChats getActiveChats(String address, Encoding encoding, Boolean hasChatReference) throws DataException {
List<GroupChat> groupChats = getActiveGroupChats(address, encoding, hasChatReference);
List<DirectChat> directChats = getActiveDirectChats(address, hasChatReference);

return new ActiveChats(groupChats, directChats);
}

private List<GroupChat> getActiveGroupChats(String address, Encoding encoding) throws DataException {
private List<GroupChat> 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 "
Expand All @@ -194,11 +194,19 @@ private List<GroupChat> getActiveGroupChats(String address, Encoding encoding) t
+ "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<GroupChat> groupChats = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(groupsSql, address)) {
Expand Down Expand Up @@ -230,8 +238,16 @@ private List<GroupChat> getActiveGroupChats(String address, Encoding encoding) t
+ "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)) {
Expand Down Expand Up @@ -259,7 +275,7 @@ private List<GroupChat> getActiveGroupChats(String address, Encoding encoding) t
return groupChats;
}

private List<DirectChat> getActiveDirectChats(String address) throws DataException {
private List<DirectChat> getActiveDirectChats(String address, Boolean hasChatReference) throws DataException {
// Find chat messages involving address
String directSql = "SELECT other_address, name, latest_timestamp, sender, sender_name "
+ "FROM ("
Expand All @@ -275,11 +291,21 @@ private List<DirectChat> getActiveDirectChats(String address) throws DataExcepti
+ "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 };

Expand Down
11 changes: 9 additions & 2 deletions src/test/java/org/qortal/test/RepositoryTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -411,13 +411,20 @@ public void testAtLateral() {
}
}

/** 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");
}
Expand Down

0 comments on commit 61dec0e

Please sign in to comment.