create transformation for call log

This commit is contained in:
Daniel Gultsch 2023-02-23 15:58:13 +01:00
parent 44ac7190a9
commit 63bfbfb40a
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
22 changed files with 294 additions and 193 deletions

View file

@ -11,7 +11,7 @@ import im.conversations.android.database.entity.AccountEntity;
import im.conversations.android.database.model.MessageEmbedded;
import im.conversations.android.database.model.Modification;
import im.conversations.android.database.model.PartType;
import im.conversations.android.transformer.Transformation;
import im.conversations.android.transformer.MessageTransformation;
import im.conversations.android.transformer.Transformer;
import im.conversations.android.xmpp.model.correction.Replace;
import im.conversations.android.xmpp.model.jabber.Body;
@ -33,7 +33,7 @@ import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
@RunWith(AndroidJUnit4.class)
public class TransformationTest {
public class MessageTransformationTest {
private static final BareJid ACCOUNT = JidCreate.bareFromOrThrowUnchecked("user@example.com");
private static final BareJid REMOTE = JidCreate.bareFromOrThrowUnchecked("juliet@example.com");
@ -68,7 +68,7 @@ public class TransformationTest {
final var reaction = reactions.addExtension(new Reaction());
reaction.setContent("Y");
this.transformer.transform(
Transformation.of(reactionMessage, Instant.now(), REMOTE, "stanza-b", null));
MessageTransformation.of(reactionMessage, Instant.now(), REMOTE, "stanza-b", null));
final var originalMessage = new Message();
originalMessage.setId("1");
originalMessage.setTo(REMOTE);
@ -76,7 +76,7 @@ public class TransformationTest {
final var body = originalMessage.addExtension(new Body());
body.setContent(GREETING);
this.transformer.transform(
Transformation.of(originalMessage, Instant.now(), REMOTE, "stanza-a", null));
MessageTransformation.of(originalMessage, Instant.now(), REMOTE, "stanza-a", null));
final var messages = database.messageDao().getMessages(1L);
Assert.assertEquals(1, messages.size());
@ -95,19 +95,21 @@ public class TransformationTest {
message.addExtension(new Body("Please give me a thumbs up"));
message.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a")));
this.transformer.transform(
Transformation.of(message, Instant.now(), REMOTE, "stanza-a", "id-user-a"));
MessageTransformation.of(message, Instant.now(), REMOTE, "stanza-a", "id-user-a"));
final var reactionA = new Message(Message.Type.GROUPCHAT);
reactionA.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b")));
reactionA.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(reactionA, Instant.now(), REMOTE, "stanza-b", "id-user-b"));
MessageTransformation.of(
reactionA, Instant.now(), REMOTE, "stanza-b", "id-user-b"));
final var reactionB = new Message(Message.Type.GROUPCHAT);
reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-c")));
reactionB.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(reactionB, Instant.now(), REMOTE, "stanza-c", "id-user-c"));
MessageTransformation.of(
reactionB, Instant.now(), REMOTE, "stanza-c", "id-user-c"));
final var reactionC = new Message(Message.Type.GROUPCHAT);
reactionC.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-d")));
@ -115,7 +117,8 @@ public class TransformationTest {
reactions.addExtension(new Reaction("Y"));
reactions.addExtension(new Reaction("Z"));
this.transformer.transform(
Transformation.of(reactionC, Instant.now(), REMOTE, "stanza-d", "id-user-d"));
MessageTransformation.of(
reactionC, Instant.now(), REMOTE, "stanza-d", "id-user-d"));
final var messages = database.messageDao().getMessages(1L);
Assert.assertEquals(1, messages.size());
@ -141,7 +144,8 @@ public class TransformationTest {
messageCorrection.addExtension(new Replace()).setId("1");
this.transformer.transform(
Transformation.of(messageCorrection, Instant.now(), REMOTE, "stanza-a", null));
MessageTransformation.of(
messageCorrection, Instant.now(), REMOTE, "stanza-a", null));
// the correction should not show up as a message
Assert.assertEquals(0, database.messageDao().getMessages(1L).size());
@ -153,7 +157,7 @@ public class TransformationTest {
messageWithTypo.addExtension(new Body()).setContent("Hii example!");
this.transformer.transform(
Transformation.of(messageWithTypo, Instant.now(), REMOTE, "stanza-b", null));
MessageTransformation.of(messageWithTypo, Instant.now(), REMOTE, "stanza-b", null));
final var messages = database.messageDao().getMessages(1L);
@ -175,7 +179,7 @@ public class TransformationTest {
messageWithTypo.addExtension(new Body()).setContent("Hii example!");
this.transformer.transform(
Transformation.of(messageWithTypo, Instant.now(), REMOTE, "stanza-a", null));
MessageTransformation.of(messageWithTypo, Instant.now(), REMOTE, "stanza-a", null));
Assert.assertEquals(1, database.messageDao().getMessages(1L).size());
@ -187,7 +191,8 @@ public class TransformationTest {
messageCorrection.addExtension(new Replace()).setId("1");
this.transformer.transform(
Transformation.of(messageCorrection, Instant.now(), REMOTE, "stanza-b", null));
MessageTransformation.of(
messageCorrection, Instant.now(), REMOTE, "stanza-b", null));
final var messages = database.messageDao().getMessages(1L);
@ -206,19 +211,21 @@ public class TransformationTest {
message.addExtension(new Body("Please give me a thumbs up"));
message.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a")));
this.transformer.transform(
Transformation.of(message, Instant.now(), REMOTE, "stanza-a", "id-user-a"));
MessageTransformation.of(message, Instant.now(), REMOTE, "stanza-a", "id-user-a"));
final var reactionA = new Message(Message.Type.GROUPCHAT);
reactionA.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b")));
reactionA.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("N"));
this.transformer.transform(
Transformation.of(reactionA, Instant.now(), REMOTE, "stanza-b", "id-user-b"));
MessageTransformation.of(
reactionA, Instant.now(), REMOTE, "stanza-b", "id-user-b"));
final var reactionB = new Message(Message.Type.GROUPCHAT);
reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b")));
reactionB.addExtension(Reactions.to("stanza-a")).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(reactionB, Instant.now(), REMOTE, "stanza-c", "id-user-b"));
MessageTransformation.of(
reactionB, Instant.now(), REMOTE, "stanza-c", "id-user-b"));
final var messages = database.messageDao().getMessages(1L);
Assert.assertEquals(1, messages.size());
@ -240,7 +247,7 @@ public class TransformationTest {
m1.addExtension(new Replace()).setId(ogMessageId);
m1.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a")));
this.transformer.transform(
Transformation.of(
MessageTransformation.of(
m1,
Instant.ofEpochMilli(2000),
REMOTE,
@ -254,7 +261,7 @@ public class TransformationTest {
m2.addExtension(new Replace()).setId(ogMessageId);
m2.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a")));
this.transformer.transform(
Transformation.of(
MessageTransformation.of(
m2,
Instant.ofEpochMilli(3000),
REMOTE,
@ -266,7 +273,7 @@ public class TransformationTest {
reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b")));
reactionB.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(
MessageTransformation.of(
reactionB, Instant.now(), REMOTE, "irrelevant-stanza-id3", "id-user-b"));
// the original message
@ -275,7 +282,8 @@ public class TransformationTest {
m4.addExtension(new Body("Please give me thumbs up"));
m4.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a")));
this.transformer.transform(
Transformation.of(m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a"));
MessageTransformation.of(
m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a"));
final var messages = database.messageDao().getMessages(1L);
Assert.assertEquals(1, messages.size());
@ -298,7 +306,7 @@ public class TransformationTest {
reactionA.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b")));
reactionA.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(
MessageTransformation.of(
reactionA, Instant.now(), REMOTE, "irrelevant-stanza-id1", "id-user-b"));
// second reaction
@ -306,7 +314,7 @@ public class TransformationTest {
reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-c")));
reactionB.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(
MessageTransformation.of(
reactionB, Instant.now(), REMOTE, "irrelevant-stanza-id2", "id-user-c"));
// a correction
@ -315,7 +323,7 @@ public class TransformationTest {
m1.addExtension(new Replace()).setId(ogMessageId);
m1.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a")));
this.transformer.transform(
Transformation.of(
MessageTransformation.of(
m1,
Instant.ofEpochMilli(2000),
REMOTE,
@ -328,7 +336,8 @@ public class TransformationTest {
m4.addExtension(new Body("Please give me thumbs up (Typo)"));
m4.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a")));
this.transformer.transform(
Transformation.of(m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a"));
MessageTransformation.of(
m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a"));
final var messages = database.messageDao().getMessages(1L);
Assert.assertEquals(1, messages.size());
@ -353,14 +362,15 @@ public class TransformationTest {
m4.addExtension(new Body("Please give me a thumbs up"));
m4.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-a")));
this.transformer.transform(
Transformation.of(m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a"));
MessageTransformation.of(
m4, Instant.ofEpochMilli(1000), REMOTE, ogStanzaId, "id-user-a"));
// first reaction
final var reactionA = new Message(Message.Type.GROUPCHAT);
reactionA.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-b")));
reactionA.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(
MessageTransformation.of(
reactionA, Instant.now(), REMOTE, "irrelevant-stanza-id1", "id-user-b"));
// second reaction
@ -368,7 +378,7 @@ public class TransformationTest {
reactionB.setFrom(JidCreate.fullFrom(group, Resourcepart.from("user-c")));
reactionB.addExtension(Reactions.to(ogStanzaId)).addExtension(new Reaction("Y"));
this.transformer.transform(
Transformation.of(
MessageTransformation.of(
reactionB, Instant.now(), REMOTE, "irrelevant-stanza-id2", "id-user-c"));
final var messages = database.messageDao().getMessages(1L);
@ -390,7 +400,8 @@ public class TransformationTest {
m1.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit")));
m1.addExtension(new Body("Hi. How are you?"));
this.transformer.transform(Transformation.of(m1, Instant.now(), REMOTE, "stanza-a", null));
this.transformer.transform(
MessageTransformation.of(m1, Instant.now(), REMOTE, "stanza-a", null));
final var m2 = new Message();
m2.setId("2");
@ -401,7 +412,8 @@ public class TransformationTest {
reply.setId("1");
reply.setTo(REMOTE);
this.transformer.transform(Transformation.of(m2, Instant.now(), REMOTE, "stanza-b", null));
this.transformer.transform(
MessageTransformation.of(m2, Instant.now(), REMOTE, "stanza-b", null));
final var messages = database.messageDao().getMessages(1L);
Assert.assertEquals(2, messages.size());
@ -423,14 +435,14 @@ public class TransformationTest {
m1.setFrom(JidCreate.fullFrom(ACCOUNT, Resourcepart.from("junit")));
m1.addExtension(new Body("Hi. How are you?"));
this.transformer.transform(Transformation.of(m1, Instant.now(), REMOTE, null, null));
this.transformer.transform(MessageTransformation.of(m1, Instant.now(), REMOTE, null, null));
final var m2 = new Message();
m2.setTo(JidCreate.fullFrom(ACCOUNT, Resourcepart.from("junit")));
m2.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit")));
m2.addExtension(new Received()).setId("1");
this.transformer.transform(Transformation.of(m2, Instant.now(), REMOTE, null, null));
this.transformer.transform(MessageTransformation.of(m2, Instant.now(), REMOTE, null, null));
final var messages = database.messageDao().getMessages(1L);
final var message = Iterables.getOnlyElement(messages);
@ -446,14 +458,14 @@ public class TransformationTest {
m1.setId("m1");
m1.addExtension(new Body("It is raining outside"));
this.transformer.transform(Transformation.of(m1, Instant.now(), REMOTE, null, null));
this.transformer.transform(MessageTransformation.of(m1, Instant.now(), REMOTE, null, null));
final var m2 = new Message();
m2.setTo(ACCOUNT);
m2.setFrom(JidCreate.fullFrom(REMOTE, Resourcepart.from("junit")));
m2.addExtension(new Retract()).setId("m1");
this.transformer.transform(Transformation.of(m2, Instant.now(), REMOTE, null, null));
this.transformer.transform(MessageTransformation.of(m2, Instant.now(), REMOTE, null, null));
final var messages = database.messageDao().getMessages(1L);
final var message = Iterables.getOnlyElement(messages);

View file

@ -31,7 +31,7 @@ import im.conversations.android.axolotl.AxolotlEncryptionException;
import im.conversations.android.axolotl.AxolotlService;
import im.conversations.android.dns.IP;
import im.conversations.android.notification.RtpSessionNotification;
import im.conversations.android.transformer.CallLogEntry;
import im.conversations.android.transformer.CallLogTransformation;
import im.conversations.android.util.BooleanFutures;
import im.conversations.android.xml.Element;
import im.conversations.android.xml.Namespace;
@ -179,7 +179,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
private final Queue<PeerConnection.PeerConnectionState> stateHistory = new LinkedList<>();
private final RtpSessionNotification rtpSessionNotification;
private ScheduledFuture<?> ringingTimeoutFuture;
private CallLogEntry message = null;
private final CallLogTransformation.Builder callLogTransformationBuilder =
new CallLogTransformation.Builder();
private final ListenableFuture<Boolean> remoteHasVideoFeature;
public JingleRtpConnection(
@ -1346,9 +1347,10 @@ public class JingleRtpConnection extends AbstractJingleConnection
private void acceptedOnOtherDevice(final String serverMsgId) {
if (serverMsgId != null) {
this.message.setServerMsgId(serverMsgId);
this.callLogTransformationBuilder.setServerMsgId(serverMsgId);
}
this.message.setCarbon(true); // indicate that call was accepted on other device
this.callLogTransformationBuilder.setCarbon(
true); // indicate that call was accepted on other device
this.writeLogMessageSuccess(0);
this.rtpSessionNotification.cancelIncomingCallNotification();
this.finish();
@ -1386,9 +1388,10 @@ public class JingleRtpConnection extends AbstractJingleConnection
this.rtpSessionNotification.cancelIncomingCallNotification();
this.finish();
if (serverMsgId != null) {
this.message.setServerMsgId(serverMsgId);
this.callLogTransformationBuilder.setServerMsgId(serverMsgId);
}
this.message.setCarbon(true); // indicate that call was rejected on other device
this.callLogTransformationBuilder.setCarbon(
true); // indicate that call was rejected on other device
writeLogMessageMissed();
} else {
LOGGER.debug("not able to transition into REJECTED because already in " + this.state);
@ -1445,7 +1448,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
this.proposedMedia = Sets.newHashSet(media);
})) {
if (serverMsgId != null) {
this.message.setServerMsgId(serverMsgId);
this.callLogTransformationBuilder.setServerMsgId(serverMsgId);
}
startRinging();
} else {
@ -1472,15 +1475,15 @@ public class JingleRtpConnection extends AbstractJingleConnection
LOGGER.debug(connection.getAccount().address + ": timeout reached for ringing");
switch (this.state) {
case PROPOSED:
message.markUnread();
callLogTransformationBuilder.markUnread();
rejectCallFromProposed();
break;
case SESSION_INITIALIZED:
message.markUnread();
callLogTransformationBuilder.markUnread();
rejectCallFromSessionInitiate();
break;
}
rtpSessionNotification.pushMissedCallNow(message);
rtpSessionNotification.pushMissedCallNow(callLogTransformationBuilder.build());
}
private void cancelRingingTimeout() {
@ -1499,7 +1502,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
if (isInitiator()) {
if (transition(State.PROCEED)) {
if (serverMsgId != null) {
this.message.setServerMsgId(serverMsgId);
this.callLogTransformationBuilder.setServerMsgId(serverMsgId);
}
final Integer remoteDeviceId = proceed.getDeviceId();
if (isOmemoEnabled()) {
@ -1549,7 +1552,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
this.state == State.PROCEED ? State.RETRACTED_RACED : State.RETRACTED;
if (transition(target)) {
rtpSessionNotification.cancelIncomingCallNotification();
rtpSessionNotification.pushMissedCallNow(message);
rtpSessionNotification.pushMissedCallNow(callLogTransformationBuilder.build());
LOGGER.debug(
connection.getAccount().address
+ ": session with "
@ -1558,10 +1561,10 @@ public class JingleRtpConnection extends AbstractJingleConnection
+ serverMsgId
+ ")");
if (serverMsgId != null) {
this.message.setServerMsgId(serverMsgId);
this.callLogTransformationBuilder.setServerMsgId(serverMsgId);
}
if (target == State.RETRACTED) {
this.message.markUnread();
this.callLogTransformationBuilder.markUnread();
}
writeLogMessageMissed();
finish();
@ -2615,7 +2618,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
}
private void writeLogMessageSuccess(final long duration) {
this.message.setDuration(duration);
this.callLogTransformationBuilder.setDuration(duration);
// this.message.setBody(new RtpSessionStatus(true, duration).toString());
this.writeMessage();
}

View file

@ -21,7 +21,7 @@ import im.conversations.android.database.model.MessageIdentifier;
import im.conversations.android.database.model.MessageState;
import im.conversations.android.database.model.MessageWithContentReactions;
import im.conversations.android.database.model.Modification;
import im.conversations.android.transformer.Transformation;
import im.conversations.android.transformer.MessageTransformation;
import im.conversations.android.xmpp.model.reactions.Reactions;
import im.conversations.android.xmpp.model.stanza.Message;
import java.util.Collection;
@ -72,7 +72,7 @@ public abstract class MessageDao {
// will be upgraded to an original message (missing information filled in)
@Transaction
public MessageIdentifier getOrCreateMessage(
ChatIdentifier chatIdentifier, final Transformation transformation) {
ChatIdentifier chatIdentifier, final MessageTransformation transformation) {
final MessageIdentifier messageIdentifier =
get(
chatIdentifier.id,
@ -140,7 +140,7 @@ public abstract class MessageDao {
private void mergeMessageStubs(
ChatIdentifier chatIdentifier,
MessageIdentifier messageIdentifier,
final Transformation transformation) {
final MessageTransformation transformation) {
final Long stub;
if (messageIdentifier.messageId == null && transformation.messageId != null) {
stub = getMessageStubByMessageId(chatIdentifier.id, transformation.messageId);
@ -199,7 +199,7 @@ public abstract class MessageDao {
public MessageIdentifier getOrCreateVersion(
ChatIdentifier chat,
Transformation transformation,
MessageTransformation transformation,
final String messageId,
final Modification modification) {
Preconditions.checkArgument(
@ -366,7 +366,7 @@ public abstract class MessageDao {
protected abstract void insertReactions(Collection<MessageReactionEntity> reactionEntities);
public void insertReactions(
ChatIdentifier chat, Reactions reactions, Transformation transformation) {
ChatIdentifier chat, Reactions reactions, MessageTransformation transformation) {
final Message.Type messageType = transformation.type;
final MessageIdentifier messageIdentifier =
getOrCreateStub(chat, messageType, reactions.getId());

View file

@ -6,7 +6,7 @@ import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import im.conversations.android.transformer.Transformation;
import im.conversations.android.transformer.MessageTransformation;
import java.time.Instant;
import java.util.Objects;
import org.jxmpp.jid.BareJid;
@ -69,7 +69,7 @@ public class MessageEntity {
public String inReplyToStanzaId;
@Nullable public Long inReplyToMessageEntityId;
public static MessageEntity of(final long chatId, final Transformation transformation) {
public static MessageEntity of(final long chatId, final MessageTransformation transformation) {
final var entity = new MessageEntity();
entity.chatId = chatId;
entity.receivedAt = transformation.receivedAt;
@ -87,7 +87,7 @@ public class MessageEntity {
}
public static MessageEntity stub(
final long chatId, String messageId, Transformation transformation) {
final long chatId, String messageId, MessageTransformation transformation) {
final var entity = new MessageEntity();
entity.chatId = chatId;
entity.fromBare = transformation.fromBare();

View file

@ -5,7 +5,7 @@ import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import im.conversations.android.transformer.Transformation;
import im.conversations.android.transformer.MessageTransformation;
import java.time.Instant;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.parts.Resourcepart;
@ -37,7 +37,9 @@ public class MessageReactionEntity {
public String reaction;
public static MessageReactionEntity of(
long messageEntityId, final String reaction, final Transformation transformation) {
long messageEntityId,
final String reaction,
final MessageTransformation transformation) {
final var entity = new MessageReactionEntity();
entity.messageEntityId = messageEntityId;
entity.reaction = reaction;

View file

@ -7,7 +7,7 @@ import androidx.room.Index;
import androidx.room.PrimaryKey;
import com.google.common.base.Preconditions;
import im.conversations.android.database.model.Modification;
import im.conversations.android.transformer.Transformation;
import im.conversations.android.transformer.MessageTransformation;
import im.conversations.android.xmpp.model.stanza.Message;
import java.time.Instant;
import org.jxmpp.jid.BareJid;
@ -45,7 +45,7 @@ public class MessageVersionEntity {
public static MessageVersionEntity of(
long messageEntityId,
final Modification modification,
final Transformation transformation) {
final MessageTransformation transformation) {
if (transformation.type == Message.Type.GROUPCHAT
&& modification != Modification.ORIGINAL) {
Preconditions.checkState(

View file

@ -1,7 +1,7 @@
package im.conversations.android.database.model;
import com.google.common.base.Preconditions;
import im.conversations.android.transformer.Transformation;
import im.conversations.android.transformer.MessageTransformation;
import im.conversations.android.xmpp.model.error.Condition;
import im.conversations.android.xmpp.model.error.Error;
import im.conversations.android.xmpp.model.error.Text;
@ -34,7 +34,7 @@ public class MessageState {
this.errorText = errorText;
}
public static MessageState error(final Transformation transformation) {
public static MessageState error(final MessageTransformation transformation) {
Preconditions.checkArgument(transformation.type == Message.Type.ERROR);
final Error error = transformation.getExtension(Error.class);
final Condition condition = error == null ? null : error.getCondition();
@ -47,7 +47,7 @@ public class MessageState {
text == null ? null : text.getContent());
}
public static MessageState delivered(final Transformation transformation) {
public static MessageState delivered(final MessageTransformation transformation) {
return new MessageState(
transformation.fromBare(),
transformation.fromResource(),
@ -56,7 +56,7 @@ public class MessageState {
null);
}
public static MessageState displayed(final Transformation transformation) {
public static MessageState displayed(final MessageTransformation transformation) {
return new MessageState(
transformation.fromBare(),
transformation.fromResource(),

View file

@ -27,7 +27,7 @@ import eu.siacs.conversations.xmpp.jingle.Media;
import im.conversations.android.R;
import im.conversations.android.database.model.Account;
import im.conversations.android.service.RtpSessionService;
import im.conversations.android.transformer.CallLogEntry;
import im.conversations.android.transformer.CallLogTransformation;
import im.conversations.android.ui.activity.RtpSessionActivity;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
@ -271,7 +271,7 @@ public class RtpSessionNotification extends AbstractNotification {
mBuilder.setColor(ContextCompat.getColor(context, R.color.seed));
}
public void pushMissedCallNow(CallLogEntry message) {}
public void pushMissedCallNow(CallLogTransformation message) {}
private class VibrationRunnable implements Runnable {

View file

@ -1,11 +0,0 @@
package im.conversations.android.transformer;
public class CallLogEntry {
public void setServerMsgId(String serverMsgId) {}
public void setCarbon(boolean b) {}
public void markUnread() {}
public void setDuration(long duration) {}
}

View file

@ -0,0 +1,38 @@
package im.conversations.android.transformer;
import im.conversations.android.xmpp.model.stanza.Message;
import java.time.Duration;
import java.time.Instant;
import org.jxmpp.jid.Jid;
public class CallLogTransformation extends Transformation {
public final Duration duration;
private CallLogTransformation(
final Instant receivedAt,
final Jid to,
final Jid from,
final Jid remote,
final String messageId,
final String stanzaId,
final Duration duration) {
super(receivedAt, to, from, remote, Message.Type.NORMAL, messageId, stanzaId, null);
this.duration = duration;
}
public static class Builder {
public void setServerMsgId(String serverMsgId) {}
public void setCarbon(boolean b) {}
public void markUnread() {}
public void setDuration(long duration) {}
public CallLogTransformation build() {
return new CallLogTransformation(null, null, null, null, null, null, null);
}
}
}

View file

@ -0,0 +1,128 @@
package im.conversations.android.transformer;
import androidx.annotation.NonNull;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import im.conversations.android.xmpp.model.DeliveryReceipt;
import im.conversations.android.xmpp.model.DeliveryReceiptRequest;
import im.conversations.android.xmpp.model.Extension;
import im.conversations.android.xmpp.model.axolotl.Encrypted;
import im.conversations.android.xmpp.model.correction.Replace;
import im.conversations.android.xmpp.model.error.Error;
import im.conversations.android.xmpp.model.jabber.Body;
import im.conversations.android.xmpp.model.jabber.Thread;
import im.conversations.android.xmpp.model.markers.Displayed;
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.reply.Reply;
import im.conversations.android.xmpp.model.retract.Retract;
import im.conversations.android.xmpp.model.stanza.Message;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jxmpp.jid.Jid;
public class MessageTransformation extends Transformation {
private static final List<Class<? extends Extension>> EXTENSION_FOR_TRANSFORMATION =
Arrays.asList(
Body.class,
Thread.class,
Encrypted.class,
OutOfBandData.class,
DeliveryReceipt.class,
MultiUserChat.class,
Displayed.class,
Replace.class,
Reactions.class,
Reply.class,
Retract.class);
private final List<Extension> extensions;
public final Collection<DeliveryReceiptRequest> deliveryReceiptRequests;
private MessageTransformation(
final Instant receivedAt,
final Jid to,
final Jid from,
final Jid remote,
final Message.Type type,
final String messageId,
final String stanzaId,
final String occupantId,
final List<Extension> extensions,
final Collection<DeliveryReceiptRequest> deliveryReceiptRequests) {
super(receivedAt, to, from, remote, type, messageId, stanzaId, occupantId);
this.extensions = extensions;
this.deliveryReceiptRequests = deliveryReceiptRequests;
}
public boolean isAnythingToTransform() {
return this.extensions.size() > 0;
}
@Override
public Instant sentAt() {
// TODO get Delay that matches sender; return receivedAt if not found
return receivedAt;
}
public <E extends Extension> E getExtension(final Class<E> clazz) {
checkArgument(clazz);
final var extension = Iterables.find(this.extensions, clazz::isInstance, null);
return extension == null ? null : clazz.cast(extension);
}
private void checkArgument(final Class<? extends Extension> clazz) {
if (EXTENSION_FOR_TRANSFORMATION.contains(clazz) || clazz == Error.class) {
return;
}
throw new IllegalArgumentException(
String.format("%s has not been registered for transformation", clazz.getName()));
}
public <E extends Extension> Collection<E> getExtensions(final Class<E> clazz) {
checkArgument(clazz);
return Collections2.transform(
Collections2.filter(this.extensions, clazz::isInstance), clazz::cast);
}
public static MessageTransformation of(
@NonNull final Message message,
@NonNull final Instant receivedAt,
@NonNull final Jid remote,
final String stanzaId,
final String occupantId) {
final var to = message.getTo();
final var from = message.getFrom();
final var type = message.getType();
final var messageId = message.getId();
final ImmutableList.Builder<Extension> extensionListBuilder = new ImmutableList.Builder<>();
final Collection<DeliveryReceiptRequest> requests;
if (type == Message.Type.ERROR) {
extensionListBuilder.add(message.getError());
requests = Collections.emptyList();
} else {
for (final Class<? extends Extension> clazz : EXTENSION_FOR_TRANSFORMATION) {
extensionListBuilder.addAll(message.getExtensions(clazz));
}
requests = message.getExtensions(DeliveryReceiptRequest.class);
}
return new MessageTransformation(
receivedAt,
to,
from,
remote,
type,
messageId,
stanzaId,
occupantId,
extensionListBuilder.build(),
requests);
}
}

View file

@ -1,48 +1,12 @@
package im.conversations.android.transformer;
import androidx.annotation.NonNull;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import im.conversations.android.xmpp.model.DeliveryReceipt;
import im.conversations.android.xmpp.model.DeliveryReceiptRequest;
import im.conversations.android.xmpp.model.Extension;
import im.conversations.android.xmpp.model.axolotl.Encrypted;
import im.conversations.android.xmpp.model.correction.Replace;
import im.conversations.android.xmpp.model.error.Error;
import im.conversations.android.xmpp.model.jabber.Body;
import im.conversations.android.xmpp.model.jabber.Thread;
import im.conversations.android.xmpp.model.markers.Displayed;
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.reply.Reply;
import im.conversations.android.xmpp.model.retract.Retract;
import im.conversations.android.xmpp.model.stanza.Message;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.parts.Resourcepart;
public class Transformation {
private static final List<Class<? extends Extension>> EXTENSION_FOR_TRANSFORMATION =
Arrays.asList(
Body.class,
Thread.class,
Encrypted.class,
OutOfBandData.class,
DeliveryReceipt.class,
MultiUserChat.class,
Displayed.class,
Replace.class,
Reactions.class,
Reply.class,
Retract.class);
abstract class Transformation {
public final Instant receivedAt;
public final Jid to;
@ -54,11 +18,7 @@ public class Transformation {
public final String occupantId;
private final List<Extension> extensions;
public final Collection<DeliveryReceiptRequest> deliveryReceiptRequests;
private Transformation(
public Transformation(
final Instant receivedAt,
final Jid to,
final Jid from,
@ -66,9 +26,7 @@ public class Transformation {
final Message.Type type,
final String messageId,
final String stanzaId,
final String occupantId,
final List<Extension> extensions,
final Collection<DeliveryReceiptRequest> deliveryReceiptRequests) {
final String occupantId) {
this.receivedAt = receivedAt;
this.to = to;
this.from = from;
@ -77,12 +35,6 @@ public class Transformation {
this.messageId = messageId;
this.stanzaId = stanzaId;
this.occupantId = occupantId;
this.extensions = extensions;
this.deliveryReceiptRequests = deliveryReceiptRequests;
}
public boolean isAnythingToTransform() {
return this.extensions.size() > 0;
}
public BareJid fromBare() {
@ -110,58 +62,4 @@ public class Transformation {
// TODO handle case for self addressed (to == from)
return remote.asBareJid().equals(toBare());
}
public <E extends Extension> E getExtension(final Class<E> clazz) {
checkArgument(clazz);
final var extension = Iterables.find(this.extensions, clazz::isInstance, null);
return extension == null ? null : clazz.cast(extension);
}
private void checkArgument(final Class<? extends Extension> clazz) {
if (EXTENSION_FOR_TRANSFORMATION.contains(clazz) || clazz == Error.class) {
return;
}
throw new IllegalArgumentException(
String.format("%s has not been registered for transformation", clazz.getName()));
}
public <E extends Extension> Collection<E> getExtensions(final Class<E> clazz) {
checkArgument(clazz);
return Collections2.transform(
Collections2.filter(this.extensions, clazz::isInstance), clazz::cast);
}
public static Transformation of(
@NonNull final Message message,
@NonNull final Instant receivedAt,
@NonNull final Jid remote,
final String stanzaId,
final String occupantId) {
final var to = message.getTo();
final var from = message.getFrom();
final var type = message.getType();
final var messageId = message.getId();
final ImmutableList.Builder<Extension> extensionListBuilder = new ImmutableList.Builder<>();
final Collection<DeliveryReceiptRequest> requests;
if (type == Message.Type.ERROR) {
extensionListBuilder.add(message.getError());
requests = Collections.emptyList();
} else {
for (final Class<? extends Extension> clazz : EXTENSION_FOR_TRANSFORMATION) {
extensionListBuilder.addAll(message.getExtensions(clazz));
}
requests = message.getExtensions(DeliveryReceiptRequest.class);
}
return new Transformation(
receivedAt,
to,
from,
remote,
type,
messageId,
stanzaId,
occupantId,
extensionListBuilder.build(),
requests);
}
}

View file

@ -16,11 +16,11 @@ public class TransformationFactory extends XmppConnection.Delegate {
super(context, connection);
}
public Transformation create(final Message message, final String stanzaId) {
public MessageTransformation create(final Message message, final String stanzaId) {
return create(message, stanzaId, Instant.now());
}
public Transformation create(
public MessageTransformation create(
final Message message, final String stanzaId, final Instant receivedAt) {
final var boundAddress = connection.getBoundAddress().asBareJid();
final var from = message.getFrom();
@ -44,6 +44,6 @@ public class TransformationFactory extends XmppConnection.Delegate {
} else {
occupantId = null;
}
return Transformation.of(message, receivedAt, remote, stanzaId, occupantId);
return MessageTransformation.of(message, receivedAt, remote, stanzaId, occupantId);
}
}

View file

@ -42,7 +42,7 @@ public class Transformer {
this.account = account;
}
public boolean transform(final Transformation transformation) {
public boolean transform(final MessageTransformation transformation) {
return database.runInTransaction(() -> transform(database, transformation));
}
@ -53,7 +53,7 @@ public class Transformer {
* updated a status somewhere
*/
private boolean transform(
final ConversationsDatabase database, final Transformation transformation) {
final ConversationsDatabase database, final MessageTransformation transformation) {
final var remote = transformation.remote;
final var messageType = transformation.type;
final var muc = transformation.getExtension(MultiUserChat.class);
@ -141,7 +141,7 @@ public class Transformer {
return true;
}
protected List<MessageContent> parseContent(final Transformation transformation) {
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);
@ -178,7 +178,7 @@ public class Transformer {
}
private void transformMessageState(
final ChatIdentifier chat, final Transformation transformation) {
final ChatIdentifier chat, final MessageTransformation transformation) {
final var displayed = transformation.getExtension(Displayed.class);
if (displayed != null) {
if (transformation.outgoing()) {

View file

@ -66,8 +66,8 @@ public class DiscoManager extends AbstractManager {
Namespace.JINGLE_FEATURE_AUDIO,
Namespace.JINGLE_FEATURE_VIDEO,
Namespace.JINGLE_APPS_RTP,
Namespace.JINGLE_APPS_DTLS /*,
Namespace.JINGLE_MESSAGE*/);
Namespace.JINGLE_APPS_DTLS,
Namespace.JINGLE_MESSAGE);
private static final Collection<String> FEATURES_IMPACTING_PRIVACY =
Collections.singleton(Namespace.VERSION);

View file

@ -226,11 +226,18 @@ public class JingleConnectionManager extends AbstractManager {
private void respondWithJingleError(
final Iq original, String jingleCondition, final Error.Type type, Condition condition) {
// TODO add jingle condation
// TODO add jingle condition
connection.sendErrorFor(original, type, condition);
}
public void deliverMessage(
public void handle(final Message message) {
final String id = message.getId();
final String stanzaId = getManager(StanzaIdManager.class).getStanzaId(message);
final JingleMessage jingleMessage = message.getExtension(JingleMessage.class);
this.deliverMessage(message.getTo(), message.getFrom(), jingleMessage, id, stanzaId);
}
private void deliverMessage(
final Jid to,
final Jid from,
final JingleMessage message,

View file

@ -1,5 +1,8 @@
package im.conversations.android.xmpp.model.jmi;
import im.conversations.android.annotation.XmlElement;
@XmlElement
public class Accept extends JingleMessage {
public Accept() {

View file

@ -1,8 +1,10 @@
package im.conversations.android.xmpp.model.jmi;
import com.google.common.primitives.Ints;
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xml.Element;
@XmlElement
public class Proceed extends JingleMessage {
public Proceed() {

View file

@ -4,10 +4,12 @@ import com.google.common.collect.ImmutableList;
import eu.siacs.conversations.xmpp.jingle.stanzas.FileTransferDescription;
import eu.siacs.conversations.xmpp.jingle.stanzas.GenericDescription;
import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
import im.conversations.android.annotation.XmlElement;
import im.conversations.android.xml.Element;
import im.conversations.android.xml.Namespace;
import java.util.List;
@XmlElement
public class Propose extends JingleMessage {
public Propose() {

View file

@ -1,5 +1,8 @@
package im.conversations.android.xmpp.model.jmi;
import im.conversations.android.annotation.XmlElement;
@XmlElement
public class Reject extends JingleMessage {
public Reject() {

View file

@ -1,5 +1,8 @@
package im.conversations.android.xmpp.model.jmi;
import im.conversations.android.annotation.XmlElement;
@XmlElement
public class Retract extends JingleMessage {
public Retract() {

View file

@ -8,11 +8,13 @@ import im.conversations.android.xmpp.XmppConnection;
import im.conversations.android.xmpp.manager.ArchiveManager;
import im.conversations.android.xmpp.manager.CarbonsManager;
import im.conversations.android.xmpp.manager.ChatStateManager;
import im.conversations.android.xmpp.manager.JingleConnectionManager;
import im.conversations.android.xmpp.manager.PubSubManager;
import im.conversations.android.xmpp.manager.ReceiptManager;
import im.conversations.android.xmpp.manager.StanzaIdManager;
import im.conversations.android.xmpp.model.carbons.Received;
import im.conversations.android.xmpp.model.carbons.Sent;
import im.conversations.android.xmpp.model.jmi.JingleMessage;
import im.conversations.android.xmpp.model.mam.Result;
import im.conversations.android.xmpp.model.pubsub.event.Event;
import im.conversations.android.xmpp.model.stanza.Message;
@ -62,7 +64,16 @@ public class MessageProcessor extends XmppConnection.Delegate implements Consume
return;
}
// LOGGER.info("Message from {} with {}", message.getFrom(), message.getExtensionIds());
if (message.hasExtension(JingleMessage.class)) {
getManager(JingleConnectionManager.class).handle(message);
return;
}
LOGGER.info(
"Message from {} with {} in level {}",
message.getFrom(),
message.getExtensionIds(),
this.level);
final var from = message.getFrom();