package org.thoughtcrime.securesms.longmessage; import android.content.Context; import android.database.Cursor; import android.net.Uri; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; import org.session.libsession.utilities.Util; import org.session.libsession.utilities.concurrent.SignalExecutors; import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.guava.Optional; import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.SmsDatabase; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.mms.TextSlide; import java.io.IOException; import java.io.InputStream; class LongMessageRepository { private final static String TAG = LongMessageRepository.class.getSimpleName(); private final MmsDatabase mmsDatabase; private final SmsDatabase smsDatabase; LongMessageRepository(@NonNull Context context) { this.mmsDatabase = DatabaseComponent.get(context).mmsDatabase(); this.smsDatabase = DatabaseComponent.get(context).smsDatabase(); } void getMessage(@NonNull Context context, long messageId, boolean isMms, @NonNull Callback> callback) { SignalExecutors.BOUNDED.execute(() -> { if (isMms) { callback.onComplete(getMmsLongMessage(context, mmsDatabase, messageId)); } else { callback.onComplete(getSmsLongMessage(smsDatabase, messageId)); } }); } @WorkerThread private Optional getMmsLongMessage(@NonNull Context context, @NonNull MmsDatabase mmsDatabase, long messageId) { Optional record = getMmsMessage(mmsDatabase, messageId); if (record.isPresent()) { TextSlide textSlide = record.get().getSlideDeck().getTextSlide(); if (textSlide != null && textSlide.getUri() != null) { return Optional.of(new LongMessage(record.get(), readFullBody(context, textSlide.getUri()))); } else { return Optional.of(new LongMessage(record.get(), "")); } } else { return Optional.absent(); } } @WorkerThread private Optional getSmsLongMessage(@NonNull SmsDatabase smsDatabase, long messageId) { Optional record = getSmsMessage(smsDatabase, messageId); if (record.isPresent()) { return Optional.of(new LongMessage(record.get(), "")); } else { return Optional.absent(); } } @WorkerThread private Optional getMmsMessage(@NonNull MmsDatabase mmsDatabase, long messageId) { try (Cursor cursor = mmsDatabase.getMessage(messageId)) { return Optional.fromNullable((MmsMessageRecord) mmsDatabase.readerFor(cursor).getNext()); } } @WorkerThread private Optional getSmsMessage(@NonNull SmsDatabase smsDatabase, long messageId) { try (Cursor cursor = smsDatabase.getMessageCursor(messageId)) { return Optional.fromNullable(smsDatabase.readerFor(cursor).getNext()); } } private String readFullBody(@NonNull Context context, @NonNull Uri uri) { try (InputStream stream = PartAuthority.getAttachmentStream(context, uri)) { return Util.readFullyAsString(stream); } catch (IOException e) { Log.w(TAG, "Failed to read full text body.", e); return ""; } } interface Callback { void onComplete(T result); } }