mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Implement a sticker store
This commit is contained in:
parent
6a1b7dc597
commit
4acc9a96e3
4 changed files with 154 additions and 1 deletions
|
@ -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.stickers.Sticker;
|
||||
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.StickerPackOperationMessage;
|
||||
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);
|
||||
|
||||
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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1647,7 +1661,7 @@ public class Manager implements Closeable {
|
|||
if (rm.isBlockedListRequest()) {
|
||||
actions.add(SendSyncBlockedListAction.create());
|
||||
}
|
||||
// TODO Handle rm.isConfigurationRequest();
|
||||
// TODO Handle rm.isConfigurationRequest(); rm.isKeysRequest();
|
||||
}
|
||||
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()));
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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.stickers.StickerStore;
|
||||
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 StickerStore stickerStore;
|
||||
|
||||
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.stickerStore = new StickerStore();
|
||||
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.stickerStore = new StickerStore();
|
||||
account.registered = true;
|
||||
account.isMultiDevice = true;
|
||||
|
||||
|
@ -267,6 +271,14 @@ public class SignalAccount implements Closeable {
|
|||
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);
|
||||
|
@ -314,6 +326,7 @@ public class SignalAccount implements Closeable {
|
|||
.putPOJO("contactStore", contactStore)
|
||||
.putPOJO("recipientStore", recipientStore)
|
||||
.putPOJO("profileStore", profileStore)
|
||||
.putPOJO("stickerStore", stickerStore)
|
||||
;
|
||||
try {
|
||||
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||
|
@ -379,6 +392,10 @@ public class SignalAccount implements Closeable {
|
|||
return profileStore;
|
||||
}
|
||||
|
||||
public StickerStore getStickerStore() {
|
||||
return stickerStore;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
|
35
src/main/java/org/asamk/signal/storage/stickers/Sticker.java
Normal file
35
src/main/java/org/asamk/signal/storage/stickers/Sticker.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue