mirror of
https://github.com/AsamK/signal-cli.git
synced 2026-05-22 13:54:19 +00:00
Always download long text attachments and use them as message body
Fixes #1901
This commit is contained in:
parent
775236efc3
commit
8fcd953ece
@ -3,6 +3,7 @@ package org.asamk.signal.manager.api;
|
|||||||
import org.asamk.signal.manager.groups.GroupUtils;
|
import org.asamk.signal.manager.groups.GroupUtils;
|
||||||
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
||||||
|
import org.asamk.signal.manager.util.MimeUtils;
|
||||||
import org.signal.core.models.ServiceId;
|
import org.signal.core.models.ServiceId;
|
||||||
import org.signal.libsignal.metadata.ProtocolException;
|
import org.signal.libsignal.metadata.ProtocolException;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
@ -37,6 +38,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.ViewedMessage;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -128,10 +130,22 @@ public record MessageEnvelope(
|
|||||||
|
|
||||||
static Data from(
|
static Data from(
|
||||||
final SignalServiceDataMessage dataMessage,
|
final SignalServiceDataMessage dataMessage,
|
||||||
|
Map<String, String> longTexts,
|
||||||
RecipientResolver recipientResolver,
|
RecipientResolver recipientResolver,
|
||||||
RecipientAddressResolver addressResolver,
|
RecipientAddressResolver addressResolver,
|
||||||
final AttachmentFileProvider fileProvider
|
final AttachmentFileProvider fileProvider
|
||||||
) {
|
) {
|
||||||
|
var body = dataMessage.getBody();
|
||||||
|
if (dataMessage.getAttachments().isPresent()) {
|
||||||
|
for (final var attachment : dataMessage.getAttachments().get()) {
|
||||||
|
if (MimeUtils.LONG_TEXT.equals(attachment.getContentType()) && attachment.isPointer()) {
|
||||||
|
final var longBody = longTexts.get(attachment.asPointer().getRemoteId().toString());
|
||||||
|
if (longBody != null) {
|
||||||
|
body = Optional.of(longBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return new Data(dataMessage.getTimestamp(),
|
return new Data(dataMessage.getTimestamp(),
|
||||||
dataMessage.getGroupContext().map(GroupContext::from),
|
dataMessage.getGroupContext().map(GroupContext::from),
|
||||||
dataMessage.getStoryContext()
|
dataMessage.getStoryContext()
|
||||||
@ -139,7 +153,7 @@ public record MessageEnvelope(
|
|||||||
recipientResolver,
|
recipientResolver,
|
||||||
addressResolver)),
|
addressResolver)),
|
||||||
dataMessage.getGroupCallUpdate().map(GroupCallUpdate::from),
|
dataMessage.getGroupCallUpdate().map(GroupCallUpdate::from),
|
||||||
dataMessage.getBody(),
|
body,
|
||||||
dataMessage.getExpiresInSeconds(),
|
dataMessage.getExpiresInSeconds(),
|
||||||
dataMessage.isExpirationUpdate(),
|
dataMessage.isExpirationUpdate(),
|
||||||
dataMessage.isViewOnce(),
|
dataMessage.isViewOnce(),
|
||||||
@ -621,12 +635,17 @@ public record MessageEnvelope(
|
|||||||
|
|
||||||
public static Edit from(
|
public static Edit from(
|
||||||
final SignalServiceEditMessage editMessage,
|
final SignalServiceEditMessage editMessage,
|
||||||
|
Map<String, String> longTexts,
|
||||||
RecipientResolver recipientResolver,
|
RecipientResolver recipientResolver,
|
||||||
RecipientAddressResolver addressResolver,
|
RecipientAddressResolver addressResolver,
|
||||||
final AttachmentFileProvider fileProvider
|
final AttachmentFileProvider fileProvider
|
||||||
) {
|
) {
|
||||||
return new Edit(editMessage.getTargetSentTimestamp(),
|
return new Edit(editMessage.getTargetSentTimestamp(),
|
||||||
Data.from(editMessage.getDataMessage(), recipientResolver, addressResolver, fileProvider));
|
Data.from(editMessage.getDataMessage(),
|
||||||
|
longTexts,
|
||||||
|
recipientResolver,
|
||||||
|
addressResolver,
|
||||||
|
fileProvider));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,12 +662,13 @@ public record MessageEnvelope(
|
|||||||
|
|
||||||
public static Sync from(
|
public static Sync from(
|
||||||
final SignalServiceSyncMessage syncMessage,
|
final SignalServiceSyncMessage syncMessage,
|
||||||
|
Map<String, String> longTexts,
|
||||||
RecipientResolver recipientResolver,
|
RecipientResolver recipientResolver,
|
||||||
RecipientAddressResolver addressResolver,
|
RecipientAddressResolver addressResolver,
|
||||||
final AttachmentFileProvider fileProvider
|
final AttachmentFileProvider fileProvider
|
||||||
) {
|
) {
|
||||||
return new Sync(syncMessage.getSent()
|
return new Sync(syncMessage.getSent()
|
||||||
.map(s -> Sent.from(s, recipientResolver, addressResolver, fileProvider)),
|
.map(s -> Sent.from(s, longTexts, recipientResolver, addressResolver, fileProvider)),
|
||||||
syncMessage.getBlockedList().map(b -> Blocked.from(b, recipientResolver, addressResolver)),
|
syncMessage.getBlockedList().map(b -> Blocked.from(b, recipientResolver, addressResolver)),
|
||||||
syncMessage.getRead()
|
syncMessage.getRead()
|
||||||
.map(r -> r.stream().map(rm -> Read.from(rm, recipientResolver, addressResolver)).toList())
|
.map(r -> r.stream().map(rm -> Read.from(rm, recipientResolver, addressResolver)).toList())
|
||||||
@ -677,6 +697,7 @@ public record MessageEnvelope(
|
|||||||
|
|
||||||
static Sent from(
|
static Sent from(
|
||||||
SentTranscriptMessage sentMessage,
|
SentTranscriptMessage sentMessage,
|
||||||
|
Map<String, String> longTexts,
|
||||||
RecipientResolver recipientResolver,
|
RecipientResolver recipientResolver,
|
||||||
RecipientAddressResolver addressResolver,
|
RecipientAddressResolver addressResolver,
|
||||||
final AttachmentFileProvider fileProvider
|
final AttachmentFileProvider fileProvider
|
||||||
@ -692,9 +713,17 @@ public record MessageEnvelope(
|
|||||||
.toApiRecipientAddress())
|
.toApiRecipientAddress())
|
||||||
.collect(Collectors.toSet()),
|
.collect(Collectors.toSet()),
|
||||||
sentMessage.getDataMessage()
|
sentMessage.getDataMessage()
|
||||||
.map(message -> Data.from(message, recipientResolver, addressResolver, fileProvider)),
|
.map(message -> Data.from(message,
|
||||||
|
longTexts,
|
||||||
|
recipientResolver,
|
||||||
|
addressResolver,
|
||||||
|
fileProvider)),
|
||||||
sentMessage.getEditMessage()
|
sentMessage.getEditMessage()
|
||||||
.map(message -> Edit.from(message, recipientResolver, addressResolver, fileProvider)),
|
.map(message -> Edit.from(message,
|
||||||
|
longTexts,
|
||||||
|
recipientResolver,
|
||||||
|
addressResolver,
|
||||||
|
fileProvider)),
|
||||||
sentMessage.getStoryMessage().map(s -> Story.from(s, fileProvider)));
|
sentMessage.getStoryMessage().map(s -> Story.from(s, fileProvider)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -993,6 +1022,7 @@ public record MessageEnvelope(
|
|||||||
public static MessageEnvelope from(
|
public static MessageEnvelope from(
|
||||||
SignalServiceEnvelope envelope,
|
SignalServiceEnvelope envelope,
|
||||||
SignalServiceContent content,
|
SignalServiceContent content,
|
||||||
|
Map<String, String> longTexts,
|
||||||
RecipientResolver recipientResolver,
|
RecipientResolver recipientResolver,
|
||||||
RecipientAddressResolver addressResolver,
|
RecipientAddressResolver addressResolver,
|
||||||
final AttachmentFileProvider fileProvider,
|
final AttachmentFileProvider fileProvider,
|
||||||
@ -1023,9 +1053,15 @@ public record MessageEnvelope(
|
|||||||
receipt = content.getReceiptMessage().map(Receipt::from);
|
receipt = content.getReceiptMessage().map(Receipt::from);
|
||||||
typing = content.getTypingMessage().map(Typing::from);
|
typing = content.getTypingMessage().map(Typing::from);
|
||||||
data = content.getDataMessage()
|
data = content.getDataMessage()
|
||||||
.map(dataMessage -> Data.from(dataMessage, recipientResolver, addressResolver, fileProvider));
|
.map(dataMessage -> Data.from(dataMessage,
|
||||||
edit = content.getEditMessage().map(s -> Edit.from(s, recipientResolver, addressResolver, fileProvider));
|
longTexts,
|
||||||
sync = content.getSyncMessage().map(s -> Sync.from(s, recipientResolver, addressResolver, fileProvider));
|
recipientResolver,
|
||||||
|
addressResolver,
|
||||||
|
fileProvider));
|
||||||
|
edit = content.getEditMessage()
|
||||||
|
.map(s -> Edit.from(s, longTexts, recipientResolver, addressResolver, fileProvider));
|
||||||
|
sync = content.getSyncMessage()
|
||||||
|
.map(s -> Sync.from(s, longTexts, recipientResolver, addressResolver, fileProvider));
|
||||||
call = content.getCallMessage().map(Call::from);
|
call = content.getCallMessage().map(Call::from);
|
||||||
story = content.getStoryMessage().map(s -> Story.from(s, fileProvider));
|
story = content.getStoryMessage().map(s -> Story.from(s, fileProvider));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
|||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||||
import org.asamk.signal.manager.storage.stickers.StickerPack;
|
import org.asamk.signal.manager.storage.stickers.StickerPack;
|
||||||
|
import org.asamk.signal.manager.util.MimeUtils;
|
||||||
import org.signal.core.models.ServiceId;
|
import org.signal.core.models.ServiceId;
|
||||||
import org.signal.core.models.ServiceId.ACI;
|
import org.signal.core.models.ServiceId.ACI;
|
||||||
import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
|
import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
|
||||||
@ -70,8 +71,13 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
|||||||
import org.whispersystems.signalservice.internal.push.Envelope;
|
import org.whispersystems.signalservice.internal.push.Envelope;
|
||||||
import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException;
|
import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -273,13 +279,18 @@ public final class IncomingMessageHandler {
|
|||||||
return List.of();
|
return List.of();
|
||||||
} else {
|
} else {
|
||||||
List<HandleAction> actions;
|
List<HandleAction> actions;
|
||||||
|
Map<String, String> longTexts;
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
actions = handleMessage(envelope, content, receiveConfig);
|
final var results = handleMessage(envelope, content, receiveConfig);
|
||||||
|
actions = results.first();
|
||||||
|
longTexts = results.second();
|
||||||
} else {
|
} else {
|
||||||
actions = List.of();
|
actions = List.of();
|
||||||
|
longTexts = Map.of();
|
||||||
}
|
}
|
||||||
handler.handleMessage(MessageEnvelope.from(envelope,
|
handler.handleMessage(MessageEnvelope.from(envelope,
|
||||||
content,
|
content,
|
||||||
|
longTexts,
|
||||||
account.getRecipientResolver(),
|
account.getRecipientResolver(),
|
||||||
account.getRecipientAddressResolver(),
|
account.getRecipientAddressResolver(),
|
||||||
context.getAttachmentHelper()::getAttachmentFile,
|
context.getAttachmentHelper()::getAttachmentFile,
|
||||||
@ -288,12 +299,13 @@ public final class IncomingMessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<HandleAction> handleMessage(
|
public Pair<List<HandleAction>, Map<String, String>> handleMessage(
|
||||||
SignalServiceEnvelope envelope,
|
SignalServiceEnvelope envelope,
|
||||||
SignalServiceContent content,
|
SignalServiceContent content,
|
||||||
ReceiveConfig receiveConfig
|
ReceiveConfig receiveConfig
|
||||||
) {
|
) {
|
||||||
var actions = new ArrayList<HandleAction>();
|
final var actions = new ArrayList<HandleAction>();
|
||||||
|
final var longTexts = new HashMap<String, String>();
|
||||||
final var senderDeviceAddress = getSender(envelope, content);
|
final var senderDeviceAddress = getSender(envelope, content);
|
||||||
final var sender = senderDeviceAddress.recipientId();
|
final var sender = senderDeviceAddress.recipientId();
|
||||||
final var senderServiceId = senderDeviceAddress.serviceId();
|
final var senderServiceId = senderDeviceAddress.serviceId();
|
||||||
@ -368,11 +380,13 @@ public final class IncomingMessageHandler {
|
|||||||
message.getTimestamp()));
|
message.getTimestamp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.addAll(handleSignalServiceDataMessage(message,
|
final var dataResults = handleSignalServiceDataMessage(message,
|
||||||
false,
|
false,
|
||||||
senderDeviceAddress,
|
senderDeviceAddress,
|
||||||
destination,
|
destination,
|
||||||
receiveConfig));
|
receiveConfig);
|
||||||
|
actions.addAll(dataResults.first());
|
||||||
|
longTexts.putAll(dataResults.second());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.getStoryMessage().isPresent()) {
|
if (content.getStoryMessage().isPresent()) {
|
||||||
@ -382,10 +396,12 @@ public final class IncomingMessageHandler {
|
|||||||
|
|
||||||
if (content.getSyncMessage().isPresent()) {
|
if (content.getSyncMessage().isPresent()) {
|
||||||
var syncMessage = content.getSyncMessage().get();
|
var syncMessage = content.getSyncMessage().get();
|
||||||
actions.addAll(handleSyncMessage(envelope, syncMessage, senderDeviceAddress, receiveConfig));
|
final var syncResults = handleSyncMessage(envelope, syncMessage, senderDeviceAddress, receiveConfig);
|
||||||
|
actions.addAll(syncResults.first());
|
||||||
|
longTexts.putAll(syncResults.second());
|
||||||
}
|
}
|
||||||
|
|
||||||
return actions;
|
return new Pair<>(actions, longTexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handlePniSignatureMessage(
|
private boolean handlePniSignatureMessage(
|
||||||
@ -471,19 +487,20 @@ public final class IncomingMessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<HandleAction> handleSyncMessage(
|
private Pair<List<HandleAction>, Map<String, String>> handleSyncMessage(
|
||||||
final SignalServiceEnvelope envelope,
|
final SignalServiceEnvelope envelope,
|
||||||
final SignalServiceSyncMessage syncMessage,
|
final SignalServiceSyncMessage syncMessage,
|
||||||
final DeviceAddress sender,
|
final DeviceAddress sender,
|
||||||
final ReceiveConfig receiveConfig
|
final ReceiveConfig receiveConfig
|
||||||
) {
|
) {
|
||||||
var actions = new ArrayList<HandleAction>();
|
final var actions = new ArrayList<HandleAction>();
|
||||||
|
final var longTexts = new HashMap<String, String>();
|
||||||
account.setMultiDevice(true);
|
account.setMultiDevice(true);
|
||||||
if (syncMessage.getSent().isPresent()) {
|
if (syncMessage.getSent().isPresent()) {
|
||||||
var message = syncMessage.getSent().get();
|
var message = syncMessage.getSent().get();
|
||||||
final var destination = message.getDestination().orElse(null);
|
final var destination = message.getDestination().orElse(null);
|
||||||
if (message.getDataMessage().isPresent()) {
|
if (message.getDataMessage().isPresent()) {
|
||||||
actions.addAll(handleSignalServiceDataMessage(message.getDataMessage().get(),
|
final var dataResults = handleSignalServiceDataMessage(message.getDataMessage().get(),
|
||||||
true,
|
true,
|
||||||
sender,
|
sender,
|
||||||
destination == null
|
destination == null
|
||||||
@ -491,7 +508,9 @@ public final class IncomingMessageHandler {
|
|||||||
: new DeviceAddress(account.getRecipientResolver().resolveRecipient(destination),
|
: new DeviceAddress(account.getRecipientResolver().resolveRecipient(destination),
|
||||||
destination.getServiceId(),
|
destination.getServiceId(),
|
||||||
0),
|
0),
|
||||||
receiveConfig));
|
receiveConfig);
|
||||||
|
actions.addAll(dataResults.first());
|
||||||
|
longTexts.putAll(dataResults.second());
|
||||||
}
|
}
|
||||||
if (message.getStoryMessage().isPresent()) {
|
if (message.getStoryMessage().isPresent()) {
|
||||||
actions.addAll(handleSignalServiceStoryMessage(message.getStoryMessage().get(),
|
actions.addAll(handleSignalServiceStoryMessage(message.getStoryMessage().get(),
|
||||||
@ -643,7 +662,7 @@ public final class IncomingMessageHandler {
|
|||||||
actions.add(RetrieveDeviceNameAction.create());
|
actions.add(RetrieveDeviceNameAction.create());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return actions;
|
return new Pair<>(actions, longTexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SignalServiceGroupContext getGroupContext(SignalServiceContent content) {
|
private SignalServiceGroupContext getGroupContext(SignalServiceContent content) {
|
||||||
@ -742,13 +761,14 @@ public final class IncomingMessageHandler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<HandleAction> handleSignalServiceDataMessage(
|
private Pair<List<HandleAction>, Map<String, String>> handleSignalServiceDataMessage(
|
||||||
SignalServiceDataMessage message,
|
SignalServiceDataMessage message,
|
||||||
boolean isSync,
|
boolean isSync,
|
||||||
DeviceAddress source,
|
DeviceAddress source,
|
||||||
DeviceAddress destination,
|
DeviceAddress destination,
|
||||||
ReceiveConfig receiveConfig
|
ReceiveConfig receiveConfig
|
||||||
) {
|
) {
|
||||||
|
final var longTexts = new HashMap<String, String>();
|
||||||
var actions = new ArrayList<HandleAction>();
|
var actions = new ArrayList<HandleAction>();
|
||||||
if (message.getGroupContext().isPresent()) {
|
if (message.getGroupContext().isPresent()) {
|
||||||
final var groupContext = message.getGroupContext().get();
|
final var groupContext = message.getGroupContext().get();
|
||||||
@ -843,6 +863,17 @@ public final class IncomingMessageHandler {
|
|||||||
if (message.getAttachments().isPresent()) {
|
if (message.getAttachments().isPresent()) {
|
||||||
for (var attachment : message.getAttachments().get()) {
|
for (var attachment : message.getAttachments().get()) {
|
||||||
context.getAttachmentHelper().downloadAttachment(attachment);
|
context.getAttachmentHelper().downloadAttachment(attachment);
|
||||||
|
if (attachment.isPointer()) {
|
||||||
|
final var file = context.getAttachmentHelper().getAttachmentFile(attachment.asPointer());
|
||||||
|
if (MimeUtils.LONG_TEXT.equals(attachment.getContentType()) && attachment.isPointer()) {
|
||||||
|
try {
|
||||||
|
final var longText = Files.readString(file.toPath());
|
||||||
|
longTexts.put(attachment.asPointer().getRemoteId().toString(), longText);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Failed to read long text attachment, ignoring", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (message.getSharedContacts().isPresent()) {
|
if (message.getSharedContacts().isPresent()) {
|
||||||
@ -872,6 +903,21 @@ public final class IncomingMessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (message.getAttachments().isPresent()) {
|
||||||
|
for (var attachment : message.getAttachments().get()) {
|
||||||
|
if (MimeUtils.LONG_TEXT.equals(attachment.getContentType()) && attachment.isPointer()) {
|
||||||
|
try {
|
||||||
|
context.getAttachmentHelper().retrieveAttachment(attachment, in -> {
|
||||||
|
final var longText = new String(in.readAllBytes(), StandardCharsets.UTF_8);
|
||||||
|
longTexts.put(attachment.asPointer().getRemoteId().toString(), longText);
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Failed to download long text attachment, ignoring", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (message.getGiftBadge().isPresent()) {
|
if (message.getGiftBadge().isPresent()) {
|
||||||
handleIncomingGiftBadge(message.getGiftBadge().get());
|
handleIncomingGiftBadge(message.getGiftBadge().get());
|
||||||
@ -892,7 +938,7 @@ public final class IncomingMessageHandler {
|
|||||||
.enqueueJob(new RetrieveStickerPackJob(stickerPackId, messageSticker.getPackKey()));
|
.enqueueJob(new RetrieveStickerPackJob(stickerPackId, messageSticker.getPackKey()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return actions;
|
return new Pair<>(actions, longTexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleIncomingGiftBadge(final SignalServiceDataMessage.GiftBadge giftBadge) {
|
private void handleIncomingGiftBadge(final SignalServiceDataMessage.GiftBadge giftBadge) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user