]> nmode's Git Repositories - signal-cli/commitdiff
Implement a sticker store
authorAsamK <asamk@gmx.de>
Tue, 24 Nov 2020 20:44:57 +0000 (21:44 +0100)
committerAsamK <asamk@gmx.de>
Wed, 25 Nov 2020 20:12:40 +0000 (21:12 +0100)
src/main/java/org/asamk/signal/manager/Manager.java
src/main/java/org/asamk/signal/storage/SignalAccount.java
src/main/java/org/asamk/signal/storage/stickers/Sticker.java [new file with mode: 0644]
src/main/java/org/asamk/signal/storage/stickers/StickerStore.java [new file with mode: 0644]

index 07c8b583d89675ee8dd7c6f13437b503dcbeb198..56376f0e8bdab689346cfc0895cb329fd7cbb4a1 100644 (file)
@@ -26,6 +26,7 @@ import org.asamk.signal.storage.groups.GroupInfoV2;
 import org.asamk.signal.storage.profiles.SignalProfile;
 import org.asamk.signal.storage.profiles.SignalProfileEntry;
 import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
 import org.asamk.signal.storage.profiles.SignalProfile;
 import org.asamk.signal.storage.profiles.SignalProfileEntry;
 import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
+import org.asamk.signal.storage.stickers.Sticker;
 import org.asamk.signal.util.IOUtils;
 import org.asamk.signal.util.Util;
 import org.signal.libsignal.metadata.InvalidMetadataMessageException;
 import org.asamk.signal.util.IOUtils;
 import org.asamk.signal.util.Util;
 import org.signal.libsignal.metadata.InvalidMetadataMessageException;
@@ -103,6 +104,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
 import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
+import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
 import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
 import org.whispersystems.signalservice.api.push.ContactTokenDetails;
 import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
 import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
 import org.whispersystems.signalservice.api.push.ContactTokenDetails;
@@ -871,6 +873,10 @@ public class Manager implements Closeable {
         byte[] packKey = KeyUtils.createStickerUploadKey();
         String packId = messageSender.uploadStickerManifest(manifest, packKey);
 
         byte[] packKey = KeyUtils.createStickerUploadKey();
         String packId = messageSender.uploadStickerManifest(manifest, packKey);
 
+        Sticker sticker = new Sticker(Hex.fromStringCondensed(packId), packKey);
+        account.getStickerStore().updateSticker(sticker);
+        account.save();
+
         try {
             return new URI("https", "signal.art", "/addstickers/", "pack_id=" + URLEncoder.encode(packId, StandardCharsets.UTF_8) + "&pack_key=" + URLEncoder.encode(Hex.toStringCondensed(packKey), StandardCharsets.UTF_8))
                     .toString();
         try {
             return new URI("https", "signal.art", "/addstickers/", "pack_id=" + URLEncoder.encode(packId, StandardCharsets.UTF_8) + "&pack_key=" + URLEncoder.encode(Hex.toStringCondensed(packKey), StandardCharsets.UTF_8))
                     .toString();
@@ -1409,6 +1415,14 @@ public class Manager implements Closeable {
                 }
             }
         }
                 }
             }
         }
+        if (message.getSticker().isPresent()) {
+            final SignalServiceDataMessage.Sticker messageSticker = message.getSticker().get();
+            Sticker sticker = account.getStickerStore().getSticker(messageSticker.getPackId());
+            if (sticker == null) {
+                sticker = new Sticker(messageSticker.getPackId(), messageSticker.getPackKey());
+                account.getStickerStore().updateSticker(sticker);
+            }
+        }
         return actions;
     }
 
         return actions;
     }
 
@@ -1647,7 +1661,7 @@ public class Manager implements Closeable {
                     if (rm.isBlockedListRequest()) {
                         actions.add(SendSyncBlockedListAction.create());
                     }
                     if (rm.isBlockedListRequest()) {
                         actions.add(SendSyncBlockedListAction.create());
                     }
-                    // TODO Handle rm.isConfigurationRequest();
+                    // TODO Handle rm.isConfigurationRequest(); rm.isKeysRequest();
                 }
                 if (syncMessage.getGroups().isPresent()) {
                     File tmpFile = null;
                 }
                 if (syncMessage.getGroups().isPresent()) {
                     File tmpFile = null;
@@ -1773,6 +1787,23 @@ public class Manager implements Closeable {
                     final VerifiedMessage verifiedMessage = syncMessage.getVerified().get();
                     account.getSignalProtocolStore().setIdentityTrustLevel(resolveSignalServiceAddress(verifiedMessage.getDestination()), verifiedMessage.getIdentityKey(), TrustLevel.fromVerifiedState(verifiedMessage.getVerified()));
                 }
                     final VerifiedMessage verifiedMessage = syncMessage.getVerified().get();
                     account.getSignalProtocolStore().setIdentityTrustLevel(resolveSignalServiceAddress(verifiedMessage.getDestination()), verifiedMessage.getIdentityKey(), TrustLevel.fromVerifiedState(verifiedMessage.getVerified()));
                 }
+                if (syncMessage.getStickerPackOperations().isPresent()) {
+                    final List<StickerPackOperationMessage> stickerPackOperationMessages = syncMessage.getStickerPackOperations().get();
+                    for (StickerPackOperationMessage m : stickerPackOperationMessages) {
+                        if (!m.getPackId().isPresent()) {
+                            continue;
+                        }
+                        Sticker sticker = account.getStickerStore().getSticker(m.getPackId().get());
+                        if (sticker == null) {
+                            if (!m.getPackKey().isPresent()) {
+                                continue;
+                            }
+                            sticker = new Sticker(m.getPackId().get(), m.getPackKey().get());
+                        }
+                        sticker.setInstalled(!m.getType().isPresent() || m.getType().get() == StickerPackOperationMessage.Type.INSTALL);
+                        account.getStickerStore().updateSticker(sticker);
+                    }
+                }
                 if (syncMessage.getConfiguration().isPresent()) {
                     // TODO
                 }
                 if (syncMessage.getConfiguration().isPresent()) {
                     // TODO
                 }
index d3c2506dc578f07e488fa6c53b9e2a8a340a763f..dbb0ac0463c2a16f7586cec01358604d811efb70 100644 (file)
@@ -21,6 +21,7 @@ import org.asamk.signal.storage.protocol.JsonSignalProtocolStore;
 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.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;
 import org.asamk.signal.storage.threads.LegacyJsonThreadStore;
 import org.asamk.signal.storage.threads.ThreadInfo;
 import org.asamk.signal.util.IOUtils;
@@ -72,6 +73,7 @@ public class SignalAccount implements Closeable {
     private JsonContactsStore contactStore;
     private RecipientStore recipientStore;
     private ProfileStore profileStore;
     private JsonContactsStore contactStore;
     private RecipientStore recipientStore;
     private ProfileStore profileStore;
+    private StickerStore stickerStore;
 
     private SignalAccount(final FileChannel fileChannel, final FileLock lock) {
         this.fileChannel = fileChannel;
 
     private SignalAccount(final FileChannel fileChannel, final FileLock lock) {
         this.fileChannel = fileChannel;
@@ -114,6 +116,7 @@ public class SignalAccount implements Closeable {
         account.contactStore = new JsonContactsStore();
         account.recipientStore = new RecipientStore();
         account.profileStore = new ProfileStore();
         account.contactStore = new JsonContactsStore();
         account.recipientStore = new RecipientStore();
         account.profileStore = new ProfileStore();
+        account.stickerStore = new StickerStore();
         account.registered = false;
 
         return account;
         account.registered = false;
 
         return account;
@@ -140,6 +143,7 @@ public class SignalAccount implements Closeable {
         account.contactStore = new JsonContactsStore();
         account.recipientStore = new RecipientStore();
         account.profileStore = new ProfileStore();
         account.contactStore = new JsonContactsStore();
         account.recipientStore = new RecipientStore();
         account.profileStore = new ProfileStore();
+        account.stickerStore = new StickerStore();
         account.registered = true;
         account.isMultiDevice = true;
 
         account.registered = true;
         account.isMultiDevice = true;
 
@@ -267,6 +271,14 @@ public class SignalAccount implements Closeable {
             profileStore = new ProfileStore();
         }
 
             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);
         JsonNode threadStoreNode = rootNode.get("threadStore");
         if (threadStoreNode != null) {
             LegacyJsonThreadStore threadStore = jsonProcessor.convertValue(threadStoreNode, LegacyJsonThreadStore.class);
@@ -314,6 +326,7 @@ public class SignalAccount implements Closeable {
                 .putPOJO("contactStore", contactStore)
                 .putPOJO("recipientStore", recipientStore)
                 .putPOJO("profileStore", profileStore)
                 .putPOJO("contactStore", contactStore)
                 .putPOJO("recipientStore", recipientStore)
                 .putPOJO("profileStore", profileStore)
+                .putPOJO("stickerStore", stickerStore)
         ;
         try {
             try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
         ;
         try {
             try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
@@ -379,6 +392,10 @@ public class SignalAccount implements Closeable {
         return profileStore;
     }
 
         return profileStore;
     }
 
+    public StickerStore getStickerStore() {
+        return stickerStore;
+    }
+
     public String getUsername() {
         return username;
     }
     public String getUsername() {
         return username;
     }
diff --git a/src/main/java/org/asamk/signal/storage/stickers/Sticker.java b/src/main/java/org/asamk/signal/storage/stickers/Sticker.java
new file mode 100644 (file)
index 0000000..386924c
--- /dev/null
@@ -0,0 +1,35 @@
+package org.asamk.signal.storage.stickers;
+
+public class Sticker {
+
+    private final byte[] packId;
+    private final byte[] packKey;
+    private boolean installed;
+
+    public Sticker(final byte[] packId, final byte[] packKey) {
+        this.packId = packId;
+        this.packKey = packKey;
+    }
+
+    public Sticker(final byte[] packId, final byte[] packKey, final boolean installed) {
+        this.packId = packId;
+        this.packKey = packKey;
+        this.installed = installed;
+    }
+
+    public byte[] getPackId() {
+        return packId;
+    }
+
+    public byte[] getPackKey() {
+        return packKey;
+    }
+
+    public boolean isInstalled() {
+        return installed;
+    }
+
+    public void setInstalled(final boolean installed) {
+        this.installed = installed;
+    }
+}
diff --git a/src/main/java/org/asamk/signal/storage/stickers/StickerStore.java b/src/main/java/org/asamk/signal/storage/stickers/StickerStore.java
new file mode 100644 (file)
index 0000000..7b87369
--- /dev/null
@@ -0,0 +1,70 @@
+package org.asamk.signal.storage.stickers;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import org.whispersystems.util.Base64;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class StickerStore {
+
+    private static final ObjectMapper jsonProcessor = new ObjectMapper();
+
+    @JsonSerialize(using = StickersSerializer.class)
+    @JsonDeserialize(using = StickersDeserializer.class)
+    private final Map<byte[], Sticker> stickers = new HashMap<>();
+
+    public Sticker getSticker(byte[] packId) {
+        return stickers.get(packId);
+    }
+
+    public void updateSticker(Sticker sticker) {
+        stickers.put(sticker.getPackId(), sticker);
+    }
+
+    private static class StickersSerializer extends JsonSerializer<Map<byte[], Sticker>> {
+
+        @Override
+        public void serialize(final Map<byte[], Sticker> value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException {
+            final Collection<Sticker> stickers = value.values();
+            jgen.writeStartArray(stickers.size());
+            for (Sticker sticker : stickers) {
+                jgen.writeStartObject();
+                jgen.writeStringField("packId", Base64.encodeBytes(sticker.getPackId()));
+                jgen.writeStringField("packKey", Base64.encodeBytes(sticker.getPackKey()));
+                jgen.writeBooleanField("installed", sticker.isInstalled());
+                jgen.writeEndObject();
+            }
+            jgen.writeEndArray();
+        }
+    }
+
+    private static class StickersDeserializer extends JsonDeserializer<Map<byte[], Sticker>> {
+
+        @Override
+        public Map<byte[], Sticker> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
+            Map<byte[], Sticker> stickers = new HashMap<>();
+            JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+            for (JsonNode n : node) {
+                byte[] packId = Base64.decode(n.get("packId").asText());
+                byte[] packKey = Base64.decode(n.get("packKey").asText());
+                boolean installed = n.get("installed").asBoolean(false);
+                stickers.put(packId, new Sticker(packId, packKey, installed));
+            }
+
+            return stickers;
+        }
+    }
+}