From a4d79ea2d34feea8897add4ffb4cb16223338304 Mon Sep 17 00:00:00 2001 From: jubb Date: Thu, 22 Apr 2021 17:26:40 +1000 Subject: [PATCH] feat: join groups logic --- .../loki/activities/JoinPublicChatActivity.kt | 19 +++++--------- .../securesms/loki/api/PublicChatManager.kt | 25 ++++++++----------- .../loki/database/LokiThreadDatabase.kt | 11 ++++++++ .../loki/utilities/OpenGroupUtilities.kt | 16 ++++++++++-- .../messaging/opengroups/OpenGroupAPIV2.kt | 6 +++-- .../messaging/opengroups/OpenGroupV2.kt | 16 +++++++----- .../sending_receiving/MessageReceiver.kt | 2 -- .../libsession/snode/OnionRequestAPI.kt | 2 +- 8 files changed, 56 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/JoinPublicChatActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/JoinPublicChatActivity.kt index f88765d223..faf4b5b5d2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/JoinPublicChatActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/JoinPublicChatActivity.kt @@ -4,7 +4,6 @@ import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.graphics.BitmapFactory import android.os.Bundle -import android.util.Patterns import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -76,25 +75,22 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode } fun joinPublicChatIfPossible(url: String) { - if (!Patterns.WEB_URL.matcher(url).matches() || !url.startsWith("https://")) { - return Toast.makeText(this, R.string.invalid_url, Toast.LENGTH_SHORT).show() - } - + // add http if just an IP style / host style URL is entered but leave it if scheme is included val properString = if (!url.startsWith("http")) "http://$url" else url - val httpUrl = HttpUrl.parse(url) ?: return Toast.makeText(this,R.string.invalid_url, Toast.LENGTH_SHORT).show() + val httpUrl = HttpUrl.parse(properString) ?: return Toast.makeText(this,R.string.invalid_url, Toast.LENGTH_SHORT).show() val room = httpUrl.pathSegments().firstOrNull() val publicKey = httpUrl.queryParameter("public_key") val isV2OpenGroup = !room.isNullOrEmpty() showLoader() - val channel: Long = 1 lifecycleScope.launch(Dispatchers.IO) { try { if (isV2OpenGroup) { - val server = httpUrl.newBuilder().removeAllQueryParameters("public_key").removePathSegment(0).build().toString() - OpenGroupUtilities.addGroup(this@JoinPublicChatActivity, server, room, publicKey) + val server = HttpUrl.Builder().scheme(httpUrl.scheme()).host(httpUrl.host()).build() + OpenGroupUtilities.addGroup(this@JoinPublicChatActivity, server.toString().removeSuffix("/"), room!!, publicKey!!) } else { + val channel: Long = 1 OpenGroupUtilities.addGroup(this@JoinPublicChatActivity, url, channel) } MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(this@JoinPublicChatActivity) @@ -195,10 +191,7 @@ class EnterChatURLFragment : Fragment() { private fun joinPublicChatIfPossible() { val inputMethodManager = requireContext().getSystemService(BaseActionBarActivity.INPUT_METHOD_SERVICE) as InputMethodManager inputMethodManager.hideSoftInputFromWindow(chatURLEditText.windowToken, 0) - var chatURL = chatURLEditText.text.trim().toString().toLowerCase().replace("http://", "https://") - if (!chatURL.toLowerCase().startsWith("https")) { - chatURL = "https://$chatURL" - } + val chatURL = chatURLEditText.text.trim().toString().toLowerCase() (requireActivity() as JoinPublicChatActivity).joinPublicChatIfPossible(chatURL) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/api/PublicChatManager.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/api/PublicChatManager.kt index bf8e82bc43..c33bc3ca31 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/api/PublicChatManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/api/PublicChatManager.kt @@ -80,15 +80,6 @@ class PublicChatManager(private val context: Context) { return addChat(server, channel, channelInfo) } - @WorkerThread - fun addChat(server: String, room: String): OpenGroupV2 { - // Ensure the auth token is acquired. - OpenGroupAPIV2.getAuthToken(room, server).get() - - val channelInfo = OpenGroupAPIV2.getInfo(room, server).get() - return addChat(server, room, channelInfo) - } - @WorkerThread public fun addChat(server: String, channel: Long, info: OpenGroupInfo): OpenGroup { val chat = PublicChat(channel, server, info.displayName, true) @@ -117,17 +108,21 @@ class PublicChatManager(private val context: Context) { @WorkerThread fun addChat(server: String, room: String, info: OpenGroupAPIV2.Info): OpenGroupV2 { - val chat = OpenGroupV2(server, room, info.id, info.name, info.imageID) - val threadID = GroupManager.getOpenGroupThreadID(chat.id, context) + val chat = OpenGroupV2(server, room, info.id, info.name) + var threadID = GroupManager.getOpenGroupThreadID(chat.id, context) var profilePicture: Bitmap? = null if (threadID < 0) { - val imageID = info.imageID - if (!imageID.isNullOrEmpty()) { - val profilePictureAsByteArray = OpenGroupAPIV2.downloadOpenGroupProfilePicture(info.id,server) + val profilePictureAsByteArray = try { + OpenGroupAPIV2.downloadOpenGroupProfilePicture(info.id,server).get() + } catch (e: Exception) { + null + } profilePicture = BitmapUtil.fromByteArray(profilePictureAsByteArray) - } val result = GroupManager.createOpenGroup(chat.id, context, profilePicture, info.name) + threadID = result.threadId } + DatabaseFactory.getLokiThreadDatabase(context).setOpenGroupChat(chat, threadID) + Util.runOnMain { startPollersIfNeeded() } return chat } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiThreadDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiThreadDatabase.kt index 189e0a5471..22cfcdd84c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiThreadDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiThreadDatabase.kt @@ -94,6 +94,17 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa } } + fun setOpenGroupChat(openGroupV2: OpenGroupV2, threadID: Long) { + if (threadID < 0) { + return + } + val database = databaseHelper.writableDatabase + val contentValues = ContentValues(2) + contentValues.put(Companion.threadID, threadID) + contentValues.put(publicChat, JsonUtil.toJson(openGroupV2.toJson())) + database.insertOrUpdate(publicChatTable, contentValues, "${Companion.threadID} = ?", arrayOf(threadID.toString())) + } + override fun getPublicChat(threadID: Long): PublicChat? { if (threadID < 0) { return null diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/OpenGroupUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/OpenGroupUtilities.kt index d38624b7b5..037ec1acbe 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/OpenGroupUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/OpenGroupUtilities.kt @@ -3,8 +3,10 @@ package org.thoughtcrime.securesms.loki.utilities import android.content.Context import androidx.annotation.WorkerThread import org.greenrobot.eventbus.EventBus +import org.session.libsession.messaging.MessagingConfiguration import org.session.libsession.messaging.opengroups.OpenGroup import org.session.libsession.messaging.opengroups.OpenGroupAPI +import org.session.libsession.messaging.opengroups.OpenGroupAPIV2 import org.session.libsession.messaging.opengroups.OpenGroupV2 import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.TextSecurePreferences @@ -21,14 +23,24 @@ object OpenGroupUtilities { @JvmStatic @WorkerThread - fun addGroup(context: Context, server: String, room: String, publicKey: String?): OpenGroupV2 { + fun addGroup(context: Context, server: String, room: String, publicKey: String): OpenGroupV2 { val groupId = "$server.$room" val threadID = GroupManager.getOpenGroupThreadID(groupId, context) val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID) if (openGroup != null) return openGroup + MessagingConfiguration.shared.storage.setOpenGroupPublicKey(server,publicKey) + OpenGroupAPIV2.getAuthToken(room, server).get() + val groupInfo = OpenGroupAPIV2.getInfo(room,server).get() val application = ApplicationContext.getInstance(context) - val group = application.publicChatManager.addChat(server, room, publicKey) + + val group = application.publicChatManager.addChat(server, room, groupInfo) + + val storage = MessagingConfiguration.shared.storage + storage.removeLastDeletionServerId(room, server) + storage.removeLastMessageServerId(room, server) + + return group } @JvmStatic diff --git a/libsession/src/main/java/org/session/libsession/messaging/opengroups/OpenGroupAPIV2.kt b/libsession/src/main/java/org/session/libsession/messaging/opengroups/OpenGroupAPIV2.kt index a097402a1f..57a67461ca 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/opengroups/OpenGroupAPIV2.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/opengroups/OpenGroupAPIV2.kt @@ -6,6 +6,7 @@ import nl.komponents.kovenant.Kovenant import nl.komponents.kovenant.Promise import nl.komponents.kovenant.functional.bind import nl.komponents.kovenant.functional.map +import okhttp3.Headers import okhttp3.HttpUrl import okhttp3.MediaType import okhttp3.RequestBody @@ -92,9 +93,10 @@ object OpenGroupAPIV2 { fun execute(token: String?): Promise, Exception> { val requestBuilder = okhttp3.Request.Builder() .url(urlBuilder.build()) + .headers(Headers.of(request.headers)) if (request.isAuthRequired) { if (token.isNullOrEmpty()) throw IllegalStateException("No auth token for request") - requestBuilder.addHeader("Authorization", token) + requestBuilder.header("Authorization", token) } when (request.verb) { GET -> requestBuilder.get() @@ -353,7 +355,7 @@ object OpenGroupAPIV2 { } fun getInfo(room: String, server: String): Promise { - val request = Request(verb = GET, room = room, server = server, endpoint = "rooms/$room", isAuthRequired = false) + val request = Request(verb = GET, room = null, server = server, endpoint = "rooms/$room", isAuthRequired = false) return send(request).map(sharedContext) { json -> val rawRoom = json["room"] as? Map<*, *> ?: throw Error.PARSING_FAILED val id = rawRoom["id"] as? String ?: throw Error.PARSING_FAILED diff --git a/libsession/src/main/java/org/session/libsession/messaging/opengroups/OpenGroupV2.kt b/libsession/src/main/java/org/session/libsession/messaging/opengroups/OpenGroupV2.kt index db700d3ccc..cac55cc222 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/opengroups/OpenGroupV2.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/opengroups/OpenGroupV2.kt @@ -8,17 +8,15 @@ data class OpenGroupV2( val room: String, val id: String, val name: String, - val publicKey: String, - val imageId: String? + val publicKey: String ) { - constructor(server: String, room: String, name: String, publicKey: String, imageId: String?) : this( + constructor(server: String, room: String, name: String, publicKey: String) : this( server = server, room = room, id = "$server.$room", name = name, publicKey = publicKey, - imageId = imageId ) companion object { @@ -32,9 +30,8 @@ data class OpenGroupV2( val server = json.get("server").asText().toLowerCase(Locale.getDefault()) val displayName = json.get("displayName").asText() val publicKey = json.get("publicKey").asText() - val imageId = json.get("imageId").asText().let { str -> if (str.isEmpty()) null else str } - OpenGroupV2(server, room, displayName, publicKey, imageId) + OpenGroupV2(server, room, displayName, publicKey) } catch (e: Exception) { null } @@ -42,4 +39,11 @@ data class OpenGroupV2( } + fun toJson(): Map = mapOf( + "room" to room, + "server" to server, + "displayName" to name, + "publicKey" to publicKey, + ) + } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt index 216d79627c..9cfbfaa720 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt @@ -7,7 +7,6 @@ import org.session.libsession.messaging.messages.visible.VisibleMessage import org.session.libsession.utilities.GroupUtil import org.session.libsignal.service.internal.push.PushTransportDetails import org.session.libsignal.service.internal.push.SignalServiceProtos -import org.session.libsignal.utilities.logging.Log object MessageReceiver { @@ -122,7 +121,6 @@ object MessageReceiver { message.recipient = userPublicKey message.sentTimestamp = envelope.timestamp message.receivedTimestamp = if (envelope.hasServerTimestamp()) envelope.serverTimestamp else System.currentTimeMillis() - Log.d("Loki", "time: ${envelope.timestamp}, sent: ${envelope.serverTimestamp}") message.groupPublicKey = groupPublicKey message.openGroupServerMessageID = openGroupServerID // Validate diff --git a/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt b/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt index 836af5dd79..4c06c989ba 100644 --- a/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt +++ b/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt @@ -445,7 +445,7 @@ object OnionRequestAPI { val urlAsString = url.toString() val host = url.host() val endpoint = when { - server.count() < urlAsString.count() -> urlAsString.substringAfter("$server/") + server.count() < urlAsString.count() -> urlAsString.substringAfter(server).removePrefix("/") else -> "" } val body = request.getBodyForOnionRequest() ?: "null"