mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 10:05:15 +00:00
fix: fixing up LokiMessageDatabase.kt table structure, deletion closer to finished
This commit is contained in:
parent
51554f1cdf
commit
ef19c0d10e
@ -137,9 +137,19 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
|
||||
return openGroupMessagingDatabase.getMessageID(serverID)
|
||||
}
|
||||
|
||||
override fun deleteMessage(messageID: Long) {
|
||||
val messagingDatabase = DatabaseFactory.getSmsDatabase(context)
|
||||
messagingDatabase.deleteMessage(messageID)
|
||||
override fun getMessageID(serverId: Long, threadId: Long): Pair<Long, Boolean>? {
|
||||
val messageDB = DatabaseFactory.getLokiMessageDatabase(context)
|
||||
return messageDB.getMessageID(serverId, threadId)
|
||||
}
|
||||
|
||||
override fun deleteMessage(messageID: Long, isSms: Boolean) {
|
||||
if (isSms) {
|
||||
val db = DatabaseFactory.getSmsDatabase(context)
|
||||
db.deleteMessage(messageID)
|
||||
} else {
|
||||
val db = DatabaseFactory.getMmsDatabase(context)
|
||||
db.delete(messageID)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDatabaseAttachment(attachmentId: Long): DatabaseAttachment? {
|
||||
|
@ -1718,7 +1718,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
boolean initiating = threadId == -1;
|
||||
boolean needsSplit = message.length() > characterCalculator.calculateCharacters(message).maxPrimaryMessageSize;
|
||||
boolean isMediaMessage = attachmentManager.isAttachmentPresent() ||
|
||||
recipient.isGroupRecipient() ||
|
||||
// recipient.isGroupRecipient() ||
|
||||
inputPanel.getQuote().isPresent() ||
|
||||
linkPreviewViewModel.hasLinkPreview() ||
|
||||
LinkPreviewUtil.isValidMediaUrl(message) || // Loki - Send GIFs as media messages
|
||||
|
@ -533,7 +533,7 @@ public class ConversationFragment extends Fragment
|
||||
boolean isSentByUser = true;
|
||||
for (MessageRecord messageRecord : messageRecords) {
|
||||
isSentByUser = isSentByUser && messageRecord.isOutgoing();
|
||||
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id);
|
||||
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id, !messageRecord.isMms());
|
||||
if (serverID != null) {
|
||||
serverIDs.add(serverID);
|
||||
} else {
|
||||
@ -545,7 +545,7 @@ public class ConversationFragment extends Fragment
|
||||
.deleteMessages(serverIDs, publicChat.getChannel(), publicChat.getServer(), isSentByUser)
|
||||
.success(l -> {
|
||||
for (MessageRecord messageRecord : messageRecords) {
|
||||
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id);
|
||||
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id, !messageRecord.isMms());
|
||||
if (l.contains(serverID)) {
|
||||
if (messageRecord.isMms()) {
|
||||
DatabaseFactory.getMmsDatabase(getActivity()).delete(messageRecord.getId());
|
||||
@ -568,7 +568,7 @@ public class ConversationFragment extends Fragment
|
||||
.deleteMessage(serverId, openGroupChat.getRoom(), openGroupChat.getServer())
|
||||
.success(l -> {
|
||||
for (MessageRecord messageRecord : messageRecords) {
|
||||
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id);
|
||||
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id, !messageRecord.isMms());
|
||||
if (serverID != null && serverID.equals(serverId)) {
|
||||
if (messageRecord.isMms()) {
|
||||
DatabaseFactory.getMmsDatabase(getContext()).delete(messageRecord.getId());
|
||||
|
@ -388,8 +388,9 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
return database.getMessageFor(timestamp, address)?.getId()
|
||||
}
|
||||
|
||||
override fun setOpenGroupServerMessageID(messageID: Long, serverID: Long) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageID, serverID)
|
||||
override fun setOpenGroupServerMessageID(messageID: Long, serverID: Long, threadID: Long, isSms: Boolean) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageID, serverID, isSms)
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setOriginalThreadID(messageID, serverID, threadID)
|
||||
}
|
||||
|
||||
override fun getQuoteServerID(quoteID: Long, publicKey: String): Long? {
|
||||
|
@ -54,9 +54,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int lokiV20 = 41;
|
||||
private static final int lokiV21 = 42;
|
||||
private static final int lokiV22 = 43;
|
||||
private static final int lokiV23 = 44;
|
||||
|
||||
// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
|
||||
private static final int DATABASE_VERSION = lokiV22;
|
||||
private static final int DATABASE_VERSION = lokiV23;
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
@ -124,6 +125,8 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL(LokiUserDatabase.getCreateServerDisplayNameTableCommand());
|
||||
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
|
||||
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType());
|
||||
db.execSQL(LokiMessageDatabase.getUpdateMessageMappingTable());
|
||||
|
||||
executeStatements(db, SmsDatabase.CREATE_INDEXS);
|
||||
executeStatements(db, MmsDatabase.CREATE_INDEXS);
|
||||
@ -272,6 +275,11 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
"SendDeliveryReceiptJob");
|
||||
}
|
||||
|
||||
if (oldVersion < lokiV23) {
|
||||
db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType());
|
||||
db.execSQL(LokiMessageDatabase.getUpdateMessageMappingTable());
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
@ -6,11 +6,8 @@ import org.session.libsession.messaging.threads.Address
|
||||
import org.thoughtcrime.securesms.database.Database
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import org.thoughtcrime.securesms.loki.utilities.get
|
||||
import org.thoughtcrime.securesms.loki.utilities.getInt
|
||||
import org.thoughtcrime.securesms.loki.utilities.getString
|
||||
import org.thoughtcrime.securesms.loki.utilities.insertOrUpdate
|
||||
import org.session.libsignal.service.loki.database.LokiMessageDatabaseProtocol
|
||||
import org.thoughtcrime.securesms.loki.utilities.*
|
||||
|
||||
class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiMessageDatabaseProtocol {
|
||||
|
||||
@ -23,14 +20,21 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
private val friendRequestStatus = "friend_request_status"
|
||||
private val threadID = "thread_id"
|
||||
private val errorMessage = "error_message"
|
||||
private val messageType = "message_type"
|
||||
@JvmStatic val createMessageIDTableCommand = "CREATE TABLE $messageIDTable ($messageID INTEGER PRIMARY KEY, $serverID INTEGER DEFAULT 0, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createMessageToThreadMappingTableCommand = "CREATE TABLE IF NOT EXISTS $messageThreadMappingTable ($messageID INTEGER PRIMARY KEY, $threadID INTEGER);"
|
||||
@JvmStatic val createErrorMessageTableCommand = "CREATE TABLE IF NOT EXISTS $errorMessageTable ($messageID INTEGER PRIMARY KEY, $errorMessage STRING);"
|
||||
@JvmStatic val updateMessageIDTableForType = "ALTER TABLE $messageIDTable ADD COLUMN $messageType INTEGER DEFAULT 0; ALTER TABLE $messageIDTable ADD CONSTRAINT PK_$messageIDTable PRIMARY KEY ($messageID, $serverID);"
|
||||
@JvmStatic val updateMessageMappingTable = "ALTER TABLE $messageThreadMappingTable ADD COLUMN $serverID INTEGER DEFAULT 0; ALTER TABLE $messageThreadMappingTable ADD CONSTRAINT PK_$messageThreadMappingTable PRIMARY KEY ($messageID, $serverID);"
|
||||
|
||||
const val SMS_TYPE = 0
|
||||
const val MMS_TYPE = 1
|
||||
|
||||
}
|
||||
|
||||
override fun getQuoteServerID(quoteID: Long, quoteePublicKey: String): Long? {
|
||||
val message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quoteID, quoteePublicKey)
|
||||
return if (message != null) getServerID(message.getId()) else null
|
||||
return if (message != null) getServerID(message.getId(), !message.isMms) else null
|
||||
}
|
||||
|
||||
fun getServerID(messageID: Long): Long? {
|
||||
@ -40,6 +44,13 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
}?.toLong()
|
||||
}
|
||||
|
||||
fun getServerID(messageID: Long, isSms: Boolean): Long? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(messageIDTable, "${Companion.messageID} = ? AND $messageType = ?", arrayOf( messageID.toString(), if (isSms) SMS_TYPE.toString() else MMS_TYPE.toString() )) { cursor ->
|
||||
cursor.getInt(serverID)
|
||||
}?.toLong()
|
||||
}
|
||||
|
||||
fun getMessageID(serverID: Long): Long? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(messageIDTable, "${Companion.serverID} = ?", arrayOf( serverID.toString() )) { cursor ->
|
||||
@ -47,12 +58,22 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
}?.toLong()
|
||||
}
|
||||
|
||||
override fun setServerID(messageID: Long, serverID: Long) {
|
||||
fun getMessageID(serverID: Long, threadID: Long): Pair<Long,Boolean>? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get("$messageIDTable INNER JOIN $messageThreadMappingTable ON $messageIDTable.$messageID = $messageThreadMappingTable.$messageID",
|
||||
"${Companion.serverID} = ? AND ${Companion.threadID} = ?",
|
||||
arrayOf(serverID.toString(),threadID.toString())) { cursor ->
|
||||
cursor.getLong(messageID) to (cursor.getInt(messageType) == SMS_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setServerID(messageID: Long, serverID: Long, isSms: Boolean) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
contentValues.put(Companion.serverID, serverID)
|
||||
database.insertOrUpdate(messageIDTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
contentValues.put(messageType, if (isSms) SMS_TYPE else MMS_TYPE)
|
||||
database.insertOrUpdate(messageIDTable, contentValues, "${Companion.messageID} = ? AND ${Companion.serverID} = ?", arrayOf( messageID.toString(), serverID.toString() ))
|
||||
}
|
||||
|
||||
fun getOriginalThreadID(messageID: Long): Long {
|
||||
@ -62,12 +83,13 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
}?.toLong() ?: -1L
|
||||
}
|
||||
|
||||
fun setOriginalThreadID(messageID: Long, threadID: Long) {
|
||||
fun setOriginalThreadID(messageID: Long, serverID: Long, threadID: Long) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
contentValues.put(Companion.serverID, serverID)
|
||||
contentValues.put(Companion.threadID, threadID)
|
||||
database.insertOrUpdate(messageThreadMappingTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
database.insertOrUpdate(messageThreadMappingTable, contentValues, "${Companion.messageID} = ? AND ${Companion.serverID} = ?", arrayOf( messageID.toString(), serverID.toString() ))
|
||||
}
|
||||
|
||||
fun getErrorMessage(messageID: Long): String? {
|
||||
|
@ -11,7 +11,8 @@ import java.io.InputStream
|
||||
interface MessageDataProvider {
|
||||
|
||||
fun getMessageID(serverID: Long): Long?
|
||||
fun deleteMessage(messageID: Long)
|
||||
fun getMessageID(serverId: Long, threadId: Long): Pair<Long, Boolean>?
|
||||
fun deleteMessage(messageID: Long, isSms: Boolean)
|
||||
|
||||
fun getDatabaseAttachment(attachmentId: Long): DatabaseAttachment?
|
||||
|
||||
|
@ -64,7 +64,7 @@ interface StorageProtocol {
|
||||
// Open Groups
|
||||
fun getThreadID(openGroupID: String): String?
|
||||
fun addOpenGroup(server: String, channel: Long)
|
||||
fun setOpenGroupServerMessageID(messageID: Long, serverID: Long)
|
||||
fun setOpenGroupServerMessageID(messageID: Long, serverID: Long, threadID: Long, isSms: Boolean)
|
||||
fun getQuoteServerID(quoteID: Long, publicKey: String): Long?
|
||||
|
||||
// Open Group Public Keys
|
||||
@ -137,7 +137,7 @@ interface StorageProtocol {
|
||||
fun getOrCreateThreadIdFor(address: Address): Long
|
||||
fun getOrCreateThreadIdFor(publicKey: String, groupPublicKey: String?, openGroupID: String?): Long
|
||||
fun getThreadIdFor(address: Address): Long?
|
||||
fun getThreadIdForMms(messageId: Long): Long
|
||||
fun getThreadIdForMms(mmsId: Long): Long
|
||||
|
||||
// Session Request
|
||||
fun getSessionRequestSentTimestamp(publicKey: String): Long?
|
||||
|
@ -2,6 +2,7 @@ package org.session.libsession.messaging.open_groups
|
||||
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy
|
||||
import com.fasterxml.jackson.databind.annotation.JsonNaming
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import nl.komponents.kovenant.Kovenant
|
||||
@ -28,6 +29,8 @@ import org.session.libsignal.utilities.logging.Log
|
||||
import org.whispersystems.curve25519.Curve25519
|
||||
import java.util.*
|
||||
|
||||
typealias DeletionList = List<OpenGroupAPIV2.MessageDeletion>
|
||||
|
||||
object OpenGroupAPIV2 {
|
||||
|
||||
private val moderators: HashMap<String, Set<String>> = hashMapOf() // Server URL to (channel ID to set of moderator IDs)
|
||||
@ -60,7 +63,7 @@ object OpenGroupAPIV2 {
|
||||
val imageID: String?
|
||||
)
|
||||
|
||||
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy::class)
|
||||
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class)
|
||||
data class CompactPollRequest(val roomId: String,
|
||||
val authToken: String,
|
||||
val fromDeletionServerId: Long?,
|
||||
@ -72,6 +75,11 @@ object OpenGroupAPIV2 {
|
||||
val moderators: List<String>
|
||||
)
|
||||
|
||||
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class)
|
||||
data class MessageDeletion @JvmOverloads constructor(val id: Long = 0,
|
||||
val deletedMessageId: Long = 0
|
||||
)
|
||||
|
||||
data class Request(
|
||||
val verb: HTTP.Verb,
|
||||
val room: String?,
|
||||
@ -93,7 +101,7 @@ object OpenGroupAPIV2 {
|
||||
return RequestBody.create(MediaType.get("application/json"), parametersAsJSON)
|
||||
}
|
||||
|
||||
private fun send(request: Request): Promise<Map<*, *>, Exception> {
|
||||
private fun send(request: Request, isJsonRequired: Boolean = true): Promise<Map<*, *>, Exception> {
|
||||
val parsed = HttpUrl.parse(request.server) ?: return Promise.ofFail(Error.INVALID_URL)
|
||||
val urlBuilder = HttpUrl.Builder()
|
||||
.scheme(parsed.scheme())
|
||||
@ -128,7 +136,7 @@ object OpenGroupAPIV2 {
|
||||
if (request.useOnionRouting) {
|
||||
val publicKey = MessagingModuleConfiguration.shared.storage.getOpenGroupPublicKey(request.server)
|
||||
?: return Promise.ofFail(Error.NO_PUBLIC_KEY)
|
||||
return OnionRequestAPI.sendOnionRequest(requestBuilder.build(), request.server, publicKey)
|
||||
return OnionRequestAPI.sendOnionRequest(requestBuilder.build(), request.server, publicKey, isJSONRequired = isJsonRequired)
|
||||
.fail { e ->
|
||||
if (e is OnionRequestAPI.HTTPRequestFailedAtDestinationException && e.statusCode == 401) {
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
@ -289,7 +297,7 @@ object OpenGroupAPIV2 {
|
||||
}
|
||||
}
|
||||
|
||||
fun getDeletedMessages(room: String, server: String): Promise<List<Long>, Exception> {
|
||||
fun getDeletedMessages(room: String, server: String): Promise<List<MessageDeletion>, Exception> {
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val queryParameters = mutableMapOf<String, String>()
|
||||
storage.getLastDeletionServerId(room, server)?.let { last ->
|
||||
@ -297,12 +305,13 @@ object OpenGroupAPIV2 {
|
||||
}
|
||||
val request = Request(verb = GET, room = room, server = server, endpoint = "deleted_messages", queryParameters = queryParameters)
|
||||
return send(request).map(sharedContext) { json ->
|
||||
@Suppress("UNCHECKED_CAST") val serverIDs = (json["ids"] as? List<Int>)?.map { it.toLong() }
|
||||
?: throw Error.PARSING_FAILED
|
||||
val type = TypeFactory.defaultInstance().constructCollectionType(List::class.java, MessageDeletion::class.java)
|
||||
val idsAsString = JsonUtil.toJson(json["ids"])
|
||||
val serverIDs = JsonUtil.fromJson<List<MessageDeletion>>(idsAsString, type) ?: throw Error.PARSING_FAILED
|
||||
val lastMessageServerId = storage.getLastDeletionServerId(room, server) ?: 0
|
||||
val serverID = serverIDs.maxOrNull() ?: 0
|
||||
if (serverID > lastMessageServerId) {
|
||||
storage.setLastDeletionServerId(room, server, serverID)
|
||||
val serverID = serverIDs.maxByOrNull {it.id } ?: serverIDs.first()
|
||||
if (serverID.id > lastMessageServerId) {
|
||||
storage.setLastDeletionServerId(room, server, serverID.id)
|
||||
}
|
||||
serverIDs
|
||||
}
|
||||
@ -343,14 +352,14 @@ object OpenGroupAPIV2 {
|
||||
// endregion
|
||||
|
||||
// region General
|
||||
fun getCompactPoll(rooms: List<String>, server: String): Promise<Map<String,CompactPollResult>, Exception> {
|
||||
val requestAuths = rooms.associateWith { room -> getAuthToken(room,server) }
|
||||
fun getCompactPoll(rooms: List<String>, server: String): Promise<Map<String, CompactPollResult>, Exception> {
|
||||
val requestAuths = rooms.associateWith { room -> getAuthToken(room, server) }
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val requests = rooms.mapNotNull { room ->
|
||||
val authToken = try {
|
||||
requestAuths[room]?.get()
|
||||
} catch (e: Exception) {
|
||||
Log.e("Loki", "Failed to get auth token for $room",e)
|
||||
Log.e("Loki", "Failed to get auth token for $room", e)
|
||||
null
|
||||
} ?: return@mapNotNull null
|
||||
|
||||
@ -363,7 +372,7 @@ object OpenGroupAPIV2 {
|
||||
val request = Request(verb = POST, room = null, server = server, endpoint = "compact_poll", isAuthRequired = false, parameters = mapOf("requests" to requests))
|
||||
// build a request for all rooms
|
||||
return send(request = request).map(sharedContext) { json ->
|
||||
val results = json["results"] as? Map<*,*> ?: throw Error.PARSING_FAILED
|
||||
val results = json["results"] as? Map<*, *> ?: throw Error.PARSING_FAILED
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
|
@ -12,16 +12,15 @@ import org.session.libsession.messaging.messages.control.ClosedGroupControlMessa
|
||||
import org.session.libsession.messaging.messages.control.ConfigurationMessage
|
||||
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
|
||||
import org.session.libsession.messaging.messages.visible.*
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupMessage
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupMessageV2
|
||||
import org.session.libsession.messaging.open_groups.*
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsession.messaging.utilities.MessageWrapper
|
||||
import org.session.libsession.snode.RawResponsePromise
|
||||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsession.snode.SnodeModule
|
||||
import org.session.libsession.snode.SnodeMessage
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.SSKEnvironment
|
||||
import org.session.libsignal.service.internal.push.PushTransportDetails
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||
@ -290,8 +289,12 @@ object MessageSender {
|
||||
// Ignore future self-sends
|
||||
storage.addReceivedMessageTimestamp(message.sentTimestamp!!)
|
||||
// Track the open group server message ID
|
||||
if (message.openGroupServerMessageID != null) {
|
||||
storage.setOpenGroupServerMessageID(messageId, message.openGroupServerMessageID!!)
|
||||
if (message.openGroupServerMessageID != null && destination is Destination.OpenGroupV2) {
|
||||
val encoded = GroupUtil.getEncodedOpenGroupID("${destination.server}.${destination.room}".toByteArray())
|
||||
val threadID = storage.getThreadIdFor(Address.fromSerialized(encoded))
|
||||
if (threadID != null && threadID >= 0) {
|
||||
storage.setOpenGroupServerMessageID(messageId, message.openGroupServerMessageID!!, threadID, !(message as VisibleMessage).isMediaMessage())
|
||||
}
|
||||
}
|
||||
// Mark the message as sent
|
||||
storage.markAsSent(message.sentTimestamp!!, message.sender?:userPublicKey)
|
||||
|
@ -151,9 +151,19 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val context = MessagingModuleConfiguration.shared.context
|
||||
val userPublicKey = storage.getUserPublicKey()
|
||||
|
||||
// Get or create thread
|
||||
val threadID = storage.getOrCreateThreadIdFor(message.syncTarget
|
||||
?: message.sender!!, message.groupPublicKey, openGroupID)
|
||||
|
||||
val openGroup = threadID.let {
|
||||
storage.getOpenGroup(it.toString())
|
||||
}
|
||||
|
||||
// Update profile if needed
|
||||
val newProfile = message.profile
|
||||
if (newProfile != null && openGroupID.isNullOrEmpty() && userPublicKey != message.sender) {
|
||||
|
||||
if (newProfile != null && userPublicKey != message.sender && openGroup == null) {
|
||||
val profileManager = SSKEnvironment.shared.profileManager
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(message.sender!!), false)
|
||||
val displayName = newProfile.displayName!!
|
||||
@ -172,9 +182,6 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get or create thread
|
||||
val threadID = storage.getOrCreateThreadIdFor(message.syncTarget
|
||||
?: message.sender!!, message.groupPublicKey, openGroupID)
|
||||
// Parse quote if needed
|
||||
var quoteModel: QuoteModel? = null
|
||||
if (message.quote != null && proto.dataMessage.hasQuote()) {
|
||||
@ -224,6 +231,10 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS
|
||||
JobQueue.shared.add(downloadJob)
|
||||
}
|
||||
}
|
||||
val openGroupServerID = message.openGroupServerMessageID
|
||||
if (openGroupServerID != null) {
|
||||
storage.setOpenGroupServerMessageID(messageID, openGroupServerID, threadID, !(message.isMediaMessage() || attachments.isNotEmpty()))
|
||||
}
|
||||
// Cancel any typing indicators if needed
|
||||
cancelTypingIndicatorsIfNeeded(message.sender!!)
|
||||
//Notify the user if needed
|
||||
|
@ -9,6 +9,8 @@ import org.session.libsession.messaging.jobs.MessageReceiveJob
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPI
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupMessage
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.*
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.session.libsignal.utilities.successBackground
|
||||
@ -210,10 +212,13 @@ class OpenGroupPoller(private val openGroup: OpenGroup, private val executorServ
|
||||
}
|
||||
|
||||
private fun pollForDeletedMessages() {
|
||||
val messagingModule = MessagingModuleConfiguration.shared
|
||||
val address = GroupUtil.getEncodedOpenGroupID(openGroup.id.toByteArray())
|
||||
val threadId = messagingModule.storage.getThreadIdFor(Address.fromSerialized(address)) ?: return
|
||||
OpenGroupAPI.getDeletedMessageServerIDs(openGroup.channel, openGroup.server).success { deletedMessageServerIDs ->
|
||||
val deletedMessageIDs = deletedMessageServerIDs.mapNotNull { MessagingModuleConfiguration.shared.messageDataProvider.getMessageID(it) }
|
||||
deletedMessageIDs.forEach {
|
||||
MessagingModuleConfiguration.shared.messageDataProvider.deleteMessage(it)
|
||||
val deletedMessageIDs = deletedMessageServerIDs.mapNotNull { messagingModule.messageDataProvider.getMessageID(it, threadId) }
|
||||
deletedMessageIDs.forEach { (messageId, isSms) ->
|
||||
MessagingModuleConfiguration.shared.messageDataProvider.deleteMessage(messageId, isSms)
|
||||
}
|
||||
}.fail {
|
||||
Log.d("Loki", "Failed to get deleted messages for group chat with ID: ${openGroup.channel} on server: ${openGroup.server}.")
|
||||
|
@ -7,7 +7,10 @@ import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||
import org.session.libsignal.service.loki.database.LokiMessageDatabaseProtocol
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.session.libsignal.utilities.successBackground
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
@ -101,10 +104,17 @@ class OpenGroupV2Poller(private val openGroup: OpenGroupV2, private val executor
|
||||
}
|
||||
|
||||
private fun pollForDeletedMessages() {
|
||||
val messagingModule = MessagingModuleConfiguration.shared
|
||||
val address = GroupUtil.getEncodedOpenGroupID(openGroup.id.toByteArray())
|
||||
val threadId = messagingModule.storage.getThreadIdFor(Address.fromSerialized(address)) ?: return
|
||||
|
||||
OpenGroupAPIV2.getDeletedMessages(openGroup.room, openGroup.server).success { deletedMessageServerIDs ->
|
||||
val deletedMessageIDs = deletedMessageServerIDs.mapNotNull { MessagingModuleConfiguration.shared.messageDataProvider.getMessageID(it) }
|
||||
deletedMessageIDs.forEach {
|
||||
MessagingModuleConfiguration.shared.messageDataProvider.deleteMessage(it)
|
||||
|
||||
val deletedMessageIDs = deletedMessageServerIDs.mapNotNull { serverId ->
|
||||
messagingModule.messageDataProvider.getMessageID(serverId.deletedMessageId, threadId)
|
||||
}
|
||||
deletedMessageIDs.forEach { (messageId, isSms) ->
|
||||
MessagingModuleConfiguration.shared.messageDataProvider.deleteMessage(messageId, isSms)
|
||||
}
|
||||
}.fail {
|
||||
Log.d("Loki", "Failed to get deleted messages for group chat with ID: ${openGroup.room} on server: ${openGroup.server}.")
|
||||
|
@ -3,5 +3,5 @@ package org.session.libsignal.service.loki.database
|
||||
interface LokiMessageDatabaseProtocol {
|
||||
|
||||
fun getQuoteServerID(quoteID: Long, quoteePublicKey: String): Long?
|
||||
fun setServerID(messageID: Long, serverID: Long)
|
||||
fun setServerID(messageID: Long, serverID: Long, isSms: Boolean)
|
||||
}
|
||||
|
@ -3,8 +3,10 @@ package org.session.libsignal.utilities;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.ResolvedType;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
@ -42,6 +44,10 @@ public class JsonUtil {
|
||||
return objectMapper.readValue(serialized, clazz);
|
||||
}
|
||||
|
||||
public static<T> T fromJson(String serialized, JavaType clazz) throws IOException {
|
||||
return objectMapper.readValue(serialized, clazz);
|
||||
}
|
||||
|
||||
public static <T> T fromJson(InputStream serialized, Class<T> clazz) throws IOException {
|
||||
return objectMapper.readValue(serialized, clazz);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user