import org.asamk.signal.storage.contacts.ContactInfo;
import org.asamk.signal.storage.contacts.JsonContactsStore;
import org.asamk.signal.storage.groups.GroupInfo;
+import org.asamk.signal.storage.groups.GroupInfoV1;
import org.asamk.signal.storage.groups.JsonGroupStore;
import org.asamk.signal.storage.profiles.ProfileStore;
import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
import org.asamk.signal.storage.protocol.RecipientStore;
import org.asamk.signal.storage.protocol.SessionInfo;
import org.asamk.signal.storage.protocol.SignalServiceAddressResolver;
+import org.asamk.signal.storage.stickers.StickerStore;
import org.asamk.signal.storage.threads.LegacyJsonThreadStore;
import org.asamk.signal.storage.threads.ThreadInfo;
import org.asamk.signal.util.IOUtils;
private JsonContactsStore contactStore;
private RecipientStore recipientStore;
private ProfileStore profileStore;
+ private StickerStore stickerStore;
private SignalAccount(final FileChannel fileChannel, final FileLock lock) {
this.fileChannel = fileChannel;
final Pair<FileChannel, FileLock> pair = openFileChannel(fileName);
try {
SignalAccount account = new SignalAccount(pair.first(), pair.second());
- account.load();
+ account.load(dataPath);
return account;
} catch (Throwable e) {
pair.second().close();
}
}
- public static SignalAccount create(String dataPath, String username, IdentityKeyPair identityKey, int registrationId, ProfileKey profileKey) throws IOException {
+ public static SignalAccount create(
+ String dataPath, String username, IdentityKeyPair identityKey, int registrationId, ProfileKey profileKey
+ ) throws IOException {
IOUtils.createPrivateDirectories(dataPath);
String fileName = getFileName(dataPath, username);
if (!new File(fileName).exists()) {
account.username = username;
account.profileKey = profileKey;
account.signalProtocolStore = new JsonSignalProtocolStore(identityKey, registrationId);
- account.groupStore = new JsonGroupStore();
+ account.groupStore = new JsonGroupStore(getGroupCachePath(dataPath, username));
account.contactStore = new JsonContactsStore();
account.recipientStore = new RecipientStore();
account.profileStore = new ProfileStore();
+ account.stickerStore = new StickerStore();
account.registered = false;
return account;
}
- public static SignalAccount createLinkedAccount(String dataPath, String username, UUID uuid, String password, int deviceId, IdentityKeyPair identityKey, int registrationId, String signalingKey, ProfileKey profileKey) throws IOException {
+ public static SignalAccount createLinkedAccount(
+ String dataPath,
+ String username,
+ UUID uuid,
+ String password,
+ int deviceId,
+ IdentityKeyPair identityKey,
+ int registrationId,
+ String signalingKey,
+ ProfileKey profileKey
+ ) throws IOException {
IOUtils.createPrivateDirectories(dataPath);
String fileName = getFileName(dataPath, username);
if (!new File(fileName).exists()) {
account.deviceId = deviceId;
account.signalingKey = signalingKey;
account.signalProtocolStore = new JsonSignalProtocolStore(identityKey, registrationId);
- account.groupStore = new JsonGroupStore();
+ account.groupStore = new JsonGroupStore(getGroupCachePath(dataPath, username));
account.contactStore = new JsonContactsStore();
account.recipientStore = new RecipientStore();
account.profileStore = new ProfileStore();
+ account.stickerStore = new StickerStore();
account.registered = true;
account.isMultiDevice = true;
return dataPath + "/" + username;
}
+ private static File getGroupCachePath(String dataPath, String username) {
+ return new File(new File(dataPath, username + ".d"), "group-cache");
+ }
+
public static boolean userExists(String dataPath, String username) {
if (username == null) {
return false;
return !(!f.exists() || f.isDirectory());
}
- private void load() throws IOException {
+ private void load(String dataPath) throws IOException {
JsonNode rootNode;
synchronized (fileChannel) {
fileChannel.position(0);
try {
profileKey = new ProfileKey(Base64.decode(Util.getNotNullNode(rootNode, "profileKey").asText()));
} catch (InvalidInputException e) {
- throw new IOException("Config file contains an invalid profileKey, needs to be base64 encoded array of 32 bytes", e);
+ throw new IOException(
+ "Config file contains an invalid profileKey, needs to be base64 encoded array of 32 bytes",
+ e);
}
}
- signalProtocolStore = jsonProcessor.convertValue(Util.getNotNullNode(rootNode, "axolotlStore"), JsonSignalProtocolStore.class);
+ signalProtocolStore = jsonProcessor.convertValue(Util.getNotNullNode(rootNode, "axolotlStore"),
+ JsonSignalProtocolStore.class);
registered = Util.getNotNullNode(rootNode, "registered").asBoolean();
JsonNode groupStoreNode = rootNode.get("groupStore");
if (groupStoreNode != null) {
groupStore = jsonProcessor.convertValue(groupStoreNode, JsonGroupStore.class);
+ groupStore.groupCachePath = getGroupCachePath(dataPath, username);
}
if (groupStore == null) {
- groupStore = new JsonGroupStore();
+ groupStore = new JsonGroupStore(getGroupCachePath(dataPath, username));
}
JsonNode contactStoreNode = rootNode.get("contactStore");
}
for (GroupInfo group : groupStore.getGroups()) {
- group.members = group.members.stream()
- .map(m -> recipientStore.resolveServiceAddress(m))
- .collect(Collectors.toSet());
+ if (group instanceof GroupInfoV1) {
+ GroupInfoV1 groupInfoV1 = (GroupInfoV1) group;
+ groupInfoV1.members = groupInfoV1.members.stream()
+ .map(m -> recipientStore.resolveServiceAddress(m))
+ .collect(Collectors.toSet());
+ }
}
for (SessionInfo session : signalProtocolStore.getSessions()) {
profileStore = new ProfileStore();
}
+ JsonNode stickerStoreNode = rootNode.get("stickerStore");
+ if (stickerStoreNode != null) {
+ stickerStore = jsonProcessor.convertValue(stickerStoreNode, StickerStore.class);
+ }
+ if (stickerStore == null) {
+ stickerStore = new StickerStore();
+ }
+
JsonNode threadStoreNode = rootNode.get("threadStore");
if (threadStoreNode != null) {
- LegacyJsonThreadStore threadStore = jsonProcessor.convertValue(threadStoreNode, LegacyJsonThreadStore.class);
+ LegacyJsonThreadStore threadStore = jsonProcessor.convertValue(threadStoreNode,
+ LegacyJsonThreadStore.class);
// Migrate thread info to group and contact store
for (ThreadInfo thread : threadStore.getThreads()) {
if (thread.id == null || thread.id.isEmpty()) {
contactStore.updateContact(contactInfo);
} else {
GroupInfo groupInfo = groupStore.getGroup(Base64.decode(thread.id));
- if (groupInfo != null) {
- groupInfo.messageExpirationTime = thread.messageExpirationTime;
+ if (groupInfo instanceof GroupInfoV1) {
+ ((GroupInfoV1) groupInfo).messageExpirationTime = thread.messageExpirationTime;
groupStore.updateGroup(groupInfo);
}
}
.putPOJO("contactStore", contactStore)
.putPOJO("recipientStore", recipientStore)
.putPOJO("profileStore", profileStore)
- ;
+ .putPOJO("stickerStore", stickerStore);
try {
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
// Write to memory first to prevent corrupting the file in case of serialization errors
return profileStore;
}
+ public StickerStore getStickerStore() {
+ return stickerStore;
+ }
+
public String getUsername() {
return username;
}