mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-22 23:18:27 +00:00
Implement ClosedGroupPoller
This commit is contained in:
parent
1e16a940fe
commit
4ac15190bb
81
src/org/thoughtcrime/securesms/loki/api/ClosedGroupPoller.kt
Normal file
81
src/org/thoughtcrime/securesms/loki/api/ClosedGroupPoller.kt
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.api
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
|
import nl.komponents.kovenant.functional.bind
|
||||||
|
import nl.komponents.kovenant.functional.map
|
||||||
|
import org.thoughtcrime.securesms.jobs.PushContentReceiveJob
|
||||||
|
import org.thoughtcrime.securesms.logging.Log
|
||||||
|
import org.thoughtcrime.securesms.loki.database.SharedSenderKeysDatabase
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.successBackground
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope
|
||||||
|
import org.whispersystems.signalservice.loki.api.SnodeAPI
|
||||||
|
import org.whispersystems.signalservice.loki.api.SwarmAPI
|
||||||
|
import org.whispersystems.signalservice.loki.utilities.getRandomElementOrNull
|
||||||
|
|
||||||
|
class ClosedGroupPoller private constructor(private val context: Context, private val database: SharedSenderKeysDatabase) {
|
||||||
|
private var isPolling = false
|
||||||
|
private val handler = Handler()
|
||||||
|
|
||||||
|
private val task = object : Runnable {
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
poll()
|
||||||
|
handler.postDelayed(this, ClosedGroupPoller.pollInterval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Settings
|
||||||
|
companion object {
|
||||||
|
private val pollInterval: Long = 2 * 1000
|
||||||
|
|
||||||
|
public lateinit var shared: ClosedGroupPoller
|
||||||
|
|
||||||
|
public fun configureIfNeeded(context: Context, sskDatabase: SharedSenderKeysDatabase) {
|
||||||
|
if (::shared.isInitialized) { return; }
|
||||||
|
shared = ClosedGroupPoller(context, sskDatabase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Error
|
||||||
|
public class InsufficientSnodesException() : Exception("No snodes left to poll.")
|
||||||
|
public class PollingCanceledException() : Exception("Polling canceled.")
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Public API
|
||||||
|
public fun startIfNeeded() {
|
||||||
|
if (isPolling) { return }
|
||||||
|
isPolling = true
|
||||||
|
task.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun stopIfNeeded() {
|
||||||
|
isPolling = false
|
||||||
|
handler.removeCallbacks(task)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Private API
|
||||||
|
private fun poll() {
|
||||||
|
if (!isPolling) { return }
|
||||||
|
val publicKeys = database.getAllClosedGroupPublicKeys()
|
||||||
|
publicKeys.forEach { publicKey ->
|
||||||
|
SwarmAPI.shared.getSwarm(publicKey).bind { swarm ->
|
||||||
|
val snode = swarm.getRandomElementOrNull() ?: throw InsufficientSnodesException() // Should be cryptographically secure
|
||||||
|
if (!isPolling) { throw PollingCanceledException() }
|
||||||
|
SnodeAPI.shared.getRawMessages(snode).map {SnodeAPI.shared.parseRawMessagesResponse(it, snode) }
|
||||||
|
}.successBackground { messages ->
|
||||||
|
if (messages.isNotEmpty()) {
|
||||||
|
Log.d("Loki", "Received ${messages.count()} new message(s) in closed group with public key: $publicKey.")
|
||||||
|
}
|
||||||
|
messages.forEach {
|
||||||
|
PushContentReceiveJob(context).processEnvelope(SignalServiceEnvelope(it), false)
|
||||||
|
}
|
||||||
|
}.fail {
|
||||||
|
Log.d("Loki", "Polling failed for closed group with public key: $publicKey due to error: $it.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user