diff --git a/lib/src/main/java/org/asamk/signal/manager/AttachmentPointer.java b/lib/src/main/java/org/asamk/signal/manager/AttachmentPointer.java new file mode 100644 index 00000000..b7081a2d --- /dev/null +++ b/lib/src/main/java/org/asamk/signal/manager/AttachmentPointer.java @@ -0,0 +1,3 @@ +package org.asamk.signal.manager; + +public record AttachmentPointer(String id, String fileName, String contentType) {} diff --git a/lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java b/lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java index 949e2862..28180f12 100644 --- a/lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/AttachmentStore.java @@ -39,6 +39,12 @@ public class AttachmentStore { Optional.ofNullable(pointer.getContentType())); } + public File getAttachmentFile(AttachmentPointer pointer) { + return getAttachmentFile(SignalServiceAttachmentRemoteId.from(pointer.id()), + Optional.ofNullable(pointer.fileName()), + Optional.ofNullable(pointer.contentType())); + } + private void storeAttachment(final File attachmentFile, final AttachmentStorer storer) throws IOException { createAttachmentsDir(); try (OutputStream output = new FileOutputStream(attachmentFile)) { diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index 007a783e..ca79d844 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -272,6 +272,8 @@ public interface Manager extends Closeable { void addClosedListener(Runnable listener); + File getAttachmentFile(AttachmentPointer pointer); + @Override void close() throws IOException; diff --git a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java index 58863d08..49fe4943 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java @@ -1147,6 +1147,10 @@ class ManagerImpl implements Manager { } } + public File getAttachmentFile(AttachmentPointer pointer) { + return context.getAttachmentHelper().getAttachmentFile(pointer); + } + @Override public void close() { Thread thread; diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java index ea5739b3..fd77b8fd 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java @@ -1,5 +1,6 @@ package org.asamk.signal.manager.helper; +import org.asamk.signal.manager.AttachmentPointer; import org.asamk.signal.manager.AttachmentStore; import org.asamk.signal.manager.SignalDependencies; import org.asamk.signal.manager.api.AttachmentInvalidException; @@ -38,6 +39,11 @@ public class AttachmentHelper { return attachmentStore.getAttachmentFile(pointer); } + public File getAttachmentFile(AttachmentPointer pointer) { + return attachmentStore.getAttachmentFile(pointer); + } + + public List uploadAttachments(final List attachments) throws AttachmentInvalidException, IOException { var attachmentStreams = AttachmentUtils.createAttachmentStreams(attachments); diff --git a/src/main/java/org/asamk/signal/commands/AttachmentCommand.java b/src/main/java/org/asamk/signal/commands/AttachmentCommand.java new file mode 100644 index 00000000..8afaf030 --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/AttachmentCommand.java @@ -0,0 +1,65 @@ +package org.asamk.signal.commands; + +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; + +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.UnexpectedErrorException; +import org.asamk.signal.json.JsonAttachmentData; +import org.asamk.signal.manager.AttachmentPointer; +import org.asamk.signal.manager.Manager; +import org.asamk.signal.output.JsonWriter; +import org.asamk.signal.output.OutputWriter; +import org.asamk.signal.output.PlainTextWriter; + +import java.io.IOException; +import java.nio.file.Files; +import java.util.Base64; + +public class AttachmentCommand implements JsonRpcLocalCommand { + + @Override + public String getName() { + return "attachment"; + } + + @Override + public void attachToSubparser(final Subparser subparser) { + subparser.addArgument("--file-id") + .help("The ID of the attachment file."); + subparser.addArgument("--file-name") + .nargs("?") + .help("The name of the file."); + subparser.addArgument("--content-type") + .nargs("?") + .help("The content type of the file."); + } + + @Override + public void handleCommand( + final Namespace ns, + final Manager m, + final OutputWriter outputWriter + ) throws CommandException { + + final var id = ns.getString("file-id"); + final var fileName = ns.getString("file-name"); + final var contentType = ns.getString("content-type"); + + final var file = m.getAttachmentFile(new AttachmentPointer(id, fileName, contentType)); + + try { + final var bytes = Files.readAllBytes(file.toPath()); + final var base64 = Base64.getEncoder().encodeToString(bytes); + + if (outputWriter instanceof PlainTextWriter writer) { + writer.println(base64); + } + else if (outputWriter instanceof JsonWriter writer) { + writer.write(new JsonAttachmentData(base64)); + } + } catch (IOException ex) { + throw new UnexpectedErrorException("An error occurred reading attachment file: " + file, ex); + } + } +} diff --git a/src/main/java/org/asamk/signal/commands/Commands.java b/src/main/java/org/asamk/signal/commands/Commands.java index 1c4251da..756536bd 100644 --- a/src/main/java/org/asamk/signal/commands/Commands.java +++ b/src/main/java/org/asamk/signal/commands/Commands.java @@ -11,6 +11,7 @@ public class Commands { static { addCommand(new AddDeviceCommand()); + addCommand(new AttachmentCommand()); addCommand(new BlockCommand()); addCommand(new DaemonCommand()); addCommand(new DeleteLocalAccountDataCommand()); diff --git a/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java b/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java index bbfa4f1c..94c6b66a 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java @@ -2,6 +2,7 @@ package org.asamk.signal.dbus; import org.asamk.Signal; import org.asamk.signal.DbusConfig; +import org.asamk.signal.manager.AttachmentPointer; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.api.AttachmentInvalidException; import org.asamk.signal.manager.api.Configuration; @@ -907,6 +908,12 @@ public class DbusManagerImpl implements Manager { }).toList(); } + @Override + public File getAttachmentFile(final AttachmentPointer pointer) { + //TODO may need an implementation + return null; + } + @SuppressWarnings("unchecked") private T getValue( final Map> stringVariantMap, final String field diff --git a/src/main/java/org/asamk/signal/json/JsonAttachmentData.java b/src/main/java/org/asamk/signal/json/JsonAttachmentData.java new file mode 100644 index 00000000..a8af32d4 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonAttachmentData.java @@ -0,0 +1,3 @@ +package org.asamk.signal.json; + +public record JsonAttachmentData(String dataBase64) {}