mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 00:37:47 +00:00
implementation of the receiving side of Data Extraction notifications & explicit group updates notifications
This commit is contained in:
parent
1daa2a336f
commit
471e028cf3
@ -70,6 +70,10 @@ public interface MmsSmsColumns {
|
||||
protected static final long GROUP_UPDATE_BIT = 0x10000;
|
||||
protected static final long GROUP_QUIT_BIT = 0x20000;
|
||||
protected static final long EXPIRATION_TIMER_UPDATE_BIT = 0x40000;
|
||||
protected static final long GROUP_CREATION_BIT = 0x80000;
|
||||
protected static final long GROUP_NAME_UPDATE_BIT = 0x16000;
|
||||
protected static final long GROUP_MEMBER_ADDED_BIT = 0x32000;
|
||||
protected static final long GROUP_MEMBER_REMOVED_BIT = 0x64000;
|
||||
|
||||
// Encrypted Storage Information XXX
|
||||
public static final long ENCRYPTION_MASK = 0xFF000000;
|
||||
@ -84,6 +88,8 @@ public interface MmsSmsColumns {
|
||||
// Loki
|
||||
protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT = 0x01000000;
|
||||
protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT = 0x00100000;
|
||||
protected static final long DATA_EXTRACTION_SCREENSHOT_BIT = 0x00010000;
|
||||
protected static final long DATA_EXTRACTION_MEDIA_SAVED_BIT = 0x00001000;
|
||||
|
||||
public static boolean isDraftMessageType(long type) {
|
||||
return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE;
|
||||
@ -197,6 +203,16 @@ public interface MmsSmsColumns {
|
||||
return (type & EXPIRATION_TIMER_UPDATE_BIT) != 0;
|
||||
}
|
||||
|
||||
// DATA EXTRACTION NOTIFICATION
|
||||
|
||||
public static boolean isDataExtractionScreenshotUpdate(long type) {
|
||||
return (type & DATA_EXTRACTION_SCREENSHOT_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isDataExtractionMediaSavedUpdate(long type) {
|
||||
return (type & DATA_EXTRACTION_MEDIA_SAVED_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isIncomingCall(long type) {
|
||||
return type == INCOMING_CALL_TYPE;
|
||||
}
|
||||
@ -209,14 +225,34 @@ public interface MmsSmsColumns {
|
||||
return type == MISSED_CALL_TYPE;
|
||||
}
|
||||
|
||||
// GROUPS EXPLICIT UPDATES
|
||||
|
||||
public static boolean isGroupUpdate(long type) {
|
||||
return (type & GROUP_UPDATE_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isGroupCreation(long type) {
|
||||
return (type & GROUP_CREATION_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isGroupNameUpdate(long type) {
|
||||
return (type & GROUP_NAME_UPDATE_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isGroupMemberAdded(long type) {
|
||||
return (type & GROUP_MEMBER_ADDED_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isGroupMemberRemoved(long type) {
|
||||
return (type & GROUP_MEMBER_REMOVED_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isGroupQuit(long type) {
|
||||
return (type & GROUP_QUIT_BIT) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static boolean isFailedDecryptType(long type) {
|
||||
return (type & ENCRYPTION_REMOTE_FAILED_BIT) != 0;
|
||||
}
|
||||
|
@ -8,18 +8,23 @@ import org.session.libsession.messaging.jobs.AttachmentUploadJob
|
||||
import org.session.libsession.messaging.jobs.Job
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.jobs.MessageSendJob
|
||||
import org.session.libsession.messaging.messages.signal.*
|
||||
import org.session.libsession.messaging.messages.visible.Attachment
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||
import org.session.libsession.messaging.opengroups.OpenGroup
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment
|
||||
import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.messaging.threads.Address.Companion.fromSerialized
|
||||
import org.session.libsession.messaging.threads.GroupRecord
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.IdentityKeyUtil
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.preferences.ProfileKeyUtil
|
||||
import org.session.libsignal.libsignal.ecc.ECKeyPair
|
||||
import org.session.libsignal.libsignal.util.KeyHelper
|
||||
import org.session.libsignal.libsignal.util.guava.Optional
|
||||
@ -29,21 +34,13 @@ import org.session.libsignal.service.api.messages.SignalServiceGroup
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.session.libsession.utilities.IdentityKeyUtil
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol
|
||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
|
||||
import org.thoughtcrime.securesms.loki.utilities.get
|
||||
import org.thoughtcrime.securesms.loki.utilities.getString
|
||||
import org.session.libsession.messaging.messages.signal.IncomingMediaMessage
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingGroupMediaMessage
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||
import org.session.libsession.messaging.messages.signal.IncomingGroupMessage
|
||||
import org.session.libsession.messaging.messages.signal.IncomingTextMessage
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage
|
||||
import org.session.libsession.utilities.preferences.ProfileKeyUtil
|
||||
|
||||
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
|
||||
override fun getUserPublicKey(): String? {
|
||||
@ -125,17 +122,21 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
PointerAttachment.forPointer(Optional.of(it)).orNull()
|
||||
}
|
||||
val mediaMessage = OutgoingMediaMessage.from(message, Recipient.from(context, targetAddress, false), attachments, quote.orNull(), linkPreviews.orNull().firstOrNull())
|
||||
mmsDatabase.insertSecureDecryptedMessageOutbox(mediaMessage, message.threadID ?: -1, message.sentTimestamp!!)
|
||||
mmsDatabase.insertSecureDecryptedMessageOutbox(mediaMessage, message.threadID
|
||||
?: -1, message.sentTimestamp!!)
|
||||
} else {
|
||||
// It seems like we have replaced SignalServiceAttachment with SessionServiceAttachment
|
||||
val attachments: Optional<List<SignalServiceAttachment>> = Optional.of(message.attachmentIDs.mapNotNull {
|
||||
DatabaseFactory.getAttachmentProvider(context).getSignalAttachmentPointer(it)
|
||||
})
|
||||
val mediaMessage = IncomingMediaMessage.from(message, senderAddress, senderRecipient.expireMessages * 1000L, group, attachments, quote, linkPreviews)
|
||||
// FIXME deal with DataExtraction parameter
|
||||
val mediaMessage = IncomingMediaMessage.from(message, senderAddress, senderRecipient.expireMessages * 1000L, group, attachments, quote, linkPreviews, Optional.absent())
|
||||
if (group.isPresent) {
|
||||
mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID ?: -1, message.sentTimestamp!!)
|
||||
mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID
|
||||
?: -1, message.sentTimestamp!!)
|
||||
} else {
|
||||
mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID ?: -1)
|
||||
mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID
|
||||
?: -1)
|
||||
}
|
||||
}
|
||||
if (insertResult.isPresent) {
|
||||
@ -157,7 +158,8 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
}
|
||||
}
|
||||
val textMessage = OutgoingTextMessage.from(message, Recipient.from(context, targetAddress, false))
|
||||
smsDatabase.insertMessageOutbox(message.threadID ?: -1, textMessage, message.sentTimestamp!!)
|
||||
smsDatabase.insertMessageOutbox(message.threadID
|
||||
?: -1, textMessage, message.sentTimestamp!!)
|
||||
} else {
|
||||
val textMessage = IncomingTextMessage.from(message, senderAddress, group, senderRecipient.expireMessages * 1000L)
|
||||
if (group.isPresent) {
|
||||
@ -417,7 +419,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, sentTimestamp, 0, null, listOf(), listOf())
|
||||
val mmsDB = DatabaseFactory.getMmsDatabase(context)
|
||||
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
|
||||
if (mmsSmsDB.getMessageFor(sentTimestamp,userPublicKey) != null) return
|
||||
if (mmsSmsDB.getMessageFor(sentTimestamp, userPublicKey) != null) return
|
||||
val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null)
|
||||
mmsDB.markAsSent(infoMessageID, true)
|
||||
}
|
||||
@ -538,4 +540,30 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
override fun getAttachmentThumbnailUri(attachmentId: AttachmentId): Uri {
|
||||
return PartAuthority.getAttachmentThumbnailUri(attachmentId)
|
||||
}
|
||||
|
||||
// Data Extraction Notification
|
||||
override fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, groupID: String?, sentTimestamp: Long) {
|
||||
val database = DatabaseFactory.getMmsDatabase(context)
|
||||
val address = fromSerialized(senderPublicKey)
|
||||
val recipient = Recipient.from(context, address, false)
|
||||
|
||||
if (recipient.isBlocked) return
|
||||
|
||||
var groupInfo = Optional.absent<SignalServiceGroup?>()
|
||||
if (groupID != null) {
|
||||
groupInfo = Optional.of(SignalServiceGroup(groupID.toByteArray(), SignalServiceGroup.GroupType.SIGNAL))
|
||||
}
|
||||
val mediaMessage = IncomingMediaMessage(address, sentTimestamp, -1,
|
||||
0, false,
|
||||
false,
|
||||
Optional.absent(),
|
||||
groupInfo,
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.of(message))
|
||||
|
||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1)
|
||||
}
|
||||
}
|
@ -113,6 +113,14 @@ public abstract class DisplayRecord {
|
||||
return SmsDatabase.Types.isGroupUpdate(type);
|
||||
}
|
||||
|
||||
public boolean isGroupCreation() { return MmsSmsColumns.Types.isGroupCreation(type); }
|
||||
|
||||
public boolean isGroupNameUpdate() { return MmsSmsColumns.Types.isGroupNameUpdate(type); }
|
||||
|
||||
public boolean isGroupMemberAdded() { return MmsSmsColumns.Types.isGroupMemberAdded(type); }
|
||||
|
||||
public boolean isGroupMemberRemoved() { return MmsSmsColumns.Types.isGroupMemberRemoved(type); }
|
||||
|
||||
public boolean isGroupQuit() {
|
||||
return SmsDatabase.Types.isGroupQuit(type);
|
||||
}
|
||||
@ -125,6 +133,14 @@ public abstract class DisplayRecord {
|
||||
return SmsDatabase.Types.isExpirationTimerUpdate(type);
|
||||
}
|
||||
|
||||
public boolean isDataExtractionScreenshot() {
|
||||
return MmsSmsColumns.Types.isDataExtractionScreenshotUpdate(type);
|
||||
}
|
||||
|
||||
public boolean isDataExtractionMediaSaved() {
|
||||
return MmsSmsColumns.Types.isDataExtractionMediaSavedUpdate(type);
|
||||
}
|
||||
|
||||
public boolean isCallLog() {
|
||||
return SmsDatabase.Types.isCallLog(type);
|
||||
}
|
||||
|
@ -90,10 +90,26 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
|
||||
@Override
|
||||
public SpannableString getDisplayBody(@NonNull Context context) {
|
||||
if (isGroupUpdate() && isOutgoing()) {
|
||||
if (isGroupCreation() && isOutgoing()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_you_created_a_new_group));
|
||||
} else if (isGroupCreation()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_s_created_a_new_group, getIndividualRecipient().toShortString()));
|
||||
} else if (isGroupUpdate() && isOutgoing()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_you_updated_group));
|
||||
} else if (isGroupUpdate()) {
|
||||
return new SpannableString(GroupDescription.Companion.getDescription(context, getBody()).toString(getIndividualRecipient()));
|
||||
} else if (isGroupNameUpdate() && isOutgoing()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_you_renamed_the_group));
|
||||
} else if (isGroupNameUpdate()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_s_renamed_the_group, getIndividualRecipient().toShortString()));
|
||||
} else if (isGroupMemberAdded() && isOutgoing()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_you_added_new_members_to_the_group));
|
||||
} else if (isGroupMemberAdded()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_s_added_new_members_to_the_group, getIndividualRecipient().toShortString()));
|
||||
} else if (isGroupMemberRemoved() && isOutgoing()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_you_added_new_members_to_the_group));
|
||||
} else if (isGroupMemberRemoved()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_s_removed_members_from_the_group, getIndividualRecipient().toShortString()));
|
||||
} else if (isGroupQuit() && isOutgoing()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_left_group));
|
||||
} else if (isGroupQuit()) {
|
||||
@ -107,14 +123,20 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
} else if (isJoined()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_s_joined_signal, getIndividualRecipient().toShortString()));
|
||||
} else if (isExpirationTimerUpdate()) {
|
||||
int seconds = (int)(getExpiresIn() / 1000);
|
||||
int seconds = (int) (getExpiresIn() / 1000);
|
||||
if (seconds <= 0) {
|
||||
return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_disabled_disappearing_messages))
|
||||
: new SpannableString(context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, getIndividualRecipient().toShortString()));
|
||||
: new SpannableString(context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, getIndividualRecipient().toShortString()));
|
||||
}
|
||||
String time = ExpirationUtil.getExpirationDisplayValue(context, seconds);
|
||||
return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time))
|
||||
: new SpannableString(context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, getIndividualRecipient().toShortString(), time));
|
||||
: new SpannableString(context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, getIndividualRecipient().toShortString(), time));
|
||||
} else if (isDataExtractionScreenshot()) {
|
||||
return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_took_a_screenshot))
|
||||
: new SpannableString(context.getString(R.string.MessageRecord_s_took_a_screenshot, getIndividualRecipient().toShortString()));
|
||||
} else if (isDataExtractionMediaSaved()) {
|
||||
return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_media_saved_by_you))
|
||||
: new SpannableString(context.getString(R.string.MessageRecord_media_saved_by_s, getIndividualRecipient().toShortString()));
|
||||
} else if (isIdentityUpdate()) {
|
||||
return new SpannableString(context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, getIndividualRecipient().toShortString()));
|
||||
} else if (isIdentityVerified()) {
|
||||
|
@ -272,6 +272,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent());
|
||||
|
||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
|
||||
@ -371,9 +372,10 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
}
|
||||
|
||||
} else {
|
||||
// FIXME handle DataExtraction parameter below where Optional.absent() is
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterAddress, message.getTimestamp(), -1,
|
||||
message.getExpiresInSeconds() * 1000L, false, content.isNeedsReceipt(), message.getBody(), message.getGroupInfo(), message.getAttachments(),
|
||||
quote, sharedContacts, linkPreviews);
|
||||
quote, sharedContacts, linkPreviews, Optional.absent());
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
database.beginTransaction();
|
||||
|
||||
|
@ -86,6 +86,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent());
|
||||
|
||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
|
||||
|
@ -493,6 +493,14 @@
|
||||
<string name="MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported">Received a message encrypted using an old version of Session that is no longer supported. Please ask the sender to update to the most recent version and resend the message.</string>
|
||||
<string name="MessageRecord_left_group">You have left the group.</string>
|
||||
<string name="MessageRecord_you_updated_group">You updated the group.</string>
|
||||
<string name="MessageRecord_you_created_a_new_group">You created a new group.</string>
|
||||
<string name="MessageRecord_s_created_a_new_group">%1$s created a new group.</string>
|
||||
<string name="MessageRecord_you_renamed_the_group">You renamed the group.</string>
|
||||
<string name="MessageRecord_s_renamed_the_group">%1$s renamed the group.</string>
|
||||
<string name="MessageRecord_you_added_new_members_to_the_group">You added new members to the group.</string>
|
||||
<string name="MessageRecord_s_added_new_members_to_the_group">%1$s added new members to the group.</string>
|
||||
<string name="MessageRecord_you_removed_members_from_the_group">You removed members from the group.</string>
|
||||
<string name="MessageRecord_s_removed_members_from_the_group">%1$s removed members from the group.</string>
|
||||
<string name="MessageRecord_you_called">You called</string>
|
||||
<string name="MessageRecord_called_you">Contact called</string>
|
||||
<string name="MessageRecord_missed_call">Missed call</string>
|
||||
@ -505,6 +513,10 @@
|
||||
<string name="MessageRecord_s_disabled_disappearing_messages">%1$s disabled disappearing messages.</string>
|
||||
<string name="MessageRecord_you_set_disappearing_message_time_to_s">You set the disappearing message timer to %1$s</string>
|
||||
<string name="MessageRecord_s_set_disappearing_message_time_to_s">%1$s set the disappearing message timer to %2$s</string>
|
||||
<string name="MessageRecord_you_took_a_screenshot">You took a screenshot.</string>
|
||||
<string name="MessageRecord_s_took_a_screenshot">%1$s took a screenshot.</string>
|
||||
<string name="MessageRecord_media_saved_by_you">Media saved by you.</string>
|
||||
<string name="MessageRecord_media_saved_by_s">Media saved by %1$s.</string>
|
||||
<string name="MessageRecord_your_safety_number_with_s_has_changed">Your safety number with %s has changed.</string>
|
||||
<string name="MessageRecord_you_marked_your_safety_number_with_s_verified">You marked your safety number with %s verified</string>
|
||||
<string name="MessageRecord_you_marked_your_safety_number_with_s_verified_from_another_device">You marked your safety number with %s verified from another device</string>
|
||||
|
@ -11,6 +11,7 @@ import org.session.libsession.messaging.messages.visible.Attachment
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||
import org.session.libsession.messaging.opengroups.OpenGroup
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
||||
import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
@ -152,4 +153,7 @@ interface StorageProtocol {
|
||||
// Message Handling
|
||||
/// Returns the ID of the `TSIncomingMessage` that was constructed.
|
||||
fun persist(message: VisibleMessage, quotes: QuoteModel?, linkPreview: List<LinkPreview?>, groupPublicKey: String?, openGroupID: String?): Long?
|
||||
|
||||
// Data Extraction Notification
|
||||
fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, groupID: String?, sentTimestamp: Long)
|
||||
}
|
@ -12,7 +12,7 @@ class DataExtractionNotification(): ControlMessage() {
|
||||
// Kind enum
|
||||
sealed class Kind {
|
||||
class Screenshot() : Kind()
|
||||
class MediaSaved(val timestanp: Long) : Kind()
|
||||
class MediaSaved(val timestamp: Long) : Kind()
|
||||
|
||||
val description: String = run {
|
||||
when(this) {
|
||||
@ -50,7 +50,7 @@ class DataExtractionNotification(): ControlMessage() {
|
||||
val kind = kind ?: return false
|
||||
return when(kind) {
|
||||
is Kind.Screenshot -> true
|
||||
is Kind.MediaSaved -> kind.timestanp > 0
|
||||
is Kind.MediaSaved -> kind.timestamp > 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ class DataExtractionNotification(): ControlMessage() {
|
||||
is Kind.Screenshot -> dataExtractionNotification.type = SignalServiceProtos.DataExtractionNotification.Type.SCREENSHOT
|
||||
is Kind.MediaSaved -> {
|
||||
dataExtractionNotification.type = SignalServiceProtos.DataExtractionNotification.Type.MEDIA_SAVED
|
||||
dataExtractionNotification.timestamp = kind.timestanp
|
||||
dataExtractionNotification.timestamp = kind.timestamp
|
||||
}
|
||||
}
|
||||
val contentProto = SignalServiceProtos.Content.newBuilder()
|
||||
|
@ -3,6 +3,7 @@ package org.session.libsession.messaging.messages.signal;
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment;
|
||||
import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage;
|
||||
import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
|
||||
import org.session.libsession.messaging.threads.Address;
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
@ -26,9 +27,11 @@ public class IncomingMediaMessage {
|
||||
private final int subscriptionId;
|
||||
private final long expiresIn;
|
||||
private final boolean expirationUpdate;
|
||||
private final QuoteModel quote;
|
||||
private final boolean unidentified;
|
||||
|
||||
private final DataExtractionNotificationInfoMessage dataExtractionNotification;
|
||||
private final QuoteModel quote;
|
||||
|
||||
private final List<Attachment> attachments = new LinkedList<>();
|
||||
private final List<Contact> sharedContacts = new LinkedList<>();
|
||||
private final List<LinkPreview> linkPreviews = new LinkedList<>();
|
||||
@ -44,17 +47,19 @@ public class IncomingMediaMessage {
|
||||
Optional<List<SignalServiceAttachment>> attachments,
|
||||
Optional<QuoteModel> quote,
|
||||
Optional<List<Contact>> sharedContacts,
|
||||
Optional<List<LinkPreview>> linkPreviews)
|
||||
Optional<List<LinkPreview>> linkPreviews,
|
||||
Optional<DataExtractionNotificationInfoMessage> dataExtractionNotification)
|
||||
{
|
||||
this.push = true;
|
||||
this.from = from;
|
||||
this.sentTimeMillis = sentTimeMillis;
|
||||
this.body = body.orNull();
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresIn = expiresIn;
|
||||
this.expirationUpdate = expirationUpdate;
|
||||
this.quote = quote.orNull();
|
||||
this.unidentified = unidentified;
|
||||
this.push = true;
|
||||
this.from = from;
|
||||
this.sentTimeMillis = sentTimeMillis;
|
||||
this.body = body.orNull();
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresIn = expiresIn;
|
||||
this.expirationUpdate = expirationUpdate;
|
||||
this.dataExtractionNotification = dataExtractionNotification.orNull();
|
||||
this.quote = quote.orNull();
|
||||
this.unidentified = unidentified;
|
||||
|
||||
if (group.isPresent()) this.groupId = Address.fromSerialized(GroupUtil.INSTANCE.getEncodedId(group.get()));
|
||||
else this.groupId = null;
|
||||
@ -70,10 +75,11 @@ public class IncomingMediaMessage {
|
||||
Optional<SignalServiceGroup> group,
|
||||
Optional<List<SignalServiceAttachment>> attachments,
|
||||
Optional<QuoteModel> quote,
|
||||
Optional<List<LinkPreview>> linkPreviews)
|
||||
Optional<List<LinkPreview>> linkPreviews,
|
||||
Optional<DataExtractionNotificationInfoMessage> dataExtractionNotification)
|
||||
{
|
||||
return new IncomingMediaMessage(from, message.getReceivedTimestamp(), -1, expiresIn, false,
|
||||
false, Optional.fromNullable(message.getText()), group, attachments, quote, Optional.absent(), linkPreviews);
|
||||
false, Optional.fromNullable(message.getText()), group, attachments, quote, Optional.absent(), linkPreviews, dataExtractionNotification);
|
||||
}
|
||||
|
||||
public int getSubscriptionId() {
|
||||
@ -128,6 +134,8 @@ public class IncomingMediaMessage {
|
||||
return linkPreviews;
|
||||
}
|
||||
|
||||
public DataExtractionNotificationInfoMessage getDataExtractionNotification() { return dataExtractionNotification; }
|
||||
|
||||
public boolean isUnidentified() {
|
||||
return unidentified;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import org.session.libsession.messaging.messages.control.*
|
||||
import org.session.libsession.messaging.messages.visible.Attachment
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment
|
||||
import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
@ -43,6 +44,7 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content,
|
||||
is TypingIndicator -> handleTypingIndicator(message)
|
||||
is ClosedGroupControlMessage -> handleClosedGroupControlMessage(message)
|
||||
is ExpirationTimerUpdate -> handleExpirationTimerUpdate(message, proto)
|
||||
is DataExtractionNotification -> handleDataExtractionNotification(message)
|
||||
is ConfigurationMessage -> handleConfigurationMessage(message)
|
||||
is VisibleMessage -> handleVisibleMessage(message, proto, openGroupID)
|
||||
}
|
||||
@ -102,6 +104,21 @@ fun MessageReceiver.disableExpirationTimer(message: ExpirationTimerUpdate, proto
|
||||
SSKEnvironment.shared.messageExpirationManager.disableExpirationTimer(id, senderPublicKey, proto)
|
||||
}
|
||||
|
||||
// Data Extraction Notification handling
|
||||
|
||||
private fun MessageReceiver.handleDataExtractionNotification(message: DataExtractionNotification) {
|
||||
val storage = MessagingConfiguration.shared.storage
|
||||
val senderPublicKey = message.sender!!
|
||||
val notification: DataExtractionNotificationInfoMessage = when(message.kind) {
|
||||
is DataExtractionNotification.Kind.Screenshot -> DataExtractionNotificationInfoMessage(DataExtractionNotificationInfoMessage.Kind.SCREENSHOT)
|
||||
is DataExtractionNotification.Kind.MediaSaved -> DataExtractionNotificationInfoMessage(DataExtractionNotificationInfoMessage.Kind.MEDIASAVED)
|
||||
else -> return
|
||||
}
|
||||
storage.insertDataExtractionNotificationMessage(senderPublicKey, notification, message.groupPublicKey, message.sentTimestamp!!)
|
||||
}
|
||||
|
||||
// Configuration message handling
|
||||
|
||||
private fun MessageReceiver.handleConfigurationMessage(message: ConfigurationMessage) {
|
||||
val context = MessagingConfiguration.shared.context
|
||||
val storage = MessagingConfiguration.shared.storage
|
||||
@ -239,7 +256,7 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli
|
||||
storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }),
|
||||
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp)
|
||||
// Notify the user
|
||||
storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp)
|
||||
storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.NEW, name, members, admins, sentTimestamp)
|
||||
}
|
||||
storage.setProfileSharing(Address.fromSerialized(groupID), true)
|
||||
// Add the group to the user's set of public keys to poll for
|
||||
@ -356,7 +373,7 @@ private fun MessageReceiver.handleClosedGroupNameChanged(message: ClosedGroupCon
|
||||
val name = kind.name
|
||||
storage.updateTitle(groupID, name)
|
||||
|
||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, message.sentTimestamp!!)
|
||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.NAME_UPDATE, name, members, admins, message.sentTimestamp!!)
|
||||
}
|
||||
|
||||
private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupControlMessage) {
|
||||
@ -384,7 +401,7 @@ private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupCo
|
||||
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, name, members, admins, threadID, message.sentTimestamp!!)
|
||||
} else {
|
||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, message.sentTimestamp!!)
|
||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.MEMBER_ADDED, name, members, admins, message.sentTimestamp!!)
|
||||
}
|
||||
if (userPublicKey in admins) {
|
||||
// send current encryption key to the latest added members
|
||||
@ -445,7 +462,7 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup
|
||||
}
|
||||
val (contextType, signalType) =
|
||||
if (senderLeft) SignalServiceProtos.GroupContext.Type.QUIT to SignalServiceGroup.Type.QUIT
|
||||
else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.UPDATE
|
||||
else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.MEMBER_REMOVED
|
||||
|
||||
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins, message.sentTimestamp!!)
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package org.session.libsession.messaging.sending_receiving.dataextraction
|
||||
|
||||
class DataExtractionNotificationInfoMessage {
|
||||
|
||||
enum class Kind {
|
||||
SCREENSHOT,
|
||||
MEDIASAVED
|
||||
}
|
||||
|
||||
var kind: Kind? = null
|
||||
|
||||
constructor(kind: Kind?) {
|
||||
this.kind = kind
|
||||
}
|
||||
|
||||
}
|
@ -37,7 +37,11 @@ public class SignalServiceGroup {
|
||||
UPDATE,
|
||||
DELIVER,
|
||||
QUIT,
|
||||
REQUEST_INFO
|
||||
REQUEST_INFO,
|
||||
NEW,
|
||||
NAME_UPDATE,
|
||||
MEMBER_ADDED,
|
||||
MEMBER_REMOVED
|
||||
}
|
||||
|
||||
private final byte[] groupId;
|
||||
|
Loading…
x
Reference in New Issue
Block a user