]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java
fc5172782324c42932279ae85bc1a879e595e0ca
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / storage / messageCache / MessageCache.java
1 package org.asamk.signal.manager.storage.messageCache;
2
3 import org.asamk.signal.manager.storage.recipients.RecipientId;
4 import org.asamk.signal.manager.util.IOUtils;
5 import org.asamk.signal.manager.util.MessageCacheUtils;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8 import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
9
10 import java.io.File;
11 import java.io.IOException;
12 import java.nio.file.Files;
13 import java.util.Arrays;
14 import java.util.Collections;
15 import java.util.Objects;
16 import java.util.stream.Collectors;
17 import java.util.stream.Stream;
18
19 public class MessageCache {
20
21 private final static Logger logger = LoggerFactory.getLogger(MessageCache.class);
22
23 private final File messageCachePath;
24
25 public MessageCache(final File messageCachePath) {
26 this.messageCachePath = messageCachePath;
27 }
28
29 public Iterable<CachedMessage> getCachedMessages() {
30 if (!messageCachePath.exists()) {
31 return Collections.emptyList();
32 }
33
34 return Arrays.stream(Objects.requireNonNull(messageCachePath.listFiles())).flatMap(dir -> {
35 if (dir.isFile()) {
36 return Stream.of(dir);
37 }
38
39 final var files = Objects.requireNonNull(dir.listFiles());
40 if (files.length == 0) {
41 try {
42 Files.delete(dir.toPath());
43 } catch (IOException e) {
44 logger.warn("Failed to delete cache dir “{}”, ignoring: {}", dir, e.getMessage());
45 }
46 return Stream.empty();
47 }
48 return Arrays.stream(files).filter(File::isFile);
49 }).map(CachedMessage::new).collect(Collectors.toList());
50 }
51
52 public CachedMessage cacheMessage(SignalServiceEnvelope envelope, RecipientId recipientId) {
53 final var now = System.currentTimeMillis();
54
55 try {
56 var cacheFile = getMessageCacheFile(recipientId, now, envelope.getTimestamp());
57 MessageCacheUtils.storeEnvelope(envelope, cacheFile);
58 return new CachedMessage(cacheFile);
59 } catch (IOException e) {
60 logger.warn("Failed to store encrypted message in disk cache, ignoring: {}", e.getMessage());
61 return null;
62 }
63 }
64
65 public CachedMessage replaceSender(CachedMessage cachedMessage, RecipientId sender) throws IOException {
66 final var cacheFile = getMessageCacheFile(sender, cachedMessage.getFile().getName());
67 if (cacheFile.equals(cachedMessage.getFile())) {
68 return cachedMessage;
69 }
70 Files.move(cachedMessage.getFile().toPath(), cacheFile.toPath());
71 return new CachedMessage(cacheFile);
72 }
73
74 private File getMessageCachePath(RecipientId recipientId) {
75 if (recipientId == null) {
76 return messageCachePath;
77 }
78
79 var sender = String.valueOf(recipientId.getId());
80 return new File(messageCachePath, sender.replace("/", "_"));
81 }
82
83 private File getMessageCacheFile(RecipientId recipientId, String filename) throws IOException {
84 var cachePath = getMessageCachePath(recipientId);
85 IOUtils.createPrivateDirectories(cachePath);
86 return new File(cachePath, filename);
87 }
88
89 private File getMessageCacheFile(RecipientId recipientId, long now, long timestamp) throws IOException {
90 var cachePath = getMessageCachePath(recipientId);
91 IOUtils.createPrivateDirectories(cachePath);
92 return new File(cachePath, now + "_" + timestamp);
93 }
94
95 public void mergeRecipients(final RecipientId recipientId, final RecipientId toBeMergedRecipientId) {
96 final var toBeMergedMessageCachePath = getMessageCachePath(toBeMergedRecipientId);
97 if (!toBeMergedMessageCachePath.exists()) {
98 return;
99 }
100
101 for (var file : Objects.requireNonNull(toBeMergedMessageCachePath.listFiles())) {
102 if (!file.isFile()) {
103 continue;
104 }
105
106 try {
107 final var cacheFile = getMessageCacheFile(recipientId, file.getName());
108 Files.move(file.toPath(), cacheFile.toPath());
109 } catch (IOException e) {
110 logger.warn("Failed to move cache file “{}”, ignoring: {}", file, e.getMessage());
111 }
112 }
113 }
114 }