]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java
949e28629f9492202d5af8c36799883892a7ea4e
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / AttachmentStore.java
1 package org.asamk.signal.manager;
2
3 import org.asamk.signal.manager.util.IOUtils;
4 import org.asamk.signal.manager.util.MimeUtils;
5 import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
6 import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId;
7
8 import java.io.File;
9 import java.io.FileOutputStream;
10 import java.io.IOException;
11 import java.io.OutputStream;
12 import java.util.Optional;
13
14 public class AttachmentStore {
15
16 private final File attachmentsPath;
17
18 public AttachmentStore(final File attachmentsPath) {
19 this.attachmentsPath = attachmentsPath;
20 }
21
22 public void storeAttachmentPreview(
23 final SignalServiceAttachmentPointer pointer, final AttachmentStorer storer
24 ) throws IOException {
25 storeAttachment(getAttachmentPreviewFile(pointer.getRemoteId(),
26 pointer.getFileName(),
27 Optional.ofNullable(pointer.getContentType())), storer);
28 }
29
30 public void storeAttachment(
31 final SignalServiceAttachmentPointer pointer, final AttachmentStorer storer
32 ) throws IOException {
33 storeAttachment(getAttachmentFile(pointer), storer);
34 }
35
36 public File getAttachmentFile(final SignalServiceAttachmentPointer pointer) {
37 return getAttachmentFile(pointer.getRemoteId(),
38 pointer.getFileName(),
39 Optional.ofNullable(pointer.getContentType()));
40 }
41
42 private void storeAttachment(final File attachmentFile, final AttachmentStorer storer) throws IOException {
43 createAttachmentsDir();
44 try (OutputStream output = new FileOutputStream(attachmentFile)) {
45 storer.store(output);
46 }
47 }
48
49 private File getAttachmentPreviewFile(
50 SignalServiceAttachmentRemoteId attachmentId, Optional<String> filename, Optional<String> contentType
51 ) {
52 final var extension = getAttachmentExtension(filename, contentType);
53 return new File(attachmentsPath, attachmentId.toString() + extension + ".preview");
54 }
55
56 private File getAttachmentFile(
57 SignalServiceAttachmentRemoteId attachmentId, Optional<String> filename, Optional<String> contentType
58 ) {
59 final var extension = getAttachmentExtension(filename, contentType);
60 return new File(attachmentsPath, attachmentId.toString() + extension);
61 }
62
63 private static String getAttachmentExtension(
64 final Optional<String> filename, final Optional<String> contentType
65 ) {
66 return filename.filter(f -> f.contains("."))
67 .map(f -> f.substring(f.lastIndexOf(".") + 1))
68 .or(() -> contentType.flatMap(MimeUtils::guessExtensionFromMimeType))
69 .map(ext -> "." + ext)
70 .orElse("");
71 }
72
73 private void createAttachmentsDir() throws IOException {
74 IOUtils.createPrivateDirectories(attachmentsPath);
75 }
76
77 @FunctionalInterface
78 public interface AttachmentStorer {
79
80 void store(OutputStream outputStream) throws IOException;
81 }
82 }