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