Merge branch 'master' into q-apps

This commit is contained in:
CalDescent 2023-03-17 13:17:47 +00:00
commit 98b0b1932d
9 changed files with 136 additions and 40 deletions

View File

@ -40,6 +40,8 @@ import org.qortal.utils.Base58;
import com.google.common.primitives.Bytes; import com.google.common.primitives.Bytes;
import static org.qortal.data.chat.ChatMessage.Encoding;
@Path("/chat") @Path("/chat")
@Tag(name = "Chat") @Tag(name = "Chat")
public class ChatResource { public class ChatResource {
@ -73,6 +75,7 @@ public class ChatResource {
@QueryParam("chatreference") String chatReference, @QueryParam("chatreference") String chatReference,
@QueryParam("haschatreference") Boolean hasChatReference, @QueryParam("haschatreference") Boolean hasChatReference,
@QueryParam("sender") String sender, @QueryParam("sender") String sender,
@QueryParam("encoding") Encoding encoding,
@Parameter(ref = "limit") @QueryParam("limit") Integer limit, @Parameter(ref = "limit") @QueryParam("limit") Integer limit,
@Parameter(ref = "offset") @QueryParam("offset") Integer offset, @Parameter(ref = "offset") @QueryParam("offset") Integer offset,
@Parameter(ref = "reverse") @QueryParam("reverse") Boolean reverse) { @Parameter(ref = "reverse") @QueryParam("reverse") Boolean reverse) {
@ -109,6 +112,7 @@ public class ChatResource {
hasChatReference, hasChatReference,
involvingAddresses, involvingAddresses,
sender, sender,
encoding,
limit, offset, reverse); limit, offset, reverse);
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
@ -131,7 +135,7 @@ public class ChatResource {
} }
) )
@ApiErrors({ApiError.INVALID_CRITERIA, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.INVALID_CRITERIA, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public ChatMessage getMessageBySignature(@PathParam("signature") String signature58) { public ChatMessage getMessageBySignature(@PathParam("signature") String signature58, @QueryParam("encoding") Encoding encoding) {
byte[] signature = Base58.decode(signature58); byte[] signature = Base58.decode(signature58);
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
@ -141,7 +145,7 @@ public class ChatResource {
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "Message not found"); throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "Message not found");
} }
return repository.getChatRepository().toChatMessage(chatTransactionData); return repository.getChatRepository().toChatMessage(chatTransactionData, encoding);
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }
@ -164,12 +168,12 @@ public class ChatResource {
} }
) )
@ApiErrors({ApiError.INVALID_CRITERIA, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.INVALID_CRITERIA, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public ActiveChats getActiveChats(@PathParam("address") String address) { public ActiveChats getActiveChats(@PathParam("address") String address, @QueryParam("encoding") Encoding encoding) {
if (address == null || !Crypto.isValidAddress(address)) if (address == null || !Crypto.isValidAddress(address))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
return repository.getChatRepository().getActiveChats(address); return repository.getChatRepository().getActiveChats(address, encoding);
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }

View File

@ -2,7 +2,9 @@ package org.qortal.api.websocket;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.Session;
@ -21,6 +23,8 @@ import org.qortal.repository.DataException;
import org.qortal.repository.Repository; import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager; import org.qortal.repository.RepositoryManager;
import static org.qortal.data.chat.ChatMessage.Encoding;
@WebSocket @WebSocket
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class ActiveChatsWebSocket extends ApiWebSocket { public class ActiveChatsWebSocket extends ApiWebSocket {
@ -62,7 +66,9 @@ public class ActiveChatsWebSocket extends ApiWebSocket {
@OnWebSocketMessage @OnWebSocketMessage
public void onWebSocketMessage(Session session, String message) { public void onWebSocketMessage(Session session, String message) {
/* ignored */ if (Objects.equals(message, "ping")) {
session.getRemote().sendStringByFuture("pong");
}
} }
private void onNotify(Session session, ChatTransactionData chatTransactionData, String ourAddress, AtomicReference<String> previousOutput) { private void onNotify(Session session, ChatTransactionData chatTransactionData, String ourAddress, AtomicReference<String> previousOutput) {
@ -75,7 +81,7 @@ public class ActiveChatsWebSocket extends ApiWebSocket {
} }
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
ActiveChats activeChats = repository.getChatRepository().getActiveChats(ourAddress); ActiveChats activeChats = repository.getChatRepository().getActiveChats(ourAddress, getTargetEncoding(session));
StringWriter stringWriter = new StringWriter(); StringWriter stringWriter = new StringWriter();
@ -93,4 +99,12 @@ public class ActiveChatsWebSocket extends ApiWebSocket {
} }
} }
private Encoding getTargetEncoding(Session session) {
// Default to Base58 if not specified, for backwards support
Map<String, List<String>> queryParams = session.getUpgradeRequest().getParameterMap();
List<String> encodingList = queryParams.get("encoding");
String encoding = (encodingList != null && encodingList.size() == 1) ? encodingList.get(0) : "BASE58";
return Encoding.valueOf(encoding);
}
} }

View File

@ -2,10 +2,7 @@ package org.qortal.api.websocket;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Arrays; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
@ -22,6 +19,8 @@ import org.qortal.repository.DataException;
import org.qortal.repository.Repository; import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager; import org.qortal.repository.RepositoryManager;
import static org.qortal.data.chat.ChatMessage.Encoding;
@WebSocket @WebSocket
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class ChatMessagesWebSocket extends ApiWebSocket { public class ChatMessagesWebSocket extends ApiWebSocket {
@ -35,6 +34,16 @@ public class ChatMessagesWebSocket extends ApiWebSocket {
@Override @Override
public void onWebSocketConnect(Session session) { public void onWebSocketConnect(Session session) {
Map<String, List<String>> queryParams = session.getUpgradeRequest().getParameterMap(); Map<String, List<String>> queryParams = session.getUpgradeRequest().getParameterMap();
Encoding encoding = getTargetEncoding(session);
List<String> limitList = queryParams.get("limit");
Integer limit = (limitList != null && limitList.size() == 1) ? Integer.parseInt(limitList.get(0)) : null;
List<String> offsetList = queryParams.get("offset");
Integer offset = (offsetList != null && offsetList.size() == 1) ? Integer.parseInt(offsetList.get(0)) : null;
List<String> reverseList = queryParams.get("offset");
Boolean reverse = (reverseList != null && reverseList.size() == 1) ? Boolean.getBoolean(reverseList.get(0)) : null;
List<String> txGroupIds = queryParams.get("txGroupId"); List<String> txGroupIds = queryParams.get("txGroupId");
if (txGroupIds != null && txGroupIds.size() == 1) { if (txGroupIds != null && txGroupIds.size() == 1) {
@ -50,7 +59,8 @@ public class ChatMessagesWebSocket extends ApiWebSocket {
null, null,
null, null,
null, null,
null, null, null); encoding,
limit, offset, reverse);
sendMessages(session, chatMessages); sendMessages(session, chatMessages);
} catch (DataException e) { } catch (DataException e) {
@ -81,7 +91,8 @@ public class ChatMessagesWebSocket extends ApiWebSocket {
null, null,
involvingAddresses, involvingAddresses,
null, null,
null, null, null); encoding,
limit, offset, reverse);
sendMessages(session, chatMessages); sendMessages(session, chatMessages);
} catch (DataException e) { } catch (DataException e) {
@ -107,7 +118,9 @@ public class ChatMessagesWebSocket extends ApiWebSocket {
@OnWebSocketMessage @OnWebSocketMessage
public void onWebSocketMessage(Session session, String message) { public void onWebSocketMessage(Session session, String message) {
/* ignored */ if (Objects.equals(message, "ping")) {
session.getRemote().sendStringByFuture("pong");
}
} }
private void onNotify(Session session, ChatTransactionData chatTransactionData, int txGroupId) { private void onNotify(Session session, ChatTransactionData chatTransactionData, int txGroupId) {
@ -155,7 +168,7 @@ public class ChatMessagesWebSocket extends ApiWebSocket {
// Convert ChatTransactionData to ChatMessage // Convert ChatTransactionData to ChatMessage
ChatMessage chatMessage; ChatMessage chatMessage;
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
chatMessage = repository.getChatRepository().toChatMessage(chatTransactionData); chatMessage = repository.getChatRepository().toChatMessage(chatTransactionData, getTargetEncoding(session));
} catch (DataException e) { } catch (DataException e) {
// No output this time? // No output this time?
return; return;
@ -164,4 +177,12 @@ public class ChatMessagesWebSocket extends ApiWebSocket {
sendMessages(session, Collections.singletonList(chatMessage)); sendMessages(session, Collections.singletonList(chatMessage));
} }
private Encoding getTargetEncoding(Session session) {
// Default to Base58 if not specified, for backwards support
Map<String, List<String>> queryParams = session.getUpgradeRequest().getParameterMap();
List<String> encodingList = queryParams.get("encoding");
String encoding = (encodingList != null && encodingList.size() == 1) ? encodingList.get(0) : "BASE58";
return Encoding.valueOf(encoding);
}
} }

View File

@ -1,10 +1,15 @@
package org.qortal.data.chat; package org.qortal.data.chat;
import org.bouncycastle.util.encoders.Base64;
import org.qortal.utils.Base58;
import java.util.List; import java.util.List;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import static org.qortal.data.chat.ChatMessage.Encoding;
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public class ActiveChats { public class ActiveChats {
@ -18,20 +23,38 @@ public class ActiveChats {
private String sender; private String sender;
private String senderName; private String senderName;
private byte[] signature; private byte[] signature;
private byte[] data; private Encoding encoding;
private String data;
protected GroupChat() { protected GroupChat() {
/* JAXB */ /* JAXB */
} }
public GroupChat(int groupId, String groupName, Long timestamp, String sender, String senderName, byte[] signature, byte[] data) { public GroupChat(int groupId, String groupName, Long timestamp, String sender, String senderName,
byte[] signature, Encoding encoding, byte[] data) {
this.groupId = groupId; this.groupId = groupId;
this.groupName = groupName; this.groupName = groupName;
this.timestamp = timestamp; this.timestamp = timestamp;
this.sender = sender; this.sender = sender;
this.senderName = senderName; this.senderName = senderName;
this.signature = signature; this.signature = signature;
this.data = data; this.encoding = encoding != null ? encoding : Encoding.BASE58;
if (data != null) {
switch (this.encoding) {
case BASE64:
this.data = Base64.toBase64String(data);
break;
case BASE58:
default:
this.data = Base58.encode(data);
break;
}
}
else {
this.data = null;
}
} }
public int getGroupId() { public int getGroupId() {
@ -58,7 +81,7 @@ public class ActiveChats {
return this.signature; return this.signature;
} }
public byte[] getData() { public String getData() {
return this.data; return this.data;
} }
} }

View File

@ -1,11 +1,19 @@
package org.qortal.data.chat; package org.qortal.data.chat;
import org.bouncycastle.util.encoders.Base64;
import org.qortal.utils.Base58;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public class ChatMessage { public class ChatMessage {
public enum Encoding {
BASE58,
BASE64
}
// Properties // Properties
private long timestamp; private long timestamp;
@ -29,7 +37,9 @@ public class ChatMessage {
private byte[] chatReference; private byte[] chatReference;
private byte[] data; private Encoding encoding;
private String data;
private boolean isText; private boolean isText;
private boolean isEncrypted; private boolean isEncrypted;
@ -44,8 +54,8 @@ public class ChatMessage {
// For repository use // For repository use
public ChatMessage(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String sender, public ChatMessage(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String sender,
String senderName, String recipient, String recipientName, byte[] chatReference, byte[] data, String senderName, String recipient, String recipientName, byte[] chatReference,
boolean isText, boolean isEncrypted, byte[] signature) { Encoding encoding, byte[] data, boolean isText, boolean isEncrypted, byte[] signature) {
this.timestamp = timestamp; this.timestamp = timestamp;
this.txGroupId = txGroupId; this.txGroupId = txGroupId;
this.reference = reference; this.reference = reference;
@ -55,7 +65,24 @@ public class ChatMessage {
this.recipient = recipient; this.recipient = recipient;
this.recipientName = recipientName; this.recipientName = recipientName;
this.chatReference = chatReference; this.chatReference = chatReference;
this.data = data; this.encoding = encoding != null ? encoding : Encoding.BASE58;
if (data != null) {
switch (this.encoding) {
case BASE64:
this.data = Base64.toBase64String(data);
break;
case BASE58:
default:
this.data = Base58.encode(data);
break;
}
}
else {
this.data = null;
}
this.isText = isText; this.isText = isText;
this.isEncrypted = isEncrypted; this.isEncrypted = isEncrypted;
this.signature = signature; this.signature = signature;
@ -97,7 +124,7 @@ public class ChatMessage {
return this.chatReference; return this.chatReference;
} }
public byte[] getData() { public String getData() {
return this.data; return this.data;
} }

View File

@ -6,6 +6,8 @@ import org.qortal.data.chat.ActiveChats;
import org.qortal.data.chat.ChatMessage; import org.qortal.data.chat.ChatMessage;
import org.qortal.data.transaction.ChatTransactionData; import org.qortal.data.transaction.ChatTransactionData;
import static org.qortal.data.chat.ChatMessage.Encoding;
public interface ChatRepository { public interface ChatRepository {
/** /**
@ -15,10 +17,11 @@ public interface ChatRepository {
*/ */
public List<ChatMessage> getMessagesMatchingCriteria(Long before, Long after, public List<ChatMessage> getMessagesMatchingCriteria(Long before, Long after,
Integer txGroupId, byte[] reference, byte[] chatReferenceBytes, Boolean hasChatReference, Integer txGroupId, byte[] reference, byte[] chatReferenceBytes, Boolean hasChatReference,
List<String> involving, String senderAddress, Integer limit, Integer offset, Boolean reverse) throws DataException; List<String> involving, String senderAddress, Encoding encoding,
Integer limit, Integer offset, Boolean reverse) throws DataException;
public ChatMessage toChatMessage(ChatTransactionData chatTransactionData) throws DataException; public ChatMessage toChatMessage(ChatTransactionData chatTransactionData, Encoding encoding) throws DataException;
public ActiveChats getActiveChats(String address) throws DataException; public ActiveChats getActiveChats(String address, Encoding encoding) throws DataException;
} }

View File

@ -14,6 +14,8 @@ import org.qortal.repository.ChatRepository;
import org.qortal.repository.DataException; import org.qortal.repository.DataException;
import org.qortal.transaction.Transaction.TransactionType; import org.qortal.transaction.Transaction.TransactionType;
import static org.qortal.data.chat.ChatMessage.Encoding;
public class HSQLDBChatRepository implements ChatRepository { public class HSQLDBChatRepository implements ChatRepository {
protected HSQLDBRepository repository; protected HSQLDBRepository repository;
@ -24,8 +26,8 @@ public class HSQLDBChatRepository implements ChatRepository {
@Override @Override
public List<ChatMessage> getMessagesMatchingCriteria(Long before, Long after, Integer txGroupId, byte[] referenceBytes, public List<ChatMessage> getMessagesMatchingCriteria(Long before, Long after, Integer txGroupId, byte[] referenceBytes,
byte[] chatReferenceBytes, Boolean hasChatReference, List<String> involving, String senderAddress, byte[] chatReferenceBytes, Boolean hasChatReference, List<String> involving, String senderAddress,
Integer limit, Integer offset, Boolean reverse) throws DataException { Encoding encoding, Integer limit, Integer offset, Boolean reverse) throws DataException {
// Check args meet expectations // Check args meet expectations
if ((txGroupId != null && involving != null && !involving.isEmpty()) if ((txGroupId != null && involving != null && !involving.isEmpty())
|| (txGroupId == null && (involving == null || involving.size() != 2))) || (txGroupId == null && (involving == null || involving.size() != 2)))
@ -127,7 +129,7 @@ public class HSQLDBChatRepository implements ChatRepository {
byte[] signature = resultSet.getBytes(13); byte[] signature = resultSet.getBytes(13);
ChatMessage chatMessage = new ChatMessage(timestamp, groupId, reference, senderPublicKey, sender, ChatMessage chatMessage = new ChatMessage(timestamp, groupId, reference, senderPublicKey, sender,
senderName, recipient, recipientName, chatReference, data, isText, isEncrypted, signature); senderName, recipient, recipientName, chatReference, encoding, data, isText, isEncrypted, signature);
chatMessages.add(chatMessage); chatMessages.add(chatMessage);
} while (resultSet.next()); } while (resultSet.next());
@ -139,7 +141,7 @@ public class HSQLDBChatRepository implements ChatRepository {
} }
@Override @Override
public ChatMessage toChatMessage(ChatTransactionData chatTransactionData) throws DataException { public ChatMessage toChatMessage(ChatTransactionData chatTransactionData, Encoding encoding) throws DataException {
String sql = "SELECT SenderNames.name, RecipientNames.name " String sql = "SELECT SenderNames.name, RecipientNames.name "
+ "FROM ChatTransactions " + "FROM ChatTransactions "
+ "LEFT OUTER JOIN Names AS SenderNames ON SenderNames.owner = sender " + "LEFT OUTER JOIN Names AS SenderNames ON SenderNames.owner = sender "
@ -166,21 +168,22 @@ public class HSQLDBChatRepository implements ChatRepository {
byte[] signature = chatTransactionData.getSignature(); byte[] signature = chatTransactionData.getSignature();
return new ChatMessage(timestamp, groupId, reference, senderPublicKey, sender, return new ChatMessage(timestamp, groupId, reference, senderPublicKey, sender,
senderName, recipient, recipientName, chatReference, data, isText, isEncrypted, signature); senderName, recipient, recipientName, chatReference, encoding, data,
isText, isEncrypted, signature);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch convert chat transaction from repository", e); throw new DataException("Unable to fetch convert chat transaction from repository", e);
} }
} }
@Override @Override
public ActiveChats getActiveChats(String address) throws DataException { public ActiveChats getActiveChats(String address, Encoding encoding) throws DataException {
List<GroupChat> groupChats = getActiveGroupChats(address); List<GroupChat> groupChats = getActiveGroupChats(address, encoding);
List<DirectChat> directChats = getActiveDirectChats(address); List<DirectChat> directChats = getActiveDirectChats(address);
return new ActiveChats(groupChats, directChats); return new ActiveChats(groupChats, directChats);
} }
private List<GroupChat> getActiveGroupChats(String address) throws DataException { private List<GroupChat> getActiveGroupChats(String address, Encoding encoding) throws DataException {
// Find groups where address is a member and potential latest message details // 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 " String groupsSql = "SELECT group_id, group_name, latest_timestamp, sender, sender_name, signature, data "
+ "FROM GroupMembers " + "FROM GroupMembers "
@ -213,7 +216,7 @@ public class HSQLDBChatRepository implements ChatRepository {
byte[] signature = resultSet.getBytes(6); byte[] signature = resultSet.getBytes(6);
byte[] data = resultSet.getBytes(7); byte[] data = resultSet.getBytes(7);
GroupChat groupChat = new GroupChat(groupId, groupName, timestamp, sender, senderName, signature, data); GroupChat groupChat = new GroupChat(groupId, groupName, timestamp, sender, senderName, signature, encoding, data);
groupChats.add(groupChat); groupChats.add(groupChat);
} while (resultSet.next()); } while (resultSet.next());
} }
@ -247,7 +250,7 @@ public class HSQLDBChatRepository implements ChatRepository {
data = resultSet.getBytes(5); data = resultSet.getBytes(5);
} }
GroupChat groupChat = new GroupChat(0, null, timestamp, sender, senderName, signature, data); GroupChat groupChat = new GroupChat(0, null, timestamp, sender, senderName, signature, encoding, data);
groupChats.add(groupChat); groupChats.add(groupChat);
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch active group chats from repository", e); throw new DataException("Unable to fetch active group chats from repository", e);

View File

@ -9,6 +9,7 @@ import org.qortal.crosschain.BitcoinACCTv1;
import org.qortal.crypto.Crypto; import org.qortal.crypto.Crypto;
import org.qortal.data.account.AccountBalanceData; import org.qortal.data.account.AccountBalanceData;
import org.qortal.data.account.AccountData; import org.qortal.data.account.AccountData;
import org.qortal.data.chat.ChatMessage;
import org.qortal.repository.DataException; import org.qortal.repository.DataException;
import org.qortal.repository.Repository; import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager; import org.qortal.repository.RepositoryManager;
@ -417,7 +418,7 @@ public class RepositoryTests extends Common {
try (final HSQLDBRepository hsqldb = (HSQLDBRepository) RepositoryManager.getRepository()) { try (final HSQLDBRepository hsqldb = (HSQLDBRepository) RepositoryManager.getRepository()) {
String address = Crypto.toAddress(new byte[32]); String address = Crypto.toAddress(new byte[32]);
hsqldb.getChatRepository().getActiveChats(address); hsqldb.getChatRepository().getActiveChats(address, ChatMessage.Encoding.BASE58);
} catch (DataException e) { } catch (DataException e) {
fail("HSQLDB bug #1580"); fail("HSQLDB bug #1580");
} }

View File

@ -8,11 +8,11 @@ if [ -z "$*" ]; then
echo "Usage:" echo "Usage:"
echo echo
echo "Host/update data:" echo "Host/update data:"
echo "qdata POST [service] [name] PATH [dirpath] <identifier>" echo "qdn POST [service] [name] PATH [dirpath] <identifier>"
echo "qdata POST [service] [name] STRING [data-string] <identifier>" echo "qdn POST [service] [name] STRING [data-string] <identifier>"
echo echo
echo "Fetch data:" echo "Fetch data:"
echo "qdata GET [service] [name] <identifier-or-default> <filepath-or-default> <rebuild>" echo "qdn GET [service] [name] <identifier-or-default> <filepath-or-default> <rebuild>"
echo echo
echo "Notes:" echo "Notes:"
echo "- When requesting a resource, please use 'default' to indicate a file with no identifier." echo "- When requesting a resource, please use 'default' to indicate a file with no identifier."