add 'encryption' and 'identityKey' to message version entity
This commit is contained in:
parent
677cfcd34c
commit
cf5910e96e
|
@ -2,7 +2,7 @@
|
||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"identityHash": "6186e2691813f4fbd804b90fd770e18b",
|
"identityHash": "a619bdeae0408fc2250a0bf2b9ab1f4e",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "account",
|
"tableName": "account",
|
||||||
|
@ -1834,7 +1834,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "message_version",
|
"tableName": "message_version",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `messageEntityId` INTEGER NOT NULL, `messageId` TEXT, `stanzaId` TEXT, `modification` TEXT, `modifiedBy` TEXT, `modifiedByResource` TEXT, `occupantId` TEXT, `receivedAt` INTEGER, FOREIGN KEY(`messageEntityId`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `messageEntityId` INTEGER NOT NULL, `messageId` TEXT, `stanzaId` TEXT, `modification` TEXT, `modifiedBy` TEXT, `modifiedByResource` TEXT, `occupantId` TEXT, `receivedAt` INTEGER, `encryption` TEXT, `identityKey` BLOB, FOREIGN KEY(`messageEntityId`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "id",
|
"fieldPath": "id",
|
||||||
|
@ -1889,6 +1889,18 @@
|
||||||
"columnName": "receivedAt",
|
"columnName": "receivedAt",
|
||||||
"affinity": "INTEGER",
|
"affinity": "INTEGER",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "encryption",
|
||||||
|
"columnName": "encryption",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "identityKey",
|
||||||
|
"columnName": "identityKey",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
|
@ -2352,7 +2364,7 @@
|
||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6186e2691813f4fbd804b90fd770e18b')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a619bdeae0408fc2250a0bf2b9ab1f4e')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ import com.google.common.collect.Iterables;
|
||||||
import im.conversations.android.IDs;
|
import im.conversations.android.IDs;
|
||||||
import im.conversations.android.database.ConversationsDatabase;
|
import im.conversations.android.database.ConversationsDatabase;
|
||||||
import im.conversations.android.database.entity.AccountEntity;
|
import im.conversations.android.database.entity.AccountEntity;
|
||||||
|
import im.conversations.android.database.model.Encryption;
|
||||||
import im.conversations.android.database.model.MessageEmbedded;
|
import im.conversations.android.database.model.MessageEmbedded;
|
||||||
import im.conversations.android.database.model.Modification;
|
import im.conversations.android.database.model.Modification;
|
||||||
import im.conversations.android.database.model.PartType;
|
import im.conversations.android.database.model.PartType;
|
||||||
|
@ -83,6 +84,7 @@ public class MessageTransformationTest {
|
||||||
final var message = Iterables.getOnlyElement(messages);
|
final var message = Iterables.getOnlyElement(messages);
|
||||||
final var onlyContent = Iterables.getOnlyElement(message.contents);
|
final var onlyContent = Iterables.getOnlyElement(message.contents);
|
||||||
Assert.assertEquals(GREETING, onlyContent.body);
|
Assert.assertEquals(GREETING, onlyContent.body);
|
||||||
|
Assert.assertEquals(Encryption.CLEARTEXT,message.encryption);
|
||||||
final var onlyReaction = Iterables.getOnlyElement(message.reactions);
|
final var onlyReaction = Iterables.getOnlyElement(message.reactions);
|
||||||
Assert.assertEquals("Y", onlyReaction.reaction);
|
Assert.assertEquals("Y", onlyReaction.reaction);
|
||||||
Assert.assertEquals(REMOTE, onlyReaction.reactionBy);
|
Assert.assertEquals(REMOTE, onlyReaction.reactionBy);
|
||||||
|
|
|
@ -16,11 +16,12 @@ import im.conversations.android.database.entity.MessageStateEntity;
|
||||||
import im.conversations.android.database.entity.MessageVersionEntity;
|
import im.conversations.android.database.entity.MessageVersionEntity;
|
||||||
import im.conversations.android.database.model.Account;
|
import im.conversations.android.database.model.Account;
|
||||||
import im.conversations.android.database.model.ChatIdentifier;
|
import im.conversations.android.database.model.ChatIdentifier;
|
||||||
import im.conversations.android.database.model.MessageContent;
|
import im.conversations.android.database.model.Encryption;
|
||||||
import im.conversations.android.database.model.MessageIdentifier;
|
import im.conversations.android.database.model.MessageIdentifier;
|
||||||
import im.conversations.android.database.model.MessageState;
|
import im.conversations.android.database.model.MessageState;
|
||||||
import im.conversations.android.database.model.MessageWithContentReactions;
|
import im.conversations.android.database.model.MessageWithContentReactions;
|
||||||
import im.conversations.android.database.model.Modification;
|
import im.conversations.android.database.model.Modification;
|
||||||
|
import im.conversations.android.transformer.MessageContentWrapper;
|
||||||
import im.conversations.android.transformer.MessageTransformation;
|
import im.conversations.android.transformer.MessageTransformation;
|
||||||
import im.conversations.android.xmpp.model.reactions.Reactions;
|
import im.conversations.android.xmpp.model.reactions.Reactions;
|
||||||
import im.conversations.android.xmpp.model.stanza.Message;
|
import im.conversations.android.xmpp.model.stanza.Message;
|
||||||
|
@ -31,6 +32,7 @@ import org.jxmpp.jid.Jid;
|
||||||
import org.jxmpp.jid.parts.Resourcepart;
|
import org.jxmpp.jid.parts.Resourcepart;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
public abstract class MessageDao {
|
public abstract class MessageDao {
|
||||||
|
@ -324,19 +326,37 @@ public abstract class MessageDao {
|
||||||
+ " chatId=:chatId AND stanzaId=:stanzaId")
|
+ " chatId=:chatId AND stanzaId=:stanzaId")
|
||||||
protected abstract MessageIdentifier getByStanzaId(final long chatId, final String stanzaId);
|
protected abstract MessageIdentifier getByStanzaId(final long chatId, final String stanzaId);
|
||||||
|
|
||||||
public void insertMessageContent(Long latestVersion, List<MessageContent> contents) {
|
public void insertMessageContent(
|
||||||
|
final Long latestVersion, final MessageContentWrapper messageContentWrapper) {
|
||||||
Preconditions.checkNotNull(
|
Preconditions.checkNotNull(
|
||||||
latestVersion, "Contents can only be inserted for a specific version");
|
latestVersion, "Contents can only be inserted for a specific version");
|
||||||
Preconditions.checkArgument(
|
Preconditions.checkArgument(
|
||||||
contents.size() > 0,
|
messageContentWrapper.contents.size() > 0,
|
||||||
"If you are trying to insert empty contents something went wrong");
|
"If you are trying to insert empty contents something went wrong");
|
||||||
insertMessageContent(
|
insertMessageContent(
|
||||||
Lists.transform(contents, c -> MessageContentEntity.of(latestVersion, c)));
|
Lists.transform(
|
||||||
|
messageContentWrapper.contents,
|
||||||
|
c -> MessageContentEntity.of(latestVersion, c)));
|
||||||
|
final int rows =
|
||||||
|
updateMessageVersionEncryption(
|
||||||
|
latestVersion,
|
||||||
|
messageContentWrapper.encryption,
|
||||||
|
messageContentWrapper.identityKey);
|
||||||
|
if (rows != 1) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"We expected to update encryption information on exactly 1 row");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
protected abstract void insertMessageContent(Collection<MessageContentEntity> contentEntities);
|
protected abstract void insertMessageContent(Collection<MessageContentEntity> contentEntities);
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
"UPDATE message_version SET encryption=:encryption,identityKey=:identityKey WHERE"
|
||||||
|
+ " id=:messageVersionId")
|
||||||
|
protected abstract int updateMessageVersionEncryption(
|
||||||
|
long messageVersionId, Encryption encryption, IdentityKey identityKey);
|
||||||
|
|
||||||
public void insertMessageState(
|
public void insertMessageState(
|
||||||
ChatIdentifier chatIdentifier,
|
ChatIdentifier chatIdentifier,
|
||||||
final String messageId,
|
final String messageId,
|
||||||
|
@ -402,9 +422,10 @@ public abstract class MessageDao {
|
||||||
@Query(
|
@Query(
|
||||||
"SELECT message.id as"
|
"SELECT message.id as"
|
||||||
+ " id,sentAt,outgoing,toBare,toResource,fromBare,fromResource,modification,latestVersion"
|
+ " id,sentAt,outgoing,toBare,toResource,fromBare,fromResource,modification,latestVersion"
|
||||||
+ " as version,inReplyToMessageEntityId FROM message JOIN message_version ON"
|
+ " as version,inReplyToMessageEntityId,encryption,identityKey FROM message JOIN"
|
||||||
+ " message.latestVersion=message_version.id WHERE message.chatId=:chatId AND"
|
+ " message_version ON message.latestVersion=message_version.id WHERE"
|
||||||
+ " latestVersion IS NOT NULL ORDER BY message.receivedAt")
|
+ " message.chatId=:chatId AND latestVersion IS NOT NULL ORDER BY"
|
||||||
|
+ " message.receivedAt")
|
||||||
public abstract List<MessageWithContentReactions> getMessages(long chatId);
|
public abstract List<MessageWithContentReactions> getMessages(long chatId);
|
||||||
|
|
||||||
public void setInReplyTo(
|
public void setInReplyTo(
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
package im.conversations.android.database.entity;
|
package im.conversations.android.database.entity;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
import androidx.room.ForeignKey;
|
import androidx.room.ForeignKey;
|
||||||
import androidx.room.Index;
|
import androidx.room.Index;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import im.conversations.android.database.model.Encryption;
|
||||||
import im.conversations.android.database.model.Modification;
|
import im.conversations.android.database.model.Modification;
|
||||||
import im.conversations.android.transformer.MessageTransformation;
|
import im.conversations.android.transformer.MessageTransformation;
|
||||||
import im.conversations.android.xmpp.model.stanza.Message;
|
import im.conversations.android.xmpp.model.stanza.Message;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
import org.jxmpp.jid.parts.Resourcepart;
|
import org.jxmpp.jid.parts.Resourcepart;
|
||||||
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
tableName = "message_version",
|
tableName = "message_version",
|
||||||
|
@ -36,6 +39,8 @@ public class MessageVersionEntity {
|
||||||
public Resourcepart modifiedByResource;
|
public Resourcepart modifiedByResource;
|
||||||
public String occupantId;
|
public String occupantId;
|
||||||
public Instant receivedAt;
|
public Instant receivedAt;
|
||||||
|
@Nullable public Encryption encryption;
|
||||||
|
@Nullable public IdentityKey identityKey;
|
||||||
|
|
||||||
// the version order is determined by the receivedAt
|
// the version order is determined by the receivedAt
|
||||||
// the actual display time and display order comes from the parent MessageEntity
|
// the actual display time and display order comes from the parent MessageEntity
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package im.conversations.android.database.model;
|
||||||
|
|
||||||
|
public enum Encryption {
|
||||||
|
OMEMO,
|
||||||
|
CLEARTEXT,
|
||||||
|
PGP
|
||||||
|
}
|
|
@ -1,8 +1,5 @@
|
||||||
package im.conversations.android.database.model;
|
package im.conversations.android.database.model;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MessageContent {
|
public class MessageContent {
|
||||||
|
|
||||||
public final String language;
|
public final String language;
|
||||||
|
@ -27,7 +24,4 @@ public class MessageContent {
|
||||||
public static MessageContent file(final String url) {
|
public static MessageContent file(final String url) {
|
||||||
return new MessageContent(null, PartType.FILE, null, url);
|
return new MessageContent(null, PartType.FILE, null, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final List<MessageContent> RETRACTION =
|
|
||||||
ImmutableList.of(new MessageContent(null, PartType.RETRACTION, null, null));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
|
|
||||||
public class MessageWithContentReactions {
|
public class MessageWithContentReactions {
|
||||||
|
|
||||||
|
@ -31,6 +32,8 @@ public class MessageWithContentReactions {
|
||||||
public Modification modification;
|
public Modification modification;
|
||||||
public long version;
|
public long version;
|
||||||
public Long inReplyToMessageEntityId;
|
public Long inReplyToMessageEntityId;
|
||||||
|
public Encryption encryption;
|
||||||
|
public IdentityKey identityKey;
|
||||||
|
|
||||||
@Relation(
|
@Relation(
|
||||||
entity = MessageEntity.class,
|
entity = MessageEntity.class,
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
package im.conversations.android.transformer;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import im.conversations.android.axolotl.AxolotlPayload;
|
||||||
|
import im.conversations.android.database.model.Encryption;
|
||||||
|
import im.conversations.android.database.model.MessageContent;
|
||||||
|
import im.conversations.android.database.model.PartType;
|
||||||
|
import im.conversations.android.xmpp.model.jabber.Body;
|
||||||
|
import im.conversations.android.xmpp.model.oob.OutOfBandData;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
|
|
||||||
|
public class MessageContentWrapper {
|
||||||
|
|
||||||
|
public static final MessageContentWrapper RETRACTION =
|
||||||
|
new MessageContentWrapper(
|
||||||
|
ImmutableList.of(new MessageContent(null, PartType.RETRACTION, null, null)),
|
||||||
|
Encryption.CLEARTEXT,
|
||||||
|
null);
|
||||||
|
|
||||||
|
public final List<MessageContent> contents;
|
||||||
|
public final Encryption encryption;
|
||||||
|
public final IdentityKey identityKey;
|
||||||
|
|
||||||
|
private MessageContentWrapper(
|
||||||
|
List<MessageContent> contents, Encryption encryption, IdentityKey identityKey) {
|
||||||
|
if (encryption == Encryption.OMEMO) {
|
||||||
|
Preconditions.checkArgument(
|
||||||
|
Objects.nonNull(identityKey),
|
||||||
|
"OMEMO encrypted content must provide an identity key");
|
||||||
|
}
|
||||||
|
this.contents = contents;
|
||||||
|
this.encryption = encryption;
|
||||||
|
this.identityKey = identityKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MessageContentWrapper parseCleartext(final MessageTransformation transformation) {
|
||||||
|
final Collection<Body> bodies = transformation.getExtensions(Body.class);
|
||||||
|
final Collection<OutOfBandData> outOfBandData =
|
||||||
|
transformation.getExtensions(OutOfBandData.class);
|
||||||
|
final ImmutableList.Builder<MessageContent> messageContentBuilder = ImmutableList.builder();
|
||||||
|
|
||||||
|
if (bodies.size() == 1 && outOfBandData.size() == 1) {
|
||||||
|
final String text = Iterables.getOnlyElement(bodies).getContent();
|
||||||
|
final String url = Iterables.getOnlyElement(outOfBandData).getURL();
|
||||||
|
if (!Strings.isNullOrEmpty(url) && url.equals(text)) {
|
||||||
|
return cleartext(ImmutableList.of(MessageContent.file(url)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO verify that body is not fallback
|
||||||
|
for (final Body body : bodies) {
|
||||||
|
final String text = body.getContent();
|
||||||
|
if (Strings.isNullOrEmpty(text)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
messageContentBuilder.add(MessageContent.text(text, body.getLang()));
|
||||||
|
}
|
||||||
|
for (final OutOfBandData data : outOfBandData) {
|
||||||
|
final String url = data.getURL();
|
||||||
|
if (Strings.isNullOrEmpty(url)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
messageContentBuilder.add(MessageContent.file(url));
|
||||||
|
}
|
||||||
|
return cleartext(messageContentBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MessageContentWrapper cleartext(final List<MessageContent> contents) {
|
||||||
|
return new MessageContentWrapper(contents, Encryption.CLEARTEXT, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MessageContentWrapper ofAxolotl(final AxolotlPayload payload) {
|
||||||
|
if (payload.hasPayload()) {
|
||||||
|
return new MessageContentWrapper(
|
||||||
|
ImmutableList.of(MessageContent.text(payload.payloadAsString(), null)),
|
||||||
|
Encryption.OMEMO,
|
||||||
|
payload.identityKey);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format("%s does not have payload", payload.getClass().getSimpleName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return this.contents.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +1,24 @@
|
||||||
package im.conversations.android.transformer;
|
package im.conversations.android.transformer;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import im.conversations.android.axolotl.AxolotlDecryptionException;
|
import im.conversations.android.axolotl.AxolotlDecryptionException;
|
||||||
import im.conversations.android.axolotl.AxolotlService;
|
import im.conversations.android.axolotl.AxolotlService;
|
||||||
import im.conversations.android.database.ConversationsDatabase;
|
import im.conversations.android.database.ConversationsDatabase;
|
||||||
import im.conversations.android.database.model.Account;
|
import im.conversations.android.database.model.Account;
|
||||||
import im.conversations.android.database.model.ChatIdentifier;
|
import im.conversations.android.database.model.ChatIdentifier;
|
||||||
import im.conversations.android.database.model.MessageContent;
|
|
||||||
import im.conversations.android.database.model.MessageIdentifier;
|
import im.conversations.android.database.model.MessageIdentifier;
|
||||||
import im.conversations.android.database.model.MessageState;
|
import im.conversations.android.database.model.MessageState;
|
||||||
import im.conversations.android.database.model.Modification;
|
import im.conversations.android.database.model.Modification;
|
||||||
import im.conversations.android.xmpp.model.DeliveryReceipt;
|
import im.conversations.android.xmpp.model.DeliveryReceipt;
|
||||||
import im.conversations.android.xmpp.model.axolotl.Encrypted;
|
import im.conversations.android.xmpp.model.axolotl.Encrypted;
|
||||||
import im.conversations.android.xmpp.model.correction.Replace;
|
import im.conversations.android.xmpp.model.correction.Replace;
|
||||||
import im.conversations.android.xmpp.model.jabber.Body;
|
|
||||||
import im.conversations.android.xmpp.model.markers.Displayed;
|
import im.conversations.android.xmpp.model.markers.Displayed;
|
||||||
import im.conversations.android.xmpp.model.muc.user.MultiUserChat;
|
import im.conversations.android.xmpp.model.muc.user.MultiUserChat;
|
||||||
import im.conversations.android.xmpp.model.oob.OutOfBandData;
|
|
||||||
import im.conversations.android.xmpp.model.reactions.Reactions;
|
import im.conversations.android.xmpp.model.reactions.Reactions;
|
||||||
import im.conversations.android.xmpp.model.reply.Reply;
|
import im.conversations.android.xmpp.model.reply.Reply;
|
||||||
import im.conversations.android.xmpp.model.retract.Retract;
|
import im.conversations.android.xmpp.model.retract.Retract;
|
||||||
import im.conversations.android.xmpp.model.stanza.Message;
|
import im.conversations.android.xmpp.model.stanza.Message;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -89,13 +81,12 @@ public class Transformer {
|
||||||
final Reactions reactions = transformation.getExtension(Reactions.class);
|
final Reactions reactions = transformation.getExtension(Reactions.class);
|
||||||
final Retract retract = transformation.getExtension(Retract.class);
|
final Retract retract = transformation.getExtension(Retract.class);
|
||||||
final Encrypted encrypted = transformation.getExtension(Encrypted.class);
|
final Encrypted encrypted = transformation.getExtension(Encrypted.class);
|
||||||
final List<MessageContent> contents;
|
final MessageContentWrapper contents;
|
||||||
if (encrypted != null) {
|
if (encrypted != null) {
|
||||||
try {
|
try {
|
||||||
final var payload = axolotlService.decrypt(transformation.from, encrypted);
|
final var payload = axolotlService.decrypt(transformation.from, encrypted);
|
||||||
if (payload.hasPayload()) {
|
if (payload.hasPayload()) {
|
||||||
contents =
|
contents = MessageContentWrapper.ofAxolotl(payload);
|
||||||
ImmutableList.of(MessageContent.text(payload.payloadAsString(), null));
|
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +98,7 @@ public class Transformer {
|
||||||
} else {
|
} else {
|
||||||
// TODO we need to remove fallbacks for reactions, retractions and potentially other
|
// TODO we need to remove fallbacks for reactions, retractions and potentially other
|
||||||
// things
|
// things
|
||||||
contents = parseContent(transformation);
|
contents = MessageContentWrapper.parseCleartext(transformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean identifiableSender =
|
final boolean identifiableSender =
|
||||||
|
@ -131,7 +122,8 @@ public class Transformer {
|
||||||
.getOrCreateVersion(
|
.getOrCreateVersion(
|
||||||
chat, transformation, retract.getId(), Modification.RETRACTION);
|
chat, transformation, retract.getId(), Modification.RETRACTION);
|
||||||
database.messageDao()
|
database.messageDao()
|
||||||
.insertMessageContent(messageIdentifier.version, MessageContent.RETRACTION);
|
.insertMessageContent(
|
||||||
|
messageIdentifier.version, MessageContentWrapper.RETRACTION);
|
||||||
return true;
|
return true;
|
||||||
} else if (contents.isEmpty()) {
|
} else if (contents.isEmpty()) {
|
||||||
LOGGER.info("Received message from {} w/o contents", transformation.from);
|
LOGGER.info("Received message from {} w/o contents", transformation.from);
|
||||||
|
@ -173,42 +165,6 @@ public class Transformer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<MessageContent> parseContent(final MessageTransformation transformation) {
|
|
||||||
final var encrypted = transformation.getExtension(Encrypted.class);
|
|
||||||
final var encryptedWithPayload = encrypted != null && encrypted.hasPayload();
|
|
||||||
final Collection<Body> bodies = transformation.getExtensions(Body.class);
|
|
||||||
final Collection<OutOfBandData> outOfBandData =
|
|
||||||
transformation.getExtensions(OutOfBandData.class);
|
|
||||||
final ImmutableList.Builder<MessageContent> messageContentBuilder = ImmutableList.builder();
|
|
||||||
|
|
||||||
// TODO decrypt
|
|
||||||
|
|
||||||
if (bodies.size() == 1 && outOfBandData.size() == 1) {
|
|
||||||
final String text = Iterables.getOnlyElement(bodies).getContent();
|
|
||||||
final String url = Iterables.getOnlyElement(outOfBandData).getURL();
|
|
||||||
if (!Strings.isNullOrEmpty(url) && url.equals(text)) {
|
|
||||||
return ImmutableList.of(MessageContent.file(url));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO verify that body is not fallback
|
|
||||||
for (final Body body : bodies) {
|
|
||||||
final String text = body.getContent();
|
|
||||||
if (Strings.isNullOrEmpty(text)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
messageContentBuilder.add(MessageContent.text(text, body.getLang()));
|
|
||||||
}
|
|
||||||
for (final OutOfBandData data : outOfBandData) {
|
|
||||||
final String url = data.getURL();
|
|
||||||
if (Strings.isNullOrEmpty(url)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
messageContentBuilder.add(MessageContent.file(url));
|
|
||||||
}
|
|
||||||
return messageContentBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void transformMessageState(
|
private void transformMessageState(
|
||||||
final ChatIdentifier chat, final MessageTransformation transformation) {
|
final ChatIdentifier chat, final MessageTransformation transformation) {
|
||||||
final var displayed = transformation.getExtension(Displayed.class);
|
final var displayed = transformation.getExtension(Displayed.class);
|
||||||
|
|
Loading…
Reference in a new issue