From 338de329eda9dd19403810c9031ec756b911c336 Mon Sep 17 00:00:00 2001 From: 0x330a <92654767+0x330a@users.noreply.github.com> Date: Tue, 7 Mar 2023 17:10:07 +1100 Subject: [PATCH] feat: add user group config handling --- .../securesms/database/Storage.kt | 49 +++++++++++++++++++ .../securesms/groups/OpenGroupManager.kt | 9 ++-- libsession-util/src/main/cpp/util.cpp | 8 +++ .../libsession_util/util/BaseCommunity.kt | 1 + 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index c79d9389f8..7a13fe8d28 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -5,8 +5,10 @@ import android.net.Uri import network.loki.messenger.libsession_util.ConfigBase import network.loki.messenger.libsession_util.Contacts import network.loki.messenger.libsession_util.ConversationVolatileConfig +import network.loki.messenger.libsession_util.UserGroupsConfig import network.loki.messenger.libsession_util.UserProfile import network.loki.messenger.libsession_util.util.Conversation +import network.loki.messenger.libsession_util.util.GroupInfo import network.loki.messenger.libsession_util.util.UserPic import org.session.libsession.avatars.AvatarHelper import org.session.libsession.database.StorageProtocol @@ -302,6 +304,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF is UserProfile -> updateUser(forConfigObject) is Contacts -> updateContacts(forConfigObject) is ConversationVolatileConfig -> updateConvoVolatile(forConfigObject) + is UserGroupsConfig -> updateUserGroups(forConfigObject) } } @@ -377,6 +380,52 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF } } + private fun updateUserGroups(userGroups: UserGroupsConfig) { + val threadDb = DatabaseComponent.get(context).threadDatabase() + val (communities, lgc) = userGroups.all().partition { it is GroupInfo.CommunityGroupInfo } + val allOpenGroups = getAllOpenGroups() + val toDelete = allOpenGroups.filter { it.value.joinURL !in communities.map { (it as GroupInfo.CommunityGroupInfo).community.fullUrl() } } + val existingOpenGroups: Map = allOpenGroups.filterKeys { it !in toDelete.keys } + val existingJoinUrls = existingOpenGroups.values.map { it.joinURL } + val existingClosedGroups = getAllGroups() + + // delete the ones which are not listed in the config + toDelete.values.forEach { openGroup -> + OpenGroupManager.delete(openGroup.server, openGroup.room, context) + } + + for (groupInfo in communities) { + if (groupInfo !is GroupInfo.CommunityGroupInfo) continue + val groupBaseCommunity = groupInfo.community + if (groupBaseCommunity.fullUrl() !in existingJoinUrls) { + // add it + val (threadId, _) = OpenGroupManager.add(groupBaseCommunity.baseUrl, groupBaseCommunity.room, groupBaseCommunity.pubKeyHex, context) + threadDb.setPinned(threadId, groupInfo.priority >= 1) + } else { + val (threadId, _) = existingOpenGroups.entries.first { (_, v) -> v.joinURL == groupInfo.community.fullUrl() } + threadDb.setPinned(threadId, groupInfo.priority >= 1) + } + } + + for (group in lgc) { + if (group !is GroupInfo.LegacyGroupInfo) continue + val existingGroup = existingClosedGroups.firstOrNull { GroupUtil.doubleDecodeGroupId(it.encodedId) == group.sessionId } + if (existingGroup != null) { + Log.d("Loki-DBG", "Existing closed group, don't add") + if (group.hidden) { + threadDb.setThreadArchived(existingGroup.) + } + } else { + val members = group.members.keys.map { Address.fromSerialized(it) } + val admins = group.members.filter { it.value /*admin = true*/ }.keys.map { Address.fromSerialized(it) } + val groupId = GroupUtil.doubleEncodeGroupID(group.sessionId) + val title = group.name + val formationTimestamp = 0L + createGroup(groupId, title, members, null, null, admins, formationTimestamp) + } + } + } + override fun setAuthToken(room: String, server: String, newValue: String) { val id = "$server.$room" DatabaseComponent.get(context).lokiAPIDatabase().setAuthToken(id, newValue) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt index ef47269107..b4eec8dcf8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt @@ -58,14 +58,14 @@ object OpenGroupManager { } @WorkerThread - fun add(server: String, room: String, publicKey: String, context: Context): OpenGroupApi.RoomInfo? { + fun add(server: String, room: String, publicKey: String, context: Context): Pair { val openGroupID = "$server.$room" var threadID = GroupManager.getOpenGroupThreadID(openGroupID, context) val storage = MessagingModuleConfiguration.shared.storage val threadDB = DatabaseComponent.get(context).lokiThreadDatabase() // Check it it's added already val existingOpenGroup = threadDB.getOpenGroupChat(threadID) - if (existingOpenGroup != null) { return null } + if (existingOpenGroup != null) { return threadID to null } // Clear any existing data if needed storage.removeLastDeletionServerID(room, server) storage.removeLastMessageServerID(room, server) @@ -83,7 +83,7 @@ object OpenGroupManager { } val openGroup = OpenGroup(server = server, room = room, publicKey = publicKey, name = info.name, imageId = info.imageId, canWrite = info.write, infoUpdates = info.infoUpdates) threadDB.setOpenGroupChat(openGroup, threadID) - return info + return threadID to info } fun restartPollerForServer(server: String) { @@ -129,13 +129,14 @@ object OpenGroupManager { } } + @WorkerThread fun addOpenGroup(urlAsString: String, context: Context): OpenGroupApi.RoomInfo? { val url = HttpUrl.parse(urlAsString) ?: return null val server = OpenGroup.getServer(urlAsString) val room = url.pathSegments().firstOrNull() ?: return null val publicKey = url.queryParameter("public_key") ?: return null - return add(server.toString().removeSuffix("/"), room, publicKey, context) // assume migrated from calling function + return add(server.toString().removeSuffix("/"), room, publicKey, context).second // assume migrated from calling function } fun updateOpenGroup(openGroup: OpenGroup, context: Context) { diff --git a/libsession-util/src/main/cpp/util.cpp b/libsession-util/src/main/cpp/util.cpp index 11f1c94a1b..50808891fd 100644 --- a/libsession-util/src/main/cpp/util.cpp +++ b/libsession-util/src/main/cpp/util.cpp @@ -119,4 +119,12 @@ Java_network_loki_messenger_libsession_1util_util_BaseCommunityInfo_00024Compani jobject triple = env->NewObject(clazz, constructor, base_j, room_j, pk_jbytes); return triple; +} +extern "C" +JNIEXPORT jstring JNICALL +Java_network_loki_messenger_libsession_1util_util_BaseCommunityInfo_fullUrl(JNIEnv *env, + jobject thiz) { + auto deserialized = util::deserialize_base_community(env, thiz); + auto full_url = deserialized.full_url(); + return env->NewStringUTF(full_url.data()); } \ No newline at end of file diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BaseCommunity.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BaseCommunity.kt index f2312ff7fa..a48d082a62 100644 --- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BaseCommunity.kt +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BaseCommunity.kt @@ -7,4 +7,5 @@ data class BaseCommunityInfo(val baseUrl: String, val room: String, val pubKeyHe } external fun parseFullUrl(fullUrl: String): Triple? } + external fun fullUrl(): String } \ No newline at end of file