Merge pull request #508 from Brice-W/data-extraction-2

Data extraction notifications
This commit is contained in:
Niels Andriesse
2021-04-21 13:44:46 +10:00
committed by GitHub
21 changed files with 239 additions and 36 deletions

View File

@@ -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.attachments.DatabaseAttachment
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
@@ -159,4 +160,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?, attachments: List<Attachment>): Long?
}
// Data Extraction Notification
fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long)
}

View File

@@ -9,7 +9,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 =
when(this) {
@@ -46,7 +46,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
}
}
@@ -62,7 +62,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()
@@ -73,5 +73,4 @@ class DataExtractionNotification(): ControlMessage() {
return null
}
}
}
}

View File

@@ -3,10 +3,11 @@ 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.linkpreview.LinkPreview;
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel;
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;
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel;
import org.session.libsession.utilities.GroupUtil;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
@@ -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;
@@ -73,7 +78,7 @@ public class IncomingMediaMessage {
Optional<List<LinkPreview>> linkPreviews)
{
return new IncomingMediaMessage(from, message.getSentTimestamp(), -1, expiresIn, false,
false, Optional.fromNullable(message.getText()), group, Optional.fromNullable(attachments), quote, Optional.absent(), linkPreviews);
false, Optional.fromNullable(message.getText()), group, Optional.fromNullable(attachments), quote, Optional.absent(), linkPreviews, Optional.absent());
}
public int getSubscriptionId() {
@@ -116,6 +121,20 @@ public class IncomingMediaMessage {
return groupId != null;
}
public boolean isScreenshotDataExtraction() {
if (dataExtractionNotification == null) return false;
else {
return dataExtractionNotification.getKind() == DataExtractionNotificationInfoMessage.Kind.SCREENSHOT;
}
}
public boolean isMediaSavedDataExtraction() {
if (dataExtractionNotification == null) return false;
else {
return dataExtractionNotification.getKind() == DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED;
}
}
public QuoteModel getQuote() {
return quote;
}

View File

@@ -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
@@ -45,6 +46,7 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content,
is TypingIndicator -> handleTypingIndicator(message)
is ClosedGroupControlMessage -> handleClosedGroupControlMessage(message)
is ExpirationTimerUpdate -> handleExpirationTimerUpdate(message)
is DataExtractionNotification -> handleDataExtractionNotification(message)
is ConfigurationMessage -> handleConfigurationMessage(message)
is VisibleMessage -> handleVisibleMessage(message, proto, openGroupID)
}
@@ -91,6 +93,24 @@ private fun MessageReceiver.handleExpirationTimerUpdate(message: ExpirationTimer
}
}
// Data Extraction Notification handling
private fun MessageReceiver.handleDataExtractionNotification(message: DataExtractionNotification) {
// we don't handle data extraction messages for groups (they shouldn't be sent, but in case we filter them here too)
if (message.groupPublicKey != null) return
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.MEDIA_SAVED)
else -> return
}
storage.insertDataExtractionNotificationMessage(senderPublicKey, notification, message.sentTimestamp!!)
}
// Configuration message handling
private fun MessageReceiver.handleConfigurationMessage(message: ConfigurationMessage) {
val context = MessagingConfiguration.shared.context
val storage = MessagingConfiguration.shared.storage
@@ -153,7 +173,8 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS
}
}
// Get or create thread
val threadID = storage.getOrCreateThreadIdFor(message.syncTarget ?: message.sender!!, message.groupPublicKey, openGroupID)
val threadID = storage.getOrCreateThreadIdFor(message.syncTarget
?: message.sender!!, message.groupPublicKey, openGroupID)
// Parse quote if needed
var quoteModel: QuoteModel? = null
if (message.quote != null && proto.dataMessage.hasQuote()) {
@@ -242,7 +263,7 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli
storage.updateMembers(groupID, members.map { Address.fromSerialized(it) })
} else {
storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }),
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp)
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp)
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
// Notify the user
if (userPublicKey == sender) {

View File

@@ -0,0 +1,16 @@
package org.session.libsession.messaging.sending_receiving.dataextraction
class DataExtractionNotificationInfoMessage {
enum class Kind {
SCREENSHOT,
MEDIA_SAVED
}
var kind: Kind? = null
constructor(kind: Kind?) {
this.kind = kind
}
}

View File

@@ -3,6 +3,7 @@ package org.session.libsession.messaging.utilities
import android.content.Context
import org.session.libsession.R
import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage
import org.session.libsession.utilities.ExpirationUtil
import org.session.libsignal.service.api.messages.SignalServiceGroup
@@ -78,7 +79,7 @@ object UpdateMessageBuilder {
if (!isOutgoing && sender == null) return ""
val senderName: String? = if (!isOutgoing) {
MessagingConfiguration.shared.storage.getDisplayNameForRecipient(sender!!) ?: sender
} else { sender }
} else { context.getString(R.string.MessageRecord_you) }
return if (duration <= 0) {
if (isOutgoing) context.getString(R.string.MessageRecord_you_disabled_disappearing_messages)
else context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, senderName)
@@ -89,8 +90,13 @@ object UpdateMessageBuilder {
}
}
//TODO do this when the current update is merged
fun buildDataExtractionMessage(): String {
return ""
fun buildDataExtractionMessage(context: Context, kind: DataExtractionNotificationInfoMessage.Kind, sender: String? = null): String {
val senderName = MessagingConfiguration.shared.storage.getDisplayNameForRecipient(sender!!) ?: sender
return when (kind) {
DataExtractionNotificationInfoMessage.Kind.SCREENSHOT ->
context.getString(R.string.MessageRecord_s_took_a_screenshot, senderName)
DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED ->
context.getString(R.string.MessageRecord_media_saved_by_s, senderName)
}
}
}

View File

@@ -509,6 +509,8 @@
<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_s_took_a_screenshot">%1$s took a screenshot.</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>