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 Manager m
;
22 private final DBusConnection conn
;
23 private final String objectPath
;
25 public DbusReceiveMessageHandler(Manager m
, DBusConnection conn
, final String objectPath
) {
28 this.objectPath
= objectPath
;
32 public void handleMessage(MessageEnvelope envelope
, Throwable exception
) {
34 sendDbusMessages(envelope
);
35 } catch (DBusException e
) {
40 private void sendDbusMessages(MessageEnvelope envelope
) throws DBusException
{
41 final var senderString
= envelope
.sourceAddress().map(RecipientAddress
::getLegacyIdentifier
).orElse("");
42 if (envelope
.receipt().isPresent()) {
43 final var receiptMessage
= envelope
.receipt().get();
44 final var type
= switch (receiptMessage
.type()) {
46 case VIEWED
-> "viewed";
47 case DELIVERY
-> "delivery";
48 case UNKNOWN
-> "unknown";
50 for (long timestamp
: receiptMessage
.timestamps()) {
51 conn
.sendMessage(new Signal
.ReceiptReceived(objectPath
, timestamp
, senderString
));
52 conn
.sendMessage(new Signal
.ReceiptReceivedV2(objectPath
, timestamp
, senderString
, type
, Map
.of()));
55 if (envelope
.data().isPresent()) {
56 var message
= envelope
.data().get();
58 var groupId
= message
.groupContext()
59 .map(MessageEnvelope
.Data
.GroupContext
::groupId
)
60 .map(GroupId
::serialize
)
61 .orElseGet(() -> new byte[0]);
62 var isGroupUpdate
= message
.groupContext()
63 .map(MessageEnvelope
.Data
.GroupContext
::isGroupUpdate
)
65 if (!message
.isEndSession() && !isGroupUpdate
) {
66 conn
.sendMessage(new Signal
.MessageReceived(objectPath
,
70 message
.body().orElse(""),
71 getAttachments(message
)));
72 conn
.sendMessage(new Signal
.MessageReceivedV2(objectPath
,
76 message
.body().orElse(""),
77 getMessageExtras(message
)));
80 if (envelope
.sync().isPresent()) {
81 var syncMessage
= envelope
.sync().get();
82 if (syncMessage
.sent().isPresent()) {
83 var transcript
= syncMessage
.sent().get();
85 if (transcript
.destination().isPresent() || transcript
.message().groupContext().isPresent()) {
86 var message
= transcript
.message();
87 var groupId
= message
.groupContext()
88 .map(MessageEnvelope
.Data
.GroupContext
::groupId
)
89 .map(GroupId
::serialize
)
90 .orElseGet(() -> new byte[0]);
92 conn
.sendMessage(new Signal
.SyncMessageReceived(objectPath
,
93 transcript
.message().timestamp(),
95 transcript
.destination().map(RecipientAddress
::getLegacyIdentifier
).orElse(""),
97 message
.body().orElse(""),
98 getAttachments(message
)));
99 conn
.sendMessage(new Signal
.SyncMessageReceivedV2(objectPath
,
100 transcript
.message().timestamp(),
102 transcript
.destination().map(RecipientAddress
::getLegacyIdentifier
).orElse(""),
104 message
.body().orElse(""),
105 getMessageExtras(message
)));
112 private List
<String
> getAttachments(MessageEnvelope
.Data message
) {
113 var attachments
= new ArrayList
<String
>();
114 if (message
.attachments().size() > 0) {
115 for (var attachment
: message
.attachments()) {
116 if (attachment
.file().isPresent()) {
117 attachments
.add(attachment
.file().get().getAbsolutePath());
124 private HashMap
<String
, Variant
<?
>> getMessageExtras(MessageEnvelope
.Data message
) {
125 var extras
= new HashMap
<String
, Variant
<?
>>();
126 if (message
.attachments().size() > 0) {
127 var attachments
= message
.attachments()
129 .filter(a
-> a
.id().isPresent())
130 .map(a
-> getAttachmentMap(m
, a
))
131 .collect(Collectors
.toList());
132 extras
.put("attachments", new Variant
<>(attachments
, "aa{sv}"));
134 if (message
.mentions().size() > 0) {
135 var mentions
= message
.mentions().stream().map(this::getMentionMap
).collect(Collectors
.toList());
136 extras
.put("mentions", new Variant
<>(mentions
, "aa{sv}"));
138 extras
.put("expiresInSeconds", new Variant
<>(message
.expiresInSeconds()));
139 if (message
.quote().isPresent()) {
140 extras
.put("quote", new Variant
<>(getQuoteMap(message
.quote().get()), "a{sv}"));
142 if (message
.reaction().isPresent()) {
143 final var reaction
= message
.reaction().get();
144 extras
.put("reaction", new Variant
<>(getReactionMap(reaction
), "a{sv}"));
146 if (message
.remoteDeleteId().isPresent()) {
147 extras
.put("remoteDelete",
148 new Variant
<>(Map
.of("timestamp", new Variant
<>(message
.remoteDeleteId().get())), "a{sv}"));
150 if (message
.sticker().isPresent()) {
151 final var sticker
= message
.sticker().get();
152 extras
.put("sticker", new Variant
<>(getStickerMap(sticker
), "a{sv}"));
154 extras
.put("isViewOnce", new Variant
<>(message
.isViewOnce()));
158 private Map
<String
, Variant
<?
>> getQuoteMap(final MessageEnvelope
.Data
.Quote quote
) {
160 new Variant
<>(quote
.id()),
162 new Variant
<>(quote
.author().getLegacyIdentifier()),
164 new Variant
<>(quote
.text().orElse("")));
167 private Map
<String
, Variant
<?
extends Serializable
>> getStickerMap(final MessageEnvelope
.Data
.Sticker sticker
) {
168 return Map
.of("packId", new Variant
<>(sticker
.packId()), "stickerId", new Variant
<>(sticker
.stickerId()));
171 private Map
<String
, Variant
<?
>> getReactionMap(final MessageEnvelope
.Data
.Reaction reaction
) {
172 return Map
.of("emoji",
173 new Variant
<>(reaction
.emoji()),
175 new Variant
<>(reaction
.targetAuthor().getLegacyIdentifier()),
176 "targetSentTimestamp",
177 new Variant
<>(reaction
.targetSentTimestamp()),
179 new Variant
<>(reaction
.isRemove()));
182 private Map
<String
, Variant
<?
>> getAttachmentMap(
183 final Manager m
, final MessageEnvelope
.Data
.Attachment a
185 final var map
= new HashMap
<String
, Variant
<?
>>();
186 if (a
.id().isPresent()) {
187 map
.put("remoteId", new Variant
<>(a
.id().get()));
189 if (a
.file().isPresent()) {
190 map
.put("file", new Variant
<>(a
.file().get().getAbsolutePath()));
192 map
.put("contentType", new Variant
<>(a
.contentType()));
193 map
.put("isVoiceNote", new Variant
<>(a
.isVoiceNote()));
194 map
.put("isBorderless", new Variant
<>(a
.isBorderless()));
195 map
.put("isGif", new Variant
<>(a
.isGif()));
196 if (a
.caption().isPresent()) {
197 map
.put("caption", new Variant
<>(a
.caption().get()));
199 if (a
.fileName().isPresent()) {
200 map
.put("fileName", new Variant
<>(a
.fileName().get()));
202 if (a
.size().isPresent()) {
203 map
.put("size", new Variant
<>(a
.size().get()));
205 if (a
.width().isPresent()) {
206 map
.put("width", new Variant
<>(a
.width().get()));
208 if (a
.height().isPresent()) {
209 map
.put("height", new Variant
<>(a
.height().get()));
214 private Map
<String
, Variant
<?
>> getMentionMap(
215 final MessageEnvelope
.Data
.Mention mention
217 return Map
.of("recipient",
218 new Variant
<>(mention
.recipient().getLegacyIdentifier()),
220 new Variant
<>(mention
.start()),
222 new Variant
<>(mention
.length()));