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
.groups
.GroupId
;
7 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientAddress
;
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
;
17 import java
.util
.stream
.Collectors
;
19 public class DbusReceiveMessageHandler
implements Manager
.ReceiveMessageHandler
{
21 private final DBusConnection conn
;
22 private final String objectPath
;
24 public DbusReceiveMessageHandler(DBusConnection conn
, final String objectPath
) {
26 this.objectPath
= objectPath
;
30 public void handleMessage(MessageEnvelope envelope
, Throwable exception
) {
32 sendDbusMessages(envelope
);
33 } catch (DBusException e
) {
38 private void sendDbusMessages(MessageEnvelope envelope
) throws DBusException
{
39 final var senderString
= envelope
.sourceAddress().map(RecipientAddress
::getLegacyIdentifier
).orElse("");
40 if (envelope
.receipt().isPresent()) {
41 final var receiptMessage
= envelope
.receipt().get();
42 final var type
= switch (receiptMessage
.type()) {
44 case VIEWED
-> "viewed";
45 case DELIVERY
-> "delivery";
46 case UNKNOWN
-> "unknown";
48 for (long timestamp
: receiptMessage
.timestamps()) {
49 conn
.sendMessage(new Signal
.ReceiptReceived(objectPath
, timestamp
, senderString
));
50 conn
.sendMessage(new Signal
.ReceiptReceivedV2(objectPath
, timestamp
, senderString
, type
, Map
.of()));
53 if (envelope
.data().isPresent()) {
54 var message
= envelope
.data().get();
56 var groupId
= message
.groupContext()
57 .map(MessageEnvelope
.Data
.GroupContext
::groupId
)
58 .map(GroupId
::serialize
)
59 .orElseGet(() -> new byte[0]);
60 var isGroupUpdate
= message
.groupContext()
61 .map(MessageEnvelope
.Data
.GroupContext
::isGroupUpdate
)
63 if (!message
.isEndSession() && !isGroupUpdate
) {
64 conn
.sendMessage(new Signal
.MessageReceived(objectPath
,
68 message
.body().orElse(""),
69 getAttachments(message
)));
70 conn
.sendMessage(new Signal
.MessageReceivedV2(objectPath
,
74 message
.body().orElse(""),
75 getMessageExtras(message
)));
78 if (envelope
.sync().isPresent()) {
79 var syncMessage
= envelope
.sync().get();
80 if (syncMessage
.sent().isPresent()) {
81 var transcript
= syncMessage
.sent().get();
83 if (transcript
.destination().isPresent() || transcript
.message().groupContext().isPresent()) {
84 var message
= transcript
.message();
85 var groupId
= message
.groupContext()
86 .map(MessageEnvelope
.Data
.GroupContext
::groupId
)
87 .map(GroupId
::serialize
)
88 .orElseGet(() -> new byte[0]);
90 conn
.sendMessage(new Signal
.SyncMessageReceived(objectPath
,
91 transcript
.message().timestamp(),
93 transcript
.destination().map(RecipientAddress
::getLegacyIdentifier
).orElse(""),
95 message
.body().orElse(""),
96 getAttachments(message
)));
97 conn
.sendMessage(new Signal
.SyncMessageReceivedV2(objectPath
,
98 transcript
.message().timestamp(),
100 transcript
.destination().map(RecipientAddress
::getLegacyIdentifier
).orElse(""),
102 message
.body().orElse(""),
103 getMessageExtras(message
)));
110 private List
<String
> getAttachments(MessageEnvelope
.Data message
) {
111 var attachments
= new ArrayList
<String
>();
112 if (message
.attachments().size() > 0) {
113 for (var attachment
: message
.attachments()) {
114 if (attachment
.file().isPresent()) {
115 attachments
.add(attachment
.file().get().getAbsolutePath());
122 private HashMap
<String
, Variant
<?
>> getMessageExtras(MessageEnvelope
.Data message
) {
123 var extras
= new HashMap
<String
, Variant
<?
>>();
124 if (message
.attachments().size() > 0) {
125 var attachments
= message
.attachments()
127 .filter(a
-> a
.id().isPresent())
128 .map(this::getAttachmentMap
)
129 .collect(Collectors
.toList());
130 extras
.put("attachments", new Variant
<>(attachments
, "aa{sv}"));
132 if (message
.mentions().size() > 0) {
133 var mentions
= message
.mentions().stream().map(this::getMentionMap
).collect(Collectors
.toList());
134 extras
.put("mentions", new Variant
<>(mentions
, "aa{sv}"));
136 extras
.put("expiresInSeconds", new Variant
<>(message
.expiresInSeconds()));
137 if (message
.quote().isPresent()) {
138 extras
.put("quote", new Variant
<>(getQuoteMap(message
.quote().get()), "a{sv}"));
140 if (message
.reaction().isPresent()) {
141 final var reaction
= message
.reaction().get();
142 extras
.put("reaction", new Variant
<>(getReactionMap(reaction
), "a{sv}"));
144 if (message
.remoteDeleteId().isPresent()) {
145 extras
.put("remoteDelete",
146 new Variant
<>(Map
.of("timestamp", new Variant
<>(message
.remoteDeleteId().get())), "a{sv}"));
148 if (message
.sticker().isPresent()) {
149 final var sticker
= message
.sticker().get();
150 extras
.put("sticker", new Variant
<>(getStickerMap(sticker
), "a{sv}"));
152 extras
.put("isViewOnce", new Variant
<>(message
.isViewOnce()));
156 private Map
<String
, Variant
<?
>> getQuoteMap(final MessageEnvelope
.Data
.Quote quote
) {
158 new Variant
<>(quote
.id()),
160 new Variant
<>(quote
.author().getLegacyIdentifier()),
162 new Variant
<>(quote
.text().orElse("")));
165 private Map
<String
, Variant
<?
extends Serializable
>> getStickerMap(final MessageEnvelope
.Data
.Sticker sticker
) {
166 return Map
.of("packId", new Variant
<>(sticker
.packId()), "stickerId", new Variant
<>(sticker
.stickerId()));
169 private Map
<String
, Variant
<?
>> getReactionMap(final MessageEnvelope
.Data
.Reaction reaction
) {
170 return Map
.of("emoji",
171 new Variant
<>(reaction
.emoji()),
173 new Variant
<>(reaction
.targetAuthor().getLegacyIdentifier()),
174 "targetSentTimestamp",
175 new Variant
<>(reaction
.targetSentTimestamp()),
177 new Variant
<>(reaction
.isRemove()));
180 private Map
<String
, Variant
<?
>> getAttachmentMap(
181 final MessageEnvelope
.Data
.Attachment a
183 final var map
= new HashMap
<String
, Variant
<?
>>();
184 if (a
.id().isPresent()) {
185 map
.put("remoteId", new Variant
<>(a
.id().get()));
187 if (a
.file().isPresent()) {
188 map
.put("file", new Variant
<>(a
.file().get().getAbsolutePath()));
190 map
.put("contentType", new Variant
<>(a
.contentType()));
191 map
.put("isVoiceNote", new Variant
<>(a
.isVoiceNote()));
192 map
.put("isBorderless", new Variant
<>(a
.isBorderless()));
193 map
.put("isGif", new Variant
<>(a
.isGif()));
194 if (a
.caption().isPresent()) {
195 map
.put("caption", new Variant
<>(a
.caption().get()));
197 if (a
.fileName().isPresent()) {
198 map
.put("fileName", new Variant
<>(a
.fileName().get()));
200 if (a
.size().isPresent()) {
201 map
.put("size", new Variant
<>(a
.size().get()));
203 if (a
.width().isPresent()) {
204 map
.put("width", new Variant
<>(a
.width().get()));
206 if (a
.height().isPresent()) {
207 map
.put("height", new Variant
<>(a
.height().get()));
212 private Map
<String
, Variant
<?
>> getMentionMap(
213 final MessageEnvelope
.Data
.Mention mention
215 return Map
.of("recipient",
216 new Variant
<>(mention
.recipient().getLegacyIdentifier()),
218 new Variant
<>(mention
.start()),
220 new Variant
<>(mention
.length()));