1 package org
.asamk
.signal
.dbus
;
3 import org
.asamk
.Signal
;
4 import org
.asamk
.signal
.manager
.Manager
;
5 import org
.asamk
.signal
.manager
.api
.MessageEnvelope
;
6 import org
.asamk
.signal
.manager
.api
.RecipientAddress
;
7 import org
.asamk
.signal
.manager
.groups
.GroupId
;
8 import org
.freedesktop
.dbus
.connections
.impl
.DBusConnection
;
9 import org
.freedesktop
.dbus
.exceptions
.DBusException
;
10 import org
.freedesktop
.dbus
.types
.Variant
;
12 import java
.io
.Serializable
;
13 import java
.util
.ArrayList
;
14 import java
.util
.HashMap
;
15 import java
.util
.List
;
18 public class DbusReceiveMessageHandler
implements Manager
.ReceiveMessageHandler
{
20 private final DBusConnection conn
;
21 private final String objectPath
;
23 public DbusReceiveMessageHandler(DBusConnection conn
, final String objectPath
) {
25 this.objectPath
= objectPath
;
29 public void handleMessage(MessageEnvelope envelope
, Throwable exception
) {
31 sendDbusMessages(envelope
);
32 } catch (DBusException e
) {
37 private void sendDbusMessages(MessageEnvelope envelope
) throws DBusException
{
38 final var senderString
= envelope
.sourceAddress().map(RecipientAddress
::getLegacyIdentifier
).orElse("");
39 if (envelope
.receipt().isPresent()) {
40 final var receiptMessage
= envelope
.receipt().get();
41 final var type
= switch (receiptMessage
.type()) {
43 case VIEWED
-> "viewed";
44 case DELIVERY
-> "delivery";
45 case UNKNOWN
-> "unknown";
47 for (long timestamp
: receiptMessage
.timestamps()) {
48 conn
.sendMessage(new Signal
.ReceiptReceived(objectPath
, timestamp
, senderString
));
49 conn
.sendMessage(new Signal
.ReceiptReceivedV2(objectPath
, timestamp
, senderString
, type
, Map
.of()));
52 if (envelope
.data().isPresent()) {
53 var message
= envelope
.data().get();
55 var groupId
= message
.groupContext()
56 .map(MessageEnvelope
.Data
.GroupContext
::groupId
)
57 .map(GroupId
::serialize
)
58 .orElseGet(() -> new byte[0]);
59 var isGroupUpdate
= message
.groupContext()
60 .map(MessageEnvelope
.Data
.GroupContext
::isGroupUpdate
)
62 if (!message
.isEndSession() && !isGroupUpdate
) {
63 conn
.sendMessage(new Signal
.MessageReceived(objectPath
,
67 message
.body().orElse(""),
68 getAttachments(message
)));
69 conn
.sendMessage(new Signal
.MessageReceivedV2(objectPath
,
73 message
.body().orElse(""),
74 getMessageExtras(message
)));
77 if (envelope
.sync().isPresent()) {
78 var syncMessage
= envelope
.sync().get();
79 if (syncMessage
.sent().isPresent()) {
80 var transcript
= syncMessage
.sent().get();
82 if (transcript
.message().isPresent()) {
83 final var dataMessage
= transcript
.message().get();
84 if (transcript
.destination().isPresent() || dataMessage
.groupContext().isPresent()) {
85 var groupId
= dataMessage
.groupContext()
86 .map(MessageEnvelope
.Data
.GroupContext
::groupId
)
87 .map(GroupId
::serialize
)
88 .orElseGet(() -> new byte[0]);
90 conn
.sendMessage(new Signal
.SyncMessageReceived(objectPath
,
91 dataMessage
.timestamp(),
93 transcript
.destination().map(RecipientAddress
::getLegacyIdentifier
).orElse(""),
95 dataMessage
.body().orElse(""),
96 getAttachments(dataMessage
)));
97 conn
.sendMessage(new Signal
.SyncMessageReceivedV2(objectPath
,
98 dataMessage
.timestamp(),
100 transcript
.destination().map(RecipientAddress
::getLegacyIdentifier
).orElse(""),
102 dataMessage
.body().orElse(""),
103 getMessageExtras(dataMessage
)));
111 private List
<String
> getAttachments(MessageEnvelope
.Data message
) {
112 var attachments
= new ArrayList
<String
>();
113 if (message
.attachments().size() > 0) {
114 for (var attachment
: message
.attachments()) {
115 if (attachment
.file().isPresent()) {
116 attachments
.add(attachment
.file().get().getAbsolutePath());
123 private HashMap
<String
, Variant
<?
>> getMessageExtras(MessageEnvelope
.Data message
) {
124 var extras
= new HashMap
<String
, Variant
<?
>>();
125 if (message
.attachments().size() > 0) {
126 var attachments
= message
.attachments()
128 .filter(a
-> a
.id().isPresent())
129 .map(this::getAttachmentMap
)
131 extras
.put("attachments", new Variant
<>(attachments
, "aa{sv}"));
133 if (message
.mentions().size() > 0) {
134 var mentions
= message
.mentions().stream().map(this::getMentionMap
).toList();
135 extras
.put("mentions", new Variant
<>(mentions
, "aa{sv}"));
137 extras
.put("expiresInSeconds", new Variant
<>(message
.expiresInSeconds()));
138 if (message
.quote().isPresent()) {
139 extras
.put("quote", new Variant
<>(getQuoteMap(message
.quote().get()), "a{sv}"));
141 if (message
.reaction().isPresent()) {
142 final var reaction
= message
.reaction().get();
143 extras
.put("reaction", new Variant
<>(getReactionMap(reaction
), "a{sv}"));
145 if (message
.remoteDeleteId().isPresent()) {
146 extras
.put("remoteDelete",
147 new Variant
<>(Map
.of("timestamp", new Variant
<>(message
.remoteDeleteId().get())), "a{sv}"));
149 if (message
.sticker().isPresent()) {
150 final var sticker
= message
.sticker().get();
151 extras
.put("sticker", new Variant
<>(getStickerMap(sticker
), "a{sv}"));
153 extras
.put("isViewOnce", new Variant
<>(message
.isViewOnce()));
157 private Map
<String
, Variant
<?
>> getQuoteMap(final MessageEnvelope
.Data
.Quote quote
) {
159 new Variant
<>(quote
.id()),
161 new Variant
<>(quote
.author().getLegacyIdentifier()),
163 new Variant
<>(quote
.text().orElse("")));
166 private Map
<String
, Variant
<?
extends Serializable
>> getStickerMap(final MessageEnvelope
.Data
.Sticker sticker
) {
167 return Map
.of("packId",
168 new Variant
<>(sticker
.packId().serialize()),
170 new Variant
<>(sticker
.stickerId()));
173 private Map
<String
, Variant
<?
>> getReactionMap(final MessageEnvelope
.Data
.Reaction reaction
) {
174 return Map
.of("emoji",
175 new Variant
<>(reaction
.emoji()),
177 new Variant
<>(reaction
.targetAuthor().getLegacyIdentifier()),
178 "targetSentTimestamp",
179 new Variant
<>(reaction
.targetSentTimestamp()),
181 new Variant
<>(reaction
.isRemove()));
184 private Map
<String
, Variant
<?
>> getAttachmentMap(
185 final MessageEnvelope
.Data
.Attachment a
187 final var map
= new HashMap
<String
, Variant
<?
>>();
188 if (a
.id().isPresent()) {
189 map
.put("remoteId", new Variant
<>(a
.id().get()));
191 if (a
.file().isPresent()) {
192 map
.put("file", new Variant
<>(a
.file().get().getAbsolutePath()));
194 map
.put("contentType", new Variant
<>(a
.contentType()));
195 map
.put("isVoiceNote", new Variant
<>(a
.isVoiceNote()));
196 map
.put("isBorderless", new Variant
<>(a
.isBorderless()));
197 map
.put("isGif", new Variant
<>(a
.isGif()));
198 if (a
.caption().isPresent()) {
199 map
.put("caption", new Variant
<>(a
.caption().get()));
201 if (a
.fileName().isPresent()) {
202 map
.put("fileName", new Variant
<>(a
.fileName().get()));
204 if (a
.size().isPresent()) {
205 map
.put("size", new Variant
<>(a
.size().get()));
207 if (a
.width().isPresent()) {
208 map
.put("width", new Variant
<>(a
.width().get()));
210 if (a
.height().isPresent()) {
211 map
.put("height", new Variant
<>(a
.height().get()));
216 private Map
<String
, Variant
<?
>> getMentionMap(
217 final MessageEnvelope
.Data
.Mention mention
219 return Map
.of("recipient",
220 new Variant
<>(mention
.recipient().getLegacyIdentifier()),
222 new Variant
<>(mention
.start()),
224 new Variant
<>(mention
.length()));