Search in sources :

Example 16 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupDatabase method removeUnmigratedV1Members.

/**
 * Removes the specified members from the list of 'unmigrated V1 members' -- the list of members
 * that were either dropped or had to be invited when migrating the group from V1->V2.
 */
public void removeUnmigratedV1Members(@NonNull GroupId.V2 id, @NonNull List<RecipientId> toRemove) {
    Optional<GroupRecord> group = getGroup(id);
    if (!group.isPresent()) {
        Log.w(TAG, "Couldn't find the group!", new Throwable());
        return;
    }
    List<RecipientId> newUnmigrated = group.get().getUnmigratedV1Members();
    newUnmigrated.removeAll(toRemove);
    ContentValues values = new ContentValues();
    values.put(UNMIGRATED_V1_MEMBERS, newUnmigrated.isEmpty() ? null : RecipientId.toSerializedList(newUnmigrated));
    databaseHelper.getSignalWritableDatabase().update(TABLE_NAME, values, GROUP_ID + " = ?", SqlUtil.buildArgs(id));
    Recipient.live(Recipient.externalGroupExact(context, id).getId()).refresh();
}
Also used : ContentValues(android.content.ContentValues) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId)

Example 17 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupDatabase method create.

/**
 * @param groupMasterKey null for V1, must be non-null for V2 (presence dictates group version).
 */
private void create(@NonNull GroupId groupId, @Nullable String title, @NonNull Collection<RecipientId> memberCollection, @Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable GroupMasterKey groupMasterKey, @Nullable DecryptedGroup groupState) {
    RecipientDatabase recipientDatabase = SignalDatabase.recipients();
    RecipientId groupRecipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
    List<RecipientId> members = new ArrayList<>(new HashSet<>(memberCollection));
    Collections.sort(members);
    ContentValues contentValues = new ContentValues();
    contentValues.put(RECIPIENT_ID, groupRecipientId.serialize());
    contentValues.put(GROUP_ID, groupId.toString());
    contentValues.put(TITLE, title);
    contentValues.put(MEMBERS, RecipientId.toSerializedList(members));
    if (avatar != null) {
        contentValues.put(AVATAR_ID, avatar.getRemoteId().getV2().get());
        contentValues.put(AVATAR_KEY, avatar.getKey());
        contentValues.put(AVATAR_CONTENT_TYPE, avatar.getContentType());
        contentValues.put(AVATAR_DIGEST, avatar.getDigest().orNull());
    } else {
        contentValues.put(AVATAR_ID, 0);
    }
    contentValues.put(AVATAR_RELAY, relay);
    contentValues.put(TIMESTAMP, System.currentTimeMillis());
    if (groupId.isV2()) {
        contentValues.put(ACTIVE, groupState != null && gv2GroupActive(groupState) ? 1 : 0);
        contentValues.put(DISTRIBUTION_ID, DistributionId.create().toString());
    } else if (groupId.isV1()) {
        contentValues.put(ACTIVE, 1);
        contentValues.put(EXPECTED_V2_ID, groupId.requireV1().deriveV2MigrationGroupId().toString());
    } else {
        contentValues.put(ACTIVE, 1);
    }
    contentValues.put(MMS, groupId.isMms());
    List<RecipientId> groupMembers = members;
    if (groupMasterKey != null) {
        if (groupState == null) {
            throw new AssertionError("V2 master key but no group state");
        }
        groupId.requireV2();
        groupMembers = getV2GroupMembers(groupState, true);
        contentValues.put(V2_MASTER_KEY, groupMasterKey.serialize());
        contentValues.put(V2_REVISION, groupState.getRevision());
        contentValues.put(V2_DECRYPTED_GROUP, groupState.toByteArray());
        contentValues.put(MEMBERS, RecipientId.toSerializedList(groupMembers));
    } else {
        if (groupId.isV2()) {
            throw new AssertionError("V2 group id but no master key");
        }
    }
    databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, contentValues);
    if (groupState != null && groupState.hasDisappearingMessagesTimer()) {
        recipientDatabase.setExpireMessages(groupRecipientId, groupState.getDisappearingMessagesTimer().getDuration());
    }
    if (groupMembers != null && (groupId.isMms() || Recipient.resolved(groupRecipientId).isProfileSharing())) {
        recipientDatabase.setHasGroupsInCommon(groupMembers);
    }
    Recipient.live(groupRecipientId).refresh();
    notifyConversationListListeners();
}
Also used : ContentValues(android.content.ContentValues) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) ArrayList(java.util.ArrayList)

Example 18 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class NotificationChannels method ensureCustomChannelConsistency.

@TargetApi(26)
@WorkerThread
public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) {
    if (!supported()) {
        return;
    }
    Log.d(TAG, "ensureCustomChannelConsistency()");
    NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
    RecipientDatabase db = SignalDatabase.recipients();
    List<Recipient> customRecipients = new ArrayList<>();
    Set<String> customChannelIds = new HashSet<>();
    try (RecipientDatabase.RecipientReader reader = db.getRecipientsWithNotificationChannels()) {
        Recipient recipient;
        while ((recipient = reader.getNext()) != null) {
            customRecipients.add(recipient);
            customChannelIds.add(recipient.getNotificationChannel());
        }
    }
    Set<String> existingChannelIds = Stream.of(notificationManager.getNotificationChannels()).map(NotificationChannel::getId).collect(Collectors.toSet());
    for (NotificationChannel existingChannel : notificationManager.getNotificationChannels()) {
        if ((existingChannel.getId().startsWith(CONTACT_PREFIX) || existingChannel.getId().startsWith(MESSAGES_PREFIX)) && Build.VERSION.SDK_INT >= CONVERSATION_SUPPORT_VERSION && existingChannel.getConversationId() != null) {
            if (customChannelIds.contains(existingChannel.getId())) {
                continue;
            }
            RecipientId id = ConversationUtil.getRecipientId(existingChannel.getConversationId());
            if (id != null) {
                Log.i(TAG, "Consistency: Conversation channel created outside of app, update " + id + " to use '" + existingChannel.getId() + "'");
                db.setNotificationChannel(id, existingChannel.getId());
            } else {
                Log.i(TAG, "Consistency: Conversation channel created outside of app with no matching recipient, deleting channel '" + existingChannel.getId() + "'");
                notificationManager.deleteNotificationChannel(existingChannel.getId());
            }
        } else if (existingChannel.getId().startsWith(CONTACT_PREFIX) && !customChannelIds.contains(existingChannel.getId())) {
            Log.i(TAG, "Consistency: Deleting channel '" + existingChannel.getId() + "' because the DB has no record of it.");
            notificationManager.deleteNotificationChannel(existingChannel.getId());
        } else if (existingChannel.getId().startsWith(MESSAGES_PREFIX) && !existingChannel.getId().equals(getMessagesChannel(context))) {
            Log.i(TAG, "Consistency: Deleting channel '" + existingChannel.getId() + "' because it's out of date.");
            notificationManager.deleteNotificationChannel(existingChannel.getId());
        }
    }
    for (Recipient customRecipient : customRecipients) {
        if (!existingChannelIds.contains(customRecipient.getNotificationChannel())) {
            Log.i(TAG, "Consistency: Removing custom channel '" + customRecipient.getNotificationChannel() + "' because the system doesn't have it.");
            db.setNotificationChannel(customRecipient.getId(), null);
        }
    }
}
Also used : NotificationChannel(android.app.NotificationChannel) RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) NotificationManager(android.app.NotificationManager) ArrayList(java.util.ArrayList) Recipient(org.thoughtcrime.securesms.recipients.Recipient) HashSet(java.util.HashSet) WorkerThread(androidx.annotation.WorkerThread) TargetApi(android.annotation.TargetApi)

Example 19 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class MarkReadReceiver method process.

public static void process(@NonNull Context context, @NonNull List<MarkedMessageInfo> markedReadMessages) {
    if (markedReadMessages.isEmpty())
        return;
    List<SyncMessageId> syncMessageIds = Stream.of(markedReadMessages).map(MarkedMessageInfo::getSyncMessageId).toList();
    List<ExpirationInfo> mmsExpirationInfo = Stream.of(markedReadMessages).map(MarkedMessageInfo::getExpirationInfo).filter(ExpirationInfo::isMms).filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0).toList();
    List<ExpirationInfo> smsExpirationInfo = Stream.of(markedReadMessages).map(MarkedMessageInfo::getExpirationInfo).filterNot(ExpirationInfo::isMms).filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0).toList();
    scheduleDeletion(context, smsExpirationInfo, mmsExpirationInfo);
    MultiDeviceReadUpdateJob.enqueue(syncMessageIds);
    Map<Long, List<MarkedMessageInfo>> threadToInfo = Stream.of(markedReadMessages).collect(Collectors.groupingBy(MarkedMessageInfo::getThreadId));
    Stream.of(threadToInfo).forEach(threadToInfoEntry -> {
        Map<RecipientId, List<MarkedMessageInfo>> recipientIdToInfo = Stream.of(threadToInfoEntry.getValue()).map(info -> info).collect(Collectors.groupingBy(info -> info.getSyncMessageId().getRecipientId()));
        Stream.of(recipientIdToInfo).forEach(entry -> {
            long threadId = threadToInfoEntry.getKey();
            RecipientId recipientId = entry.getKey();
            List<MarkedMessageInfo> infos = entry.getValue();
            SendReadReceiptJob.enqueue(threadId, recipientId, infos);
        });
    });
}
Also used : MarkedMessageInfo(org.thoughtcrime.securesms.database.MessageDatabase.MarkedMessageInfo) Context(android.content.Context) SignalDatabase(org.thoughtcrime.securesms.database.SignalDatabase) Collectors(com.annimon.stream.Collectors) Stream(com.annimon.stream.Stream) SyncMessageId(org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId) NonNull(androidx.annotation.NonNull) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) SendReadReceiptJob(org.thoughtcrime.securesms.jobs.SendReadReceiptJob) ExpirationInfo(org.thoughtcrime.securesms.database.MessageDatabase.ExpirationInfo) Intent(android.content.Intent) BroadcastReceiver(android.content.BroadcastReceiver) Log(org.signal.core.util.logging.Log) SuppressLint(android.annotation.SuppressLint) List(java.util.List) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) MultiDeviceReadUpdateJob(org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob) Map(java.util.Map) ExpiringMessageManager(org.thoughtcrime.securesms.service.ExpiringMessageManager) LinkedList(java.util.LinkedList) SignalExecutors(org.signal.core.util.concurrent.SignalExecutors) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) ExpirationInfo(org.thoughtcrime.securesms.database.MessageDatabase.ExpirationInfo) List(java.util.List) LinkedList(java.util.LinkedList) SyncMessageId(org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId) MarkedMessageInfo(org.thoughtcrime.securesms.database.MessageDatabase.MarkedMessageInfo)

Example 20 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class QuoteId method deserialize.

@Nullable
public static QuoteId deserialize(@NonNull Context context, @NonNull String serialized) {
    try {
        JSONObject json = new JSONObject(serialized);
        RecipientId id = json.has(AUTHOR) ? RecipientId.from(json.getString(AUTHOR)) : Recipient.external(context, json.getString(AUTHOR_DEPRECATED)).getId();
        return new QuoteId(json.getLong(ID), id);
    } catch (JSONException e) {
        Log.e(TAG, "Failed to deserialize from json", e);
        return null;
    }
}
Also used : RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) JSONObject(org.json.JSONObject) JSONException(org.json.JSONException) Nullable(androidx.annotation.Nullable)

Aggregations

RecipientId (org.thoughtcrime.securesms.recipients.RecipientId)154 NonNull (androidx.annotation.NonNull)70 Recipient (org.thoughtcrime.securesms.recipients.Recipient)70 List (java.util.List)34 ArrayList (java.util.ArrayList)33 Nullable (androidx.annotation.Nullable)32 Context (android.content.Context)31 Log (org.signal.core.util.logging.Log)31 IOException (java.io.IOException)30 ApplicationDependencies (org.thoughtcrime.securesms.dependencies.ApplicationDependencies)29 WorkerThread (androidx.annotation.WorkerThread)28 Stream (com.annimon.stream.Stream)27 LinkedList (java.util.LinkedList)25 ContentValues (android.content.ContentValues)24 Cursor (android.database.Cursor)24 Collections (java.util.Collections)24 SignalDatabase (org.thoughtcrime.securesms.database.SignalDatabase)24 GroupDatabase (org.thoughtcrime.securesms.database.GroupDatabase)23 Optional (org.whispersystems.libsignal.util.guava.Optional)22 HashSet (java.util.HashSet)21