use of org.thoughtcrime.securesms.database.model.MessageId in project Signal-Android by signalapp.
the class MmsDatabase method getOutgoingMessage.
@Override
public OutgoingMediaMessage getOutgoingMessage(long messageId) throws MmsException, NoSuchMessageException {
AttachmentDatabase attachmentDatabase = SignalDatabase.attachments();
MentionDatabase mentionDatabase = SignalDatabase.mentions();
Cursor cursor = null;
try {
cursor = rawQuery(RAW_ID_WHERE, new String[] { String.valueOf(messageId) });
if (cursor != null && cursor.moveToNext()) {
List<DatabaseAttachment> associatedAttachments = attachmentDatabase.getAttachmentsForMessage(messageId);
List<Mention> mentions = mentionDatabase.getMentionsForMessage(messageId);
long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
String body = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID));
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
boolean viewOnce = cursor.getLong(cursor.getColumnIndexOrThrow(VIEW_ONCE)) == 1;
long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(RECIPIENT_ID));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
int distributionType = SignalDatabase.threads().getDistributionType(threadId);
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
long quoteId = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_ID));
long quoteAuthor = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_AUTHOR));
String quoteText = cursor.getString(cursor.getColumnIndexOrThrow(QUOTE_BODY));
boolean quoteMissing = cursor.getInt(cursor.getColumnIndexOrThrow(QUOTE_MISSING)) == 1;
List<Attachment> quoteAttachments = Stream.of(associatedAttachments).filter(Attachment::isQuote).map(a -> (Attachment) a).toList();
List<Mention> quoteMentions = parseQuoteMentions(context, cursor);
List<Contact> contacts = getSharedContacts(cursor, associatedAttachments);
Set<Attachment> contactAttachments = new HashSet<>(Stream.of(contacts).map(Contact::getAvatarAttachment).filter(a -> a != null).toList());
List<LinkPreview> previews = getLinkPreviews(cursor, associatedAttachments);
Set<Attachment> previewAttachments = Stream.of(previews).filter(lp -> lp.getThumbnail().isPresent()).map(lp -> lp.getThumbnail().get()).collect(Collectors.toSet());
List<Attachment> attachments = Stream.of(associatedAttachments).filterNot(Attachment::isQuote).filterNot(contactAttachments::contains).filterNot(previewAttachments::contains).sorted(new DatabaseAttachment.DisplayOrderComparator()).map(a -> (Attachment) a).toList();
Recipient recipient = Recipient.resolved(RecipientId.from(recipientId));
Set<NetworkFailure> networkFailures = new HashSet<>();
Set<IdentityKeyMismatch> mismatches = new HashSet<>();
QuoteModel quote = null;
if (quoteId > 0 && quoteAuthor > 0 && (!TextUtils.isEmpty(quoteText) || !quoteAttachments.isEmpty())) {
quote = new QuoteModel(quoteId, RecipientId.from(quoteAuthor), quoteText, quoteMissing, quoteAttachments, quoteMentions);
}
if (!TextUtils.isEmpty(mismatchDocument)) {
try {
mismatches = JsonUtils.fromJson(mismatchDocument, IdentityKeyMismatchSet.class).getItems();
} catch (IOException e) {
Log.w(TAG, e);
}
}
if (!TextUtils.isEmpty(networkDocument)) {
try {
networkFailures = JsonUtils.fromJson(networkDocument, NetworkFailureSet.class).getItems();
} catch (IOException e) {
Log.w(TAG, e);
}
}
if (body != null && (Types.isGroupQuit(outboxType) || Types.isGroupUpdate(outboxType))) {
return new OutgoingGroupUpdateMessage(recipient, new MessageGroupContext(body, Types.isGroupV2(outboxType)), attachments, timestamp, 0, false, quote, contacts, previews, mentions);
} else if (Types.isExpirationTimerUpdate(outboxType)) {
return new OutgoingExpirationUpdateMessage(recipient, timestamp, expiresIn);
}
OutgoingMediaMessage message = new OutgoingMediaMessage(recipient, body, attachments, timestamp, subscriptionId, expiresIn, viewOnce, distributionType, quote, contacts, previews, mentions, networkFailures, mismatches);
if (Types.isSecureType(outboxType)) {
return new OutgoingSecureMediaMessage(message);
}
return message;
}
throw new NoSuchMessageException("No record found for id: " + messageId);
} catch (IOException e) {
throw new MmsException(e);
} finally {
if (cursor != null)
cursor.close();
}
}
use of org.thoughtcrime.securesms.database.model.MessageId in project Signal-Android by signalapp.
the class MmsDatabase method incrementReceiptCount.
@Override
public Set<MessageUpdate> incrementReceiptCount(SyncMessageId messageId, long timestamp, @NonNull ReceiptType receiptType) {
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
Set<MessageUpdate> messageUpdates = new HashSet<>();
try (Cursor cursor = database.query(TABLE_NAME, new String[] { ID, THREAD_ID, MESSAGE_BOX, RECIPIENT_ID, receiptType.getColumnName(), RECEIPT_TIMESTAMP }, DATE_SENT + " = ?", new String[] { String.valueOf(messageId.getTimetamp()) }, null, null, null, null)) {
while (cursor.moveToNext()) {
if (Types.isOutgoingMessageType(CursorUtil.requireLong(cursor, MESSAGE_BOX))) {
RecipientId theirRecipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID));
RecipientId ourRecipientId = messageId.getRecipientId();
String columnName = receiptType.getColumnName();
if (ourRecipientId.equals(theirRecipientId) || Recipient.resolved(theirRecipientId).isGroup()) {
long id = CursorUtil.requireLong(cursor, ID);
long threadId = CursorUtil.requireLong(cursor, THREAD_ID);
int status = receiptType.getGroupStatus();
boolean isFirstIncrement = CursorUtil.requireLong(cursor, columnName) == 0;
long savedTimestamp = CursorUtil.requireLong(cursor, RECEIPT_TIMESTAMP);
long updatedTimestamp = isFirstIncrement ? Math.max(savedTimestamp, timestamp) : savedTimestamp;
database.execSQL("UPDATE " + TABLE_NAME + " SET " + columnName + " = " + columnName + " + 1, " + RECEIPT_TIMESTAMP + " = ? WHERE " + ID + " = ?", SqlUtil.buildArgs(updatedTimestamp, id));
SignalDatabase.groupReceipts().update(ourRecipientId, id, status, timestamp);
messageUpdates.add(new MessageUpdate(threadId, new MessageId(id, true)));
}
}
}
if (messageUpdates.size() > 0 && receiptType == ReceiptType.DELIVERY) {
earlyDeliveryReceiptCache.increment(messageId.getTimetamp(), messageId.getRecipientId(), timestamp);
}
return messageUpdates;
}
}
use of org.thoughtcrime.securesms.database.model.MessageId in project Signal-Android by signalapp.
the class SmsDatabase method markAsRemoteDelete.
@Override
public void markAsRemoteDelete(long id) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
long threadId;
db.beginTransaction();
try {
ContentValues values = new ContentValues();
values.put(REMOTE_DELETED, 1);
values.putNull(BODY);
db.update(TABLE_NAME, values, ID_WHERE, new String[] { String.valueOf(id) });
threadId = getThreadIdForMessage(id);
SignalDatabase.reactions().deleteReactions(new MessageId(id, false));
SignalDatabase.threads().update(threadId, false);
SignalDatabase.messageLog().deleteAllRelatedToMessage(id, false);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
notifyConversationListeners(threadId);
}
use of org.thoughtcrime.securesms.database.model.MessageId in project Signal-Android by signalapp.
the class SmsDatabase method setMessagesRead.
private List<MarkedMessageInfo> setMessagesRead(String where, String[] arguments) {
SQLiteDatabase database = databaseHelper.getSignalWritableDatabase();
List<MarkedMessageInfo> results = new LinkedList<>();
Cursor cursor = null;
RecipientId releaseChannelId = SignalStore.releaseChannelValues().getReleaseChannelRecipientId();
database.beginTransaction();
try {
cursor = database.query(TABLE_NAME, new String[] { ID, RECIPIENT_ID, DATE_SENT, TYPE, EXPIRES_IN, EXPIRE_STARTED, THREAD_ID }, where, arguments, null, null, null);
while (cursor != null && cursor.moveToNext()) {
if (Types.isSecureType(CursorUtil.requireLong(cursor, TYPE))) {
long threadId = CursorUtil.requireLong(cursor, THREAD_ID);
RecipientId recipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID));
long dateSent = CursorUtil.requireLong(cursor, DATE_SENT);
long messageId = CursorUtil.requireLong(cursor, ID);
long expiresIn = CursorUtil.requireLong(cursor, EXPIRES_IN);
long expireStarted = CursorUtil.requireLong(cursor, EXPIRE_STARTED);
SyncMessageId syncMessageId = new SyncMessageId(recipientId, dateSent);
ExpirationInfo expirationInfo = new ExpirationInfo(messageId, expiresIn, expireStarted, false);
if (!recipientId.equals(releaseChannelId)) {
results.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId, false), expirationInfo));
}
}
}
ContentValues contentValues = new ContentValues();
contentValues.put(READ, 1);
contentValues.put(REACTIONS_UNREAD, 0);
contentValues.put(REACTIONS_LAST_SEEN, System.currentTimeMillis());
database.update(TABLE_NAME, contentValues, where, arguments);
database.setTransactionSuccessful();
} finally {
if (cursor != null)
cursor.close();
database.endTransaction();
}
return results;
}
use of org.thoughtcrime.securesms.database.model.MessageId in project Signal-Android by signalapp.
the class SmsDatabase method insertMessageOutbox.
@Override
public long insertMessageOutbox(long threadId, OutgoingTextMessage message, boolean forceSms, long date, InsertListener insertListener) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
long type = Types.BASE_SENDING_TYPE;
if (message.isKeyExchange())
type |= Types.KEY_EXCHANGE_BIT;
else if (message.isSecureMessage())
type |= (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT);
else if (message.isEndSession())
type |= Types.END_SESSION_BIT;
if (forceSms)
type |= Types.MESSAGE_FORCE_SMS_BIT;
if (message.isIdentityVerified())
type |= Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
else if (message.isIdentityDefault())
type |= Types.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT;
RecipientId recipientId = message.getRecipient().getId();
Map<RecipientId, EarlyReceiptCache.Receipt> earlyDeliveryReceipts = earlyDeliveryReceiptCache.remove(date);
ContentValues contentValues = new ContentValues(6);
contentValues.put(RECIPIENT_ID, recipientId.serialize());
contentValues.put(THREAD_ID, threadId);
contentValues.put(BODY, message.getMessageBody());
contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
contentValues.put(DATE_SENT, date);
contentValues.put(READ, 1);
contentValues.put(TYPE, type);
contentValues.put(SUBSCRIPTION_ID, message.getSubscriptionId());
contentValues.put(EXPIRES_IN, message.getExpiresIn());
contentValues.put(DELIVERY_RECEIPT_COUNT, Stream.of(earlyDeliveryReceipts.values()).mapToLong(EarlyReceiptCache.Receipt::getCount).sum());
contentValues.put(RECEIPT_TIMESTAMP, Stream.of(earlyDeliveryReceipts.values()).mapToLong(EarlyReceiptCache.Receipt::getTimestamp).max().orElse(-1));
long messageId = db.insert(TABLE_NAME, null, contentValues);
if (insertListener != null) {
insertListener.onComplete();
}
if (!message.isIdentityVerified() && !message.isIdentityDefault()) {
SignalDatabase.threads().setLastScrolled(threadId, 0);
SignalDatabase.threads().setLastSeenSilently(threadId);
}
SignalDatabase.threads().setHasSentSilently(threadId, true);
ApplicationDependencies.getDatabaseObserver().notifyMessageInsertObservers(threadId, new MessageId(messageId, false));
if (!message.isIdentityVerified() && !message.isIdentityDefault()) {
TrimThreadJob.enqueueAsync(threadId);
}
return messageId;
}
Aggregations