From 33788189dde6759b6681bff3f121699bc4b641e0 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Thu, 12 Dec 2019 10:07:17 +1100 Subject: [PATCH] Distinguish public chat and rss feed from regular groups --- .../securesms/ApplicationContext.java | 6 +- .../conversation/ConversationActivity.java | 18 +++--- .../securesms/database/Address.java | 28 +++------ .../securesms/database/GroupDatabase.java | 4 ++ .../database/helpers/SQLCipherOpenHelper.java | 41 +++++++++++- .../securesms/groups/GroupManager.java | 57 +++++++++++++---- .../groups/GroupMessageProcessor.java | 14 ++--- .../securesms/jobs/AvatarDownloadJob.java | 19 +++--- .../jobs/MultiDeviceGroupUpdateJob.java | 2 +- .../securesms/jobs/PushDecryptJob.java | 23 ++++--- .../securesms/jobs/PushGroupSendJob.java | 63 +++++++++++-------- .../securesms/jobs/PushGroupUpdateJob.java | 2 +- .../securesms/jobs/RequestGroupInfoJob.java | 2 +- .../securesms/loki/LokiPublicChatManager.kt | 7 +-- .../securesms/loki/LokiPublicChatPoller.kt | 2 +- .../securesms/loki/LokiRSSFeedPoller.kt | 2 +- .../securesms/mms/IncomingMediaMessage.java | 2 +- .../securesms/sms/IncomingTextMessage.java | 2 +- .../securesms/sms/MessageSender.java | 4 +- .../securesms/util/GroupUtil.java | 31 ++++++++- .../securesms/util/IdentityUtil.java | 6 +- 21 files changed, 220 insertions(+), 115 deletions(-) diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 3da175eeb7..12d605620b 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -529,7 +529,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc public void createDefaultPublicChatsIfNeeded() { List defaultPublicChats = LokiPublicChatAPI.Companion.getDefaultChats(BuildConfig.DEBUG); for (LokiPublicChat publiChat : defaultPublicChats) { - long threadID = GroupManager.getThreadId(publiChat.getId(), this); + long threadID = GroupManager.getPublicChatThreadId(publiChat.getId(), this); String migrationKey = publiChat.getId() + "_migrated"; boolean isChatMigrated = TextSecurePreferences.getBooleanPreference(this, migrationKey, false); boolean isChatSetUp = TextSecurePreferences.isChatSetUp(this, publiChat.getId()); @@ -552,7 +552,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc for (LokiRSSFeed feed : feeds) { boolean isFeedSetUp = TextSecurePreferences.isChatSetUp(this, feed.getId()); if (!isFeedSetUp || !feed.isDeletable()) { - GroupManager.createGroup(feed.getId(), this, new HashSet<>(), null, feed.getDisplayName(), false); + GroupManager.createRSSFeedGroup(feed.getId(), this, null, feed.getDisplayName()); TextSecurePreferences.markChatSetUp(this, feed.getId()); } } @@ -561,7 +561,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc private void createRSSFeedPollersIfNeeded() { // Only create the RSS feed pollers if their threads aren't deleted LokiRSSFeed lokiNewsFeed = lokiNewsFeed(); - long lokiNewsFeedThreadID = GroupManager.getThreadId(lokiNewsFeed.getId(), this); + long lokiNewsFeedThreadID = GroupManager.getRSSFeedThreadId(lokiNewsFeed.getId(), this); if (lokiNewsFeedThreadID >= 0 && lokiNewsFeedPoller == null) { lokiNewsFeedPoller = new LokiRSSFeedPoller(this, lokiNewsFeed); // Set up deletion listeners if needed diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 16641984dd..f40d5aff44 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -442,10 +442,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity LokiAPIUtilities.INSTANCE.populateUserHexEncodedPublicKeyCacheIfNeeded(threadId, this); if (this.recipient.isGroupRecipient()) { - if (this.recipient.getName().equals("Loki Public Chat")) { - Analytics.Companion.getShared().track("Loki Public Chat Opened"); - } else { + if (this.recipient.getAddress().isPublicChat()) { + Analytics.Companion.getShared().track("Public Chat Opened"); + } else if (this.recipient.getAddress().isRSSFeed()) { Analytics.Companion.getShared().track("RSS Feed Opened"); + } else { + Analytics.Companion.getShared().track("Private Group Chat Opened"); } } else { Analytics.Companion.getShared().track("Conversation Opened"); @@ -687,9 +689,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity MenuInflater inflater = this.getMenuInflater(); menu.clear(); - boolean isLokiPublicChat = isGroupConversation(); // TODO: Figure out a better way of determining this + boolean isLokiGroupChat = recipient.getAddress().isPublicChat() || recipient.getAddress().isRSSFeed(); - if (isSecureText && !isLokiPublicChat) { // TODO: + if (isSecureText && !isLokiGroupChat) { if (recipient.getExpireMessages() > 0) { inflater.inflate(R.menu.conversation_expiring_on, menu); @@ -709,7 +711,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity if (isSecureText) inflater.inflate(R.menu.conversation_callable_secure, menu); else inflater.inflate(R.menu.conversation_callable_insecure, menu); */ - } else if (isGroupConversation() && !isLokiPublicChat) { + } else if (isGroupConversation() && !isLokiGroupChat) { inflater.inflate(R.menu.conversation_group_options, menu); if (!isPushGroupConversation()) { @@ -2007,7 +2009,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } private void setBlockedUserState(Recipient recipient, boolean isSecureText, boolean isDefaultSms) { - if (recipient.isGroupRecipient() && (recipient.getName().equals("Loki News") || recipient.getName().equals("Loki Messenger Updates"))) { + if (recipient.isGroupRecipient() && recipient.getAddress().isRSSFeed()) { unblockButton.setVisibility(View.GONE); composePanel.setVisibility(View.GONE); makeDefaultSmsButton.setVisibility(View.GONE); @@ -2036,7 +2038,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } private void setGroupShareProfileReminder(@NonNull Recipient recipient) { - if (recipient.isPushGroupRecipient() && !recipient.isProfileSharing()) { + if (recipient.isPushGroupRecipient() && !recipient.isProfileSharing() && !recipient.getAddress().isPublicChat() && !recipient.getAddress().isRSSFeed()) { groupShareProfileView.get().setRecipient(recipient); groupShareProfileView.get().setVisibility(View.VISIBLE); } else if (groupShareProfileView.resolved()) { diff --git a/src/org/thoughtcrime/securesms/database/Address.java b/src/org/thoughtcrime/securesms/database/Address.java index d063025cfa..1286b4b302 100644 --- a/src/org/thoughtcrime/securesms/database/Address.java +++ b/src/org/thoughtcrime/securesms/database/Address.java @@ -52,17 +52,9 @@ public class Address implements Parcelable, Comparable
{ private final String address; - // Loki - Special flag to indicate whether this address represents a public chat or not - private Boolean isPublicChat; - private Address(@NonNull String address) { - this(address, false); - } - - private Address(@NonNull String address, Boolean isPublicChat) { if (address == null) throw new AssertionError(address); this.address = address.toLowerCase(); - this.isPublicChat = isPublicChat; } public Address(Parcel in) { @@ -77,10 +69,6 @@ public class Address implements Parcelable, Comparable
{ return Address.fromSerialized(external); } - public static @NonNull Address fromPublicChatGroupID(@NonNull String serialized) { - return new Address(serialized, true); - } - public static @NonNull List
fromSerializedList(@NonNull String serialized, char delimiter) { String[] escapedAddresses = DelimiterUtil.split(serialized, delimiter); List
addresses = new LinkedList<>(); @@ -121,13 +109,15 @@ public class Address implements Parcelable, Comparable
{ } } - public boolean isGroup() { - return GroupUtil.isEncodedGroup(address); - } + public boolean isGroup() { return GroupUtil.isEncodedGroup(address); } - public boolean isMmsGroup() { - return GroupUtil.isMmsGroup(address); - } + public boolean isSignalGroup() { return !isPublicChat() && !isRSSFeed(); } + + public boolean isPublicChat() { return GroupUtil.isPublicChat(address); } + + public boolean isRSSFeed() { return GroupUtil.isRssFeed(address); } + + public boolean isMmsGroup() { return GroupUtil.isMmsGroup(address); } public boolean isEmail() { return NumberUtil.isValidEmail(address); @@ -143,7 +133,7 @@ public class Address implements Parcelable, Comparable
{ } public @NonNull String toPhoneString() { - if (!isPhone() && !isPublicChat) { + if (!isPhone() && !isPublicChat()) { if (isEmail()) throw new AssertionError("Not e164, is email"); if (isGroup()) throw new AssertionError("Not e164, is group"); throw new AssertionError("Not e164, unknown"); diff --git a/src/org/thoughtcrime/securesms/database/GroupDatabase.java b/src/org/thoughtcrime/securesms/database/GroupDatabase.java index 747ed36e41..9d2a815cb7 100644 --- a/src/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/src/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -448,6 +448,10 @@ public class GroupDatabase extends Database { return mms; } + public boolean isPublicChat() { return Address.fromSerialized(id).isPublicChat(); } + + public boolean isRSSFeed() { return Address.fromSerialized(id).isRSSFeed(); } + public String getUrl() { return url; } } } diff --git a/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 6715feb5ee..d0b12cdd42 100644 --- a/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -37,10 +37,14 @@ import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.loki.*; import org.thoughtcrime.securesms.notifications.NotificationChannels; +import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.service.KeyCachingService; +import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.whispersystems.signalservice.loki.api.LokiPublicChat; import java.io.File; +import java.security.acl.Group; public class SQLCipherOpenHelper extends SQLiteOpenHelper { @@ -71,8 +75,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { private static final int lokiV2 = 23; private static final int lokiV3 = 24; private static final int lokiV4 = 25; + private static final int lokiV5 = 26; - private static final int DATABASE_VERSION = lokiV4; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes + private static final int DATABASE_VERSION = lokiV5; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes private static final String DATABASE_NAME = "signal.db"; private final Context context; @@ -510,6 +515,40 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { db.execSQL(LokiMessageDatabase.getCreateMessageToThreadMappingTableCommand()); } + if (oldVersion < lokiV5) { + // Migrate public chats from __textsecure_group__ to __loki_public_chat_group__ + try (Cursor lokiPublicChatCursor = db.rawQuery("SELECT public_chat FROM loki_public_chat_database", null)) { + while (lokiPublicChatCursor != null && lokiPublicChatCursor.moveToNext()) { + String chatString = lokiPublicChatCursor.getString(0); + LokiPublicChat publicChat = LokiPublicChat.fromJSON(chatString); + if (publicChat != null) { + byte[] groupId = publicChat.getId().getBytes(); + String oldId = GroupUtil.getEncodedId(groupId, false); + String newId = GroupUtil.getEncodedPublicChatId(groupId); + ContentValues threadUpdate = new ContentValues(); + threadUpdate.put("recipient_ids", newId); + db.update("thread", threadUpdate, "recipient_ids = ?", new String[]{ oldId }); + ContentValues groupUpdate = new ContentValues(); + groupUpdate.put("group_id", newId); + db.update("groups", groupUpdate,"group_id = ?", new String[] { oldId }); + } + } + } + + // Migrate rss feeds from __textsecure_group__ to __loki_rss_feed_group__ + String[] rssFeedIds = new String[] { "loki.network.feed", "loki.network.messenger-updates.feed" }; + for (String groupId : rssFeedIds) { + String oldId = GroupUtil.getEncodedId(groupId.getBytes(), false); + String newId = GroupUtil.getEncodedRSSFeedId(groupId.getBytes()); + ContentValues threadUpdate = new ContentValues(); + threadUpdate.put("recipient_ids", newId); + db.update("thread", threadUpdate, "recipient_ids = ?", new String[]{ oldId }); + ContentValues groupUpdate = new ContentValues(); + groupUpdate.put("group_id", newId); + db.update("groups", groupUpdate,"group_id = ?", new String[] { oldId }); + } + } + db.setTransactionSuccessful(); } finally { db.endTransaction(); diff --git a/src/org/thoughtcrime/securesms/groups/GroupManager.java b/src/org/thoughtcrime/securesms/groups/GroupManager.java index e17b964d93..8f5004fbe3 100644 --- a/src/org/thoughtcrime/securesms/groups/GroupManager.java +++ b/src/org/thoughtcrime/securesms/groups/GroupManager.java @@ -36,8 +36,13 @@ import java.util.Set; public class GroupManager { - public static long getThreadId(String id, @NonNull Context context) { - final String groupId = GroupUtil.getEncodedId(id.getBytes(), false); + public static long getPublicChatThreadId(String id, @NonNull Context context) { + final String groupId = GroupUtil.getEncodedPublicChatId(id.getBytes()); + return getThreadIdFromGroupId(groupId, context); + } + + public static long getRSSFeedThreadId(String id, @NonNull Context context) { + final String groupId = GroupUtil.getEncodedRSSFeedId(id.getBytes()); return getThreadIdFromGroupId(groupId, context); } @@ -73,16 +78,6 @@ public class GroupManager { memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context))); groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null); - if (!mms) { - groupDatabase.updateAvatar(groupId, avatarBytes); - DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient, true); - } - - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); - return new GroupActionResult(groupRecipient, threadId); - - /* Loki: Original Code - ================== if (!mms) { groupDatabase.updateAvatar(groupId, avatarBytes); DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient, true); @@ -91,7 +86,43 @@ public class GroupManager { long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); return new GroupActionResult(groupRecipient, threadId); } - */ + } + + public static @NonNull GroupActionResult createPublicChatGroup(@NonNull String id, + @NonNull Context context, + @Nullable Bitmap avatar, + @Nullable String name) + { + final String groupId = GroupUtil.getEncodedPublicChatId(id.getBytes()); + return createLokiGroup(groupId, context, avatar, name); + } + + public static @NonNull GroupActionResult createRSSFeedGroup(@NonNull String id, + @NonNull Context context, + @Nullable Bitmap avatar, + @Nullable String name) + { + final String groupId = GroupUtil.getEncodedRSSFeedId(id.getBytes()); + return createLokiGroup(groupId, context, avatar, name); + } + + private static @NonNull GroupActionResult createLokiGroup(@NonNull String groupId, + @NonNull Context context, + @Nullable Bitmap avatar, + @Nullable String name) + { + final byte[] avatarBytes = BitmapUtil.toByteArray(avatar); + final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); + final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false); + final Set
memberAddresses = new HashSet<>(); + + memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context))); + groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null); + + groupDatabase.updateAvatar(groupId, avatarBytes); + + long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); + return new GroupActionResult(groupRecipient, threadId); } public static GroupActionResult updateGroup(@NonNull Context context, diff --git a/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java b/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java index 4033a8823f..49df8e0e37 100644 --- a/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java +++ b/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java @@ -58,7 +58,7 @@ public class GroupMessageProcessor { GroupDatabase database = DatabaseFactory.getGroupDatabase(context); SignalServiceGroup group = message.getGroupInfo().get(); - String id = GroupUtil.getEncodedId(group.getGroupId(), false); + String id = GroupUtil.getEncodedId(group); Optional record = database.getGroup(id); if (record.isPresent() && group.getType() == Type.UPDATE) { @@ -81,7 +81,7 @@ public class GroupMessageProcessor { boolean outgoing) { GroupDatabase database = DatabaseFactory.getGroupDatabase(context); - String id = GroupUtil.getEncodedId(group.getGroupId(), false); + String id = GroupUtil.getEncodedId(group); GroupContext.Builder builder = createGroupContext(group); builder.setType(GroupContext.Type.UPDATE); @@ -108,7 +108,7 @@ public class GroupMessageProcessor { { GroupDatabase database = DatabaseFactory.getGroupDatabase(context); - String id = GroupUtil.getEncodedId(group.getGroupId(), false); + String id = GroupUtil.getEncodedId(group); Set
recordMembers = new HashSet<>(groupRecord.getMembers()); Set
messageMembers = new HashSet<>(); @@ -179,7 +179,7 @@ public class GroupMessageProcessor { boolean outgoing) { GroupDatabase database = DatabaseFactory.getGroupDatabase(context); - String id = GroupUtil.getEncodedId(group.getGroupId(), false); + String id = GroupUtil.getEncodedId(group); List
members = record.getMembers(); GroupContext.Builder builder = createGroupContext(group); @@ -204,14 +204,14 @@ public class GroupMessageProcessor { { if (group.getAvatar().isPresent()) { ApplicationContext.getInstance(context).getJobManager() - .add(new AvatarDownloadJob(group.getGroupId())); + .add(new AvatarDownloadJob(GroupUtil.getEncodedId(group))); } try { if (outgoing) { MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context); - Address addres = Address.fromExternal(context, GroupUtil.getEncodedId(group.getGroupId(), false)); - Recipient recipient = Recipient.from(context, addres, false); + Address address = Address.fromExternal(context, GroupUtil.getEncodedId(group)); + Recipient recipient = Recipient.from(context, address, false); OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipient, storage, null, content.getTimestamp(), 0, null, Collections.emptyList(), Collections.emptyList()); long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null); diff --git a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java index 3536051086..77e4e1c883 100644 --- a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java @@ -40,9 +40,9 @@ public class AvatarDownloadJob extends BaseJob implements InjectableType { @Inject SignalServiceMessageReceiver receiver; - private byte[] groupId; + private String groupId; - public AvatarDownloadJob(@NonNull byte[] groupId) { + public AvatarDownloadJob(@NonNull String groupId) { this(new Job.Parameters.Builder() .addConstraint(NetworkConstraint.KEY) .setMaxAttempts(10) @@ -50,14 +50,14 @@ public class AvatarDownloadJob extends BaseJob implements InjectableType { groupId); } - private AvatarDownloadJob(@NonNull Job.Parameters parameters, @NonNull byte[] groupId) { + private AvatarDownloadJob(@NonNull Job.Parameters parameters, @NonNull String groupId) { super(parameters); this.groupId = groupId; } @Override public @NonNull Data serialize() { - return new Data.Builder().putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false)).build(); + return new Data.Builder().putString(KEY_GROUP_ID, groupId).build(); } @Override @@ -67,9 +67,8 @@ public class AvatarDownloadJob extends BaseJob implements InjectableType { @Override public void onRun() throws IOException { - String encodeId = GroupUtil.getEncodedId(groupId, false); GroupDatabase database = DatabaseFactory.getGroupDatabase(context); - Optional record = database.getGroup(encodeId); + Optional record = database.getGroup(groupId); File attachment = null; try { @@ -97,7 +96,7 @@ public class AvatarDownloadJob extends BaseJob implements InjectableType { InputStream inputStream = receiver.retrieveAttachment(pointer, attachment, MAX_AVATAR_SIZE); Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key, 0, digest), 500, 500); - database.updateAvatar(encodeId, avatar); + database.updateAvatar(groupId, avatar); inputStream.close(); } } catch (BitmapDecodingException | NonSuccessfulResponseCodeException | InvalidMessageException e) { @@ -120,11 +119,7 @@ public class AvatarDownloadJob extends BaseJob implements InjectableType { public static final class Factory implements Job.Factory { @Override public @NonNull AvatarDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) { - try { - return new AvatarDownloadJob(parameters, GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID))); - } catch (IOException e) { - throw new AssertionError(e); - } + return new AvatarDownloadJob(parameters, data.getString(KEY_GROUP_ID)); } } } diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java index be44c92233..52a81d5d57 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java @@ -85,7 +85,7 @@ public class MultiDeviceGroupUpdateJob extends BaseJob implements InjectableType reader = DatabaseFactory.getGroupDatabase(context).getGroups(); while ((record = reader.getNext()) != null) { - if (!record.isMms()) { + if (!record.isMms() && !record.isPublicChat() && !record.isRSSFeed()) { List members = new LinkedList<>(); for (Address member : record.getMembers()) { diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 641710a6a0..99e05c6565 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -350,7 +350,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { else if (message.getBody().isPresent()) handleTextMessage(content, message, smsMessageId, Optional.absent()); - if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))) { + if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get()))) { handleUnknownGroupMessage(content, message.getGroupInfo().get()); } @@ -606,9 +606,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType { private void handleUnknownGroupMessage(@NonNull SignalServiceContent content, @NonNull SignalServiceGroup group) { - ApplicationContext.getInstance(context) - .getJobManager() - .add(new RequestGroupInfoJob(content.getSender(), group.getGroupId())); + if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) { + ApplicationContext.getInstance(context) + .getJobManager() + .add(new RequestGroupInfoJob(content.getSender(), group.getGroupId())); + } } private void handleExpirationUpdate(@NonNull SignalServiceContent content, @@ -733,7 +735,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { threadId = handleSynchronizeSentTextMessage(message); } - if (message.getMessage().getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId(), false))) { + if (message.getMessage().getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get()))) { handleUnknownGroupMessage(content, message.getMessage().getGroupInfo().get()); } @@ -743,7 +745,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { Recipient recipient = null; if (message.getDestination().isPresent()) recipient = Recipient.from(context, Address.fromSerialized(message.getDestination().get()), false); - else if (message.getMessage().getGroupInfo().isPresent()) recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId(), false)), false); + else if (message.getMessage().getGroupInfo().isPresent()) recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get())), false); if (recipient != null && !recipient.isSystemContact() && !recipient.isProfileSharing()) { @@ -1571,10 +1573,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType { long threadId; if (typingMessage.getGroupId().isPresent()) { + // Typing messages should only apply to signal groups, thus we use `getEncodedId` Address groupAddress = Address.fromSerialized(GroupUtil.getEncodedId(typingMessage.getGroupId().get(), false)); Recipient groupRecipient = Recipient.from(context, groupAddress, false); - threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(groupRecipient); } else { // See if we need to redirect the message author = getPrimaryDeviceRecipient(content.getSender()); @@ -1723,7 +1726,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { private Recipient getSyncMessageDestination(SentTranscriptMessage message) { if (message.getMessage().getGroupInfo().isPresent()) { - return Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId(), false)), false); + return Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get())), false); } else { return Recipient.from(context, Address.fromSerialized(message.getDestination().get()), false); } @@ -1739,7 +1742,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { private Recipient getMessageDestination(SignalServiceContent content, SignalServiceDataMessage message) { if (message.getGroupInfo().isPresent()) { - return Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false)), false); + return Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get())), false); } else { return Recipient.from(context, Address.fromSerialized(content.getSender()), false); } @@ -1804,7 +1807,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { return true; } else if (conversation.isGroupRecipient()) { GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); - Optional groupId = message.getGroupInfo().isPresent() ? Optional.of(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false)) + Optional groupId = message.getGroupInfo().isPresent() ? Optional.of(GroupUtil.getEncodedId(message.getGroupInfo().get())) : Optional.absent(); if (groupId.isPresent() && groupDatabase.isUnknownGroup(groupId.get())) { diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index d5d4fa6c99..37b4c3ad8f 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.attachments.DatabaseAttachment; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.database.GroupReceiptDatabase.GroupReceiptInfo; import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.NoSuchMessageException; import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch; @@ -231,7 +232,15 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { throws IOException, UntrustedIdentityException, UndeliverableMessageException { // rotateSenderCertificateIfNecessary(); - String groupId = message.getRecipient().getAddress().toGroupString(); + // Messages shouldn't be able to be sent to RSS Feeds + Address groupAddress = message.getRecipient().getAddress(); + if (groupAddress.isRSSFeed()) { + List results = new ArrayList<>(); + for (Address destination : destinations) results.add(SendMessageResult.networkFailure(new SignalServiceAddress(destination.toPhoneString()))); + return results; + } + + String groupId = groupAddress.toGroupString(); Optional profileKey = getProfileKey(message.getRecipient()); Optional quote = getQuoteFor(message); Optional sticker = getStickerFor(message); @@ -247,24 +256,28 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { .map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)) .toList(); - if (message.isGroup()) { + SignalServiceGroup.GroupType groupType = SignalServiceGroup.GroupType.SIGNAL; + if (groupAddress.isPublicChat()) { + groupType = SignalServiceGroup.GroupType.PUBLIC_CHAT; + } + + if (message.isGroup() && groupAddress.isSignalGroup()) { + // Loki - Only send GroupUpdate or GroupQuit to signal groups OutgoingGroupMediaMessage groupMessage = (OutgoingGroupMediaMessage) message; GroupContext groupContext = groupMessage.getGroupContext(); SignalServiceAttachment avatar = attachmentPointers.isEmpty() ? null : attachmentPointers.get(0); SignalServiceGroup.Type type = groupMessage.isGroupQuit() ? SignalServiceGroup.Type.QUIT : SignalServiceGroup.Type.UPDATE; - SignalServiceGroup group = new SignalServiceGroup(type, GroupUtil.getDecodedId(groupId), groupContext.getName(), groupContext.getMembersList(), avatar); + SignalServiceGroup group = new SignalServiceGroup(type, GroupUtil.getDecodedId(groupId), groupType, groupContext.getName(), groupContext.getMembersList(), avatar); SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder() .withTimestamp(message.getSentTimeMillis()) .withExpiration(message.getRecipient().getExpireMessages()) + .withBody(message.getBody()) .asGroupMessage(group) .build(); - // Loki - Disable group updates for now - List results = new ArrayList<>(); - for (Address destination : destinations) results.add(SendMessageResult.success(new SignalServiceAddress(destination.toPhoneString()), false, false)); - return results; + return messageSender.sendMessage(messageId, addresses, unidentifiedAccess, groupDataMessage); } else { - SignalServiceGroup group = new SignalServiceGroup(GroupUtil.getDecodedId(groupId)); + SignalServiceGroup group = new SignalServiceGroup(GroupUtil.getDecodedId(groupId), groupType); SignalServiceDataMessage groupMessage = SignalServiceDataMessage.newBuilder() .withTimestamp(message.getSentTimeMillis()) .asGroupMessage(group) @@ -284,26 +297,24 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { } private @NonNull List
getGroupMessageRecipients(String groupId, long messageId) { - ArrayList
result = new ArrayList<>(); + if (GroupUtil.isRssFeed(groupId)) { return new ArrayList<>(); } - // Loki - All group messages should be directed to their respective servers - long threadID = GroupManager.getThreadIdFromGroupId(groupId, context); - LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID); - if (publicChat != null) { - // We need to somehow maintain information that will allow the sender to map - // a recipient to the correct public chat thread, and so this might be a bit hacky - result.add(Address.fromPublicChatGroupID(groupId)); + // Loki - All public chat group messages should be directed to their respective servers + if (GroupUtil.isPublicChat(groupId)) { + ArrayList
result = new ArrayList<>(); + long threadID = GroupManager.getThreadIdFromGroupId(groupId, context); + LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID); + if (publicChat != null) { + result.add(Address.fromSerialized(groupId)); + } + return result; + } else { + List destinations = DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId); + if (!destinations.isEmpty()) return Stream.of(destinations).map(GroupReceiptInfo::getAddress).toList(); + + List members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false); + return Stream.of(members).map(Recipient::getAddress).toList(); } - - return result; - - /* - List destinations = DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId); - if (!destinations.isEmpty()) return Stream.of(destinations).map(GroupReceiptInfo::getAddress).toList(); - - List members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false); - return Stream.of(members).map(Recipient::getAddress).toList(); - */ } public static class Factory implements Job.Factory { diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java index e12d094c11..d35dd2925f 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java @@ -104,7 +104,7 @@ public class PushGroupUpdateJob extends BaseJob implements InjectableType { SignalServiceGroup groupContext = SignalServiceGroup.newBuilder(Type.UPDATE) .withAvatar(avatar) - .withId(groupId) + .withId(groupId, SignalServiceGroup.GroupType.SIGNAL) .withMembers(members) .withName(record.get().getTitle()) .build(); diff --git a/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java b/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java index 380aeadc9b..795e1060c0 100644 --- a/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java @@ -71,7 +71,7 @@ public class RequestGroupInfoJob extends BaseJob implements InjectableType { @Override public void onRun() throws IOException, UntrustedIdentityException { SignalServiceGroup group = SignalServiceGroup.newBuilder(Type.REQUEST_INFO) - .withId(groupId) + .withId(groupId, SignalServiceGroup.GroupType.SIGNAL) .build(); SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder() diff --git a/src/org/thoughtcrime/securesms/loki/LokiPublicChatManager.kt b/src/org/thoughtcrime/securesms/loki/LokiPublicChatManager.kt index 01da3532ad..a4197ba156 100644 --- a/src/org/thoughtcrime/securesms/loki/LokiPublicChatManager.kt +++ b/src/org/thoughtcrime/securesms/loki/LokiPublicChatManager.kt @@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.Util import org.whispersystems.signalservice.loki.api.LokiPublicChat -import java.util.* class LokiPublicChatManager(private val context: Context) { private var chats = mutableMapOf() @@ -49,10 +48,10 @@ class LokiPublicChatManager(private val context: Context) { public fun addChat(server: String, channel: Long, name: String): LokiPublicChat { val chat = LokiPublicChat(channel, server, name, true) - var threadID = GroupManager.getThreadId(chat.id, context) + var threadID = GroupManager.getPublicChatThreadId(chat.id, context) // Create the group if we don't have one if (threadID < 0) { - val result = GroupManager.createGroup(chat.id, context, HashSet(), null, chat.displayName, false) + val result = GroupManager.createPublicChatGroup(chat.id, context, null, chat.displayName) threadID = result.threadId } DatabaseFactory.getLokiThreadDatabase(context).setPublicChat(chat, threadID) @@ -73,7 +72,7 @@ class LokiPublicChatManager(private val context: Context) { removedChatThreadIds.forEach { pollers.remove(it)?.stop() } // Only append to chats if we have a thread for the chat - chats = chatsInDB.filter { GroupManager.getThreadId(it.value.id, context) > -1 }.toMutableMap() + chats = chatsInDB.filter { GroupManager.getPublicChatThreadId(it.value.id, context) > -1 }.toMutableMap() } private fun listenToThreadDeletion(threadID: Long) { diff --git a/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt b/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt index b1af5cc08c..2667838ad8 100644 --- a/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt +++ b/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt @@ -112,7 +112,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki // region Polling private fun getDataMessage(message: LokiPublicChatMessage): SignalServiceDataMessage { val id = group.id.toByteArray() - val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, null, null, null) + val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.PUBLIC_CHAT, null, null, null) val quote = if (message.quote != null) { SignalServiceDataMessage.Quote(message.quote!!.quotedMessageTimestamp, SignalServiceAddress(message.quote!!.quoteeHexEncodedPublicKey), message.quote!!.quotedMessageBody, listOf()) } else { diff --git a/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt b/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt index d695c7de26..30d3b7c269 100644 --- a/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt +++ b/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt @@ -64,7 +64,7 @@ class LokiRSSFeedPoller(private val context: Context, private val feed: LokiRSSF bodyAsHTML = matcher.replaceAll("$2 ($1)") val body = Html.fromHtml(bodyAsHTML).toString().trim() val id = feed.id.toByteArray() - val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, null, null, null) + val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null) val x2 = SignalServiceDataMessage(timestamp, x1, null, body) val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false) PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.absent()) diff --git a/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java b/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java index 8d0c19962c..f4d0a4889e 100644 --- a/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java +++ b/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java @@ -79,7 +79,7 @@ public class IncomingMediaMessage { this.quote = quote.orNull(); this.unidentified = unidentified; - if (group.isPresent()) this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get().getGroupId(), false)); + if (group.isPresent()) this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get())); else this.groupId = null; this.attachments.addAll(PointerAttachment.forPointers(attachments)); diff --git a/src/org/thoughtcrime/securesms/sms/IncomingTextMessage.java b/src/org/thoughtcrime/securesms/sms/IncomingTextMessage.java index cfafcb7132..1c787355c3 100644 --- a/src/org/thoughtcrime/securesms/sms/IncomingTextMessage.java +++ b/src/org/thoughtcrime/securesms/sms/IncomingTextMessage.java @@ -78,7 +78,7 @@ public class IncomingTextMessage implements Parcelable { this.unidentified = unidentified; if (group.isPresent()) { - this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get().getGroupId(), false)); + this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get())); } else { this.groupId = null; } diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java index 9bb30f7dc6..744a81c39a 100644 --- a/src/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java @@ -202,7 +202,7 @@ public class MessageSender { if (attachment != null) { message.getAttachments().add(attachment); } long messageID = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener); // Loki - Set the message's friend request status as soon as it has hit the database - if (message.isFriendRequest) { + if (message.isFriendRequest && !recipient.getAddress().isGroup()) { FriendRequestHandler.updateFriendRequestState(context, FriendRequestHandler.ActionType.Sending, messageID, allocatedThreadId); } sendMediaMessage(context, recipient, forceSms, messageID, message.getExpiresIn()); @@ -215,7 +215,7 @@ public class MessageSender { try { long messageID = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener); // Loki - Set the message's friend request status as soon as it has hit the database - if (message.isFriendRequest) { + if (message.isFriendRequest && !recipient.getAddress().isGroup()) { FriendRequestHandler.updateFriendRequestState(context, FriendRequestHandler.ActionType.Sending, messageID, allocatedThreadId); } sendMediaMessage(context, recipient, forceSms, messageID, message.getExpiresIn()); diff --git a/src/org/thoughtcrime/securesms/util/GroupUtil.java b/src/org/thoughtcrime/securesms/util/GroupUtil.java index 224887fb0a..b8d2500a32 100644 --- a/src/org/thoughtcrime/securesms/util/GroupUtil.java +++ b/src/org/thoughtcrime/securesms/util/GroupUtil.java @@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientModifiedListener; import org.whispersystems.libsignal.util.guava.Optional; +import org.whispersystems.signalservice.api.messages.SignalServiceGroup; import java.io.IOException; import java.util.Collections; @@ -28,12 +29,32 @@ public class GroupUtil { private static final String ENCODED_SIGNAL_GROUP_PREFIX = "__textsecure_group__!"; private static final String ENCODED_MMS_GROUP_PREFIX = "__signal_mms_group__!"; + private static final String ENCODED_PUBLIC_CHAT_GROUP_PREFIX = "__loki_public_chat_group__!"; + private static final String ENCODED_RSS_FEED_GROUP_PREFIX = "__loki_rss_feed_group__!"; private static final String TAG = GroupUtil.class.getSimpleName(); + public static String getEncodedId(SignalServiceGroup group) { + byte[] groupId = group.getGroupId(); + if (group.getGroupType() == SignalServiceGroup.GroupType.PUBLIC_CHAT) { + return getEncodedPublicChatId(groupId); + } else if (group.getGroupType() == SignalServiceGroup.GroupType.RSS_FEED) { + return getEncodedRSSFeedId(groupId); + } + return getEncodedId(groupId, false); + } + public static String getEncodedId(byte[] groupId, boolean mms) { return (mms ? ENCODED_MMS_GROUP_PREFIX : ENCODED_SIGNAL_GROUP_PREFIX) + Hex.toStringCondensed(groupId); } + public static String getEncodedPublicChatId(byte[] groupId) { + return ENCODED_PUBLIC_CHAT_GROUP_PREFIX + Hex.toStringCondensed(groupId); + } + + public static String getEncodedRSSFeedId(byte[] groupId) { + return ENCODED_RSS_FEED_GROUP_PREFIX + Hex.toStringCondensed(groupId); + } + public static byte[] getDecodedId(String groupId) throws IOException { if (!isEncodedGroup(groupId)) { throw new IOException("Invalid encoding"); @@ -48,13 +69,21 @@ public class GroupUtil { } public static boolean isEncodedGroup(@NonNull String groupId) { - return groupId.startsWith(ENCODED_SIGNAL_GROUP_PREFIX) || groupId.startsWith(ENCODED_MMS_GROUP_PREFIX); + return groupId.startsWith(ENCODED_SIGNAL_GROUP_PREFIX) || groupId.startsWith(ENCODED_MMS_GROUP_PREFIX) || groupId.startsWith(ENCODED_PUBLIC_CHAT_GROUP_PREFIX) || groupId.startsWith(ENCODED_RSS_FEED_GROUP_PREFIX); } public static boolean isMmsGroup(@NonNull String groupId) { return groupId.startsWith(ENCODED_MMS_GROUP_PREFIX); } + public static boolean isPublicChat(@NonNull String groupId) { + return groupId.startsWith(ENCODED_PUBLIC_CHAT_GROUP_PREFIX); + } + + public static boolean isRssFeed(@NonNull String groupId) { + return groupId.startsWith(ENCODED_RSS_FEED_GROUP_PREFIX); + } + @WorkerThread public static Optional createGroupLeaveMessage(@NonNull Context context, @NonNull Recipient groupRecipient) { String encodedGroupId = groupRecipient.getAddress().toGroupString(); diff --git a/src/org/thoughtcrime/securesms/util/IdentityUtil.java b/src/org/thoughtcrime/securesms/util/IdentityUtil.java index 07336f0629..56dff28e6a 100644 --- a/src/org/thoughtcrime/securesms/util/IdentityUtil.java +++ b/src/org/thoughtcrime/securesms/util/IdentityUtil.java @@ -74,8 +74,9 @@ public class IdentityUtil { GroupDatabase.GroupRecord groupRecord; while ((groupRecord = reader.getNext()) != null) { + if (groupRecord.isRSSFeed() || groupRecord.isPublicChat()) { continue; } if (groupRecord.getMembers().contains(recipient.getAddress()) && groupRecord.isActive() && !groupRecord.isMms()) { - SignalServiceGroup group = new SignalServiceGroup(groupRecord.getId()); + SignalServiceGroup group = new SignalServiceGroup(groupRecord.getId(), SignalServiceGroup.GroupType.SIGNAL); if (remote) { IncomingTextMessage incoming = new IncomingTextMessage(recipient.getAddress(), 1, time, null, Optional.of(group), 0, false); @@ -126,8 +127,9 @@ public class IdentityUtil { GroupDatabase.GroupRecord groupRecord; while ((groupRecord = reader.getNext()) != null) { + if (groupRecord.isRSSFeed() || groupRecord.isPublicChat()) { continue; } if (groupRecord.getMembers().contains(recipient.getAddress()) && groupRecord.isActive()) { - SignalServiceGroup group = new SignalServiceGroup(groupRecord.getId()); + SignalServiceGroup group = new SignalServiceGroup(groupRecord.getId(), SignalServiceGroup.GroupType.SIGNAL); IncomingTextMessage incoming = new IncomingTextMessage(recipient.getAddress(), 1, time, null, Optional.of(group), 0, false); IncomingIdentityUpdateMessage groupUpdate = new IncomingIdentityUpdateMessage(incoming);