]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/storage/profiles/ProfileStore.java
24b089684dcdd73b7b0fdceceb8ec17b9b90dba1
[signal-cli] / src / main / java / org / asamk / signal / storage / profiles / ProfileStore.java
1 package org.asamk.signal.storage.profiles;
2
3 import com.fasterxml.jackson.annotation.JsonProperty;
4 import com.fasterxml.jackson.core.JsonGenerator;
5 import com.fasterxml.jackson.core.JsonParser;
6 import com.fasterxml.jackson.databind.DeserializationContext;
7 import com.fasterxml.jackson.databind.JsonDeserializer;
8 import com.fasterxml.jackson.databind.JsonNode;
9 import com.fasterxml.jackson.databind.JsonSerializer;
10 import com.fasterxml.jackson.databind.ObjectMapper;
11 import com.fasterxml.jackson.databind.SerializerProvider;
12 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
13 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
14
15 import org.signal.zkgroup.InvalidInputException;
16 import org.signal.zkgroup.profiles.ProfileKey;
17 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
18 import org.whispersystems.signalservice.api.util.UuidUtil;
19 import org.whispersystems.util.Base64;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.UUID;
26
27 public class ProfileStore {
28
29 private static final ObjectMapper jsonProcessor = new ObjectMapper();
30
31 @JsonProperty("profiles")
32 @JsonDeserialize(using = ProfileStoreDeserializer.class)
33 @JsonSerialize(using = ProfileStoreSerializer.class)
34 private final List<SignalProfileEntry> profiles = new ArrayList<>();
35
36 public SignalProfileEntry getProfile(SignalServiceAddress serviceAddress) {
37 for (SignalProfileEntry entry : profiles) {
38 if (entry.getServiceAddress().matches(serviceAddress)) {
39 return entry;
40 }
41 }
42 return null;
43 }
44
45 public void updateProfile(SignalServiceAddress serviceAddress, ProfileKey profileKey, long now, SignalProfile profile) {
46 SignalProfileEntry newEntry = new SignalProfileEntry(serviceAddress, profileKey, now, profile);
47 for (int i = 0; i < profiles.size(); i++) {
48 if (profiles.get(i).getServiceAddress().matches(serviceAddress)) {
49 profiles.set(i, newEntry);
50 return;
51 }
52 }
53
54 profiles.add(newEntry);
55 }
56
57 public static class ProfileStoreDeserializer extends JsonDeserializer<List<SignalProfileEntry>> {
58
59 @Override
60 public List<SignalProfileEntry> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
61 JsonNode node = jsonParser.getCodec().readTree(jsonParser);
62
63 List<SignalProfileEntry> addresses = new ArrayList<>();
64
65 if (node.isArray()) {
66 for (JsonNode entry : node) {
67 String name = entry.hasNonNull("name")
68 ? entry.get("name").asText()
69 : null;
70 UUID uuid = entry.hasNonNull("uuid")
71 ? UuidUtil.parseOrNull(entry.get("uuid").asText())
72 : null;
73 final SignalServiceAddress serviceAddress = new SignalServiceAddress(uuid, name);
74 ProfileKey profileKey = null;
75 try {
76 profileKey = new ProfileKey(Base64.decode(entry.get("profileKey").asText()));
77 } catch (InvalidInputException ignored) {
78 }
79 long lastUpdateTimestamp = entry.get("lastUpdateTimestamp").asLong();
80 SignalProfile profile = jsonProcessor.treeToValue(entry.get("profile"), SignalProfile.class);
81 addresses.add(new SignalProfileEntry(serviceAddress, profileKey, lastUpdateTimestamp, profile));
82 }
83 }
84
85 return addresses;
86 }
87 }
88
89 public static class ProfileStoreSerializer extends JsonSerializer<List<SignalProfileEntry>> {
90
91 @Override
92 public void serialize(List<SignalProfileEntry> profiles, JsonGenerator json, SerializerProvider serializerProvider) throws IOException {
93 json.writeStartArray();
94 for (SignalProfileEntry profileEntry : profiles) {
95 final SignalServiceAddress address = profileEntry.getServiceAddress();
96 json.writeStartObject();
97 if (address.getNumber().isPresent()) {
98 json.writeStringField("name", address.getNumber().get());
99 }
100 if (address.getUuid().isPresent()) {
101 json.writeStringField("uuid", address.getUuid().get().toString());
102 }
103 json.writeStringField("profileKey", Base64.encodeBytes(profileEntry.getProfileKey().serialize()));
104 json.writeNumberField("lastUpdateTimestamp", profileEntry.getLastUpdateTimestamp());
105 json.writeObjectField("profile", profileEntry.getProfile());
106 json.writeEndObject();
107 }
108 json.writeEndArray();
109 }
110 }
111 }