2020-09-24 06:48:51 +02:00
|
|
|
package org.thoughtcrime.securesms.loki.api
|
|
|
|
|
|
|
|
import android.content.BroadcastReceiver
|
|
|
|
import android.content.Context
|
|
|
|
import android.content.Intent
|
|
|
|
import androidx.work.*
|
|
|
|
import nl.komponents.kovenant.Promise
|
|
|
|
import nl.komponents.kovenant.all
|
|
|
|
import nl.komponents.kovenant.functional.map
|
2021-03-23 01:12:37 +01:00
|
|
|
import org.session.libsession.messaging.jobs.MessageReceiveJob
|
2021-04-26 03:14:45 +02:00
|
|
|
import org.session.libsession.messaging.open_groups.OpenGroup
|
2021-05-03 09:58:02 +02:00
|
|
|
import org.session.libsession.messaging.open_groups.OpenGroupV2
|
2021-04-26 07:55:13 +02:00
|
|
|
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPoller
|
2021-03-23 01:12:37 +01:00
|
|
|
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPoller
|
2021-05-03 09:58:02 +02:00
|
|
|
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupV2Poller
|
2021-04-23 08:09:47 +02:00
|
|
|
import org.session.libsession.snode.SnodeAPI
|
2021-01-18 23:12:44 +01:00
|
|
|
import org.session.libsession.utilities.TextSecurePreferences
|
2021-03-19 07:08:31 +01:00
|
|
|
import org.session.libsignal.utilities.logging.Log
|
|
|
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
2021-04-23 08:09:47 +02:00
|
|
|
import java.io.IOException
|
2020-09-24 06:48:51 +02:00
|
|
|
import java.util.concurrent.TimeUnit
|
|
|
|
|
|
|
|
class BackgroundPollWorker(val context: Context, params: WorkerParameters) : Worker(context, params) {
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
const val TAG = "BackgroundPollWorker"
|
|
|
|
|
|
|
|
private const val RETRY_ATTEMPTS = 3
|
|
|
|
|
|
|
|
@JvmStatic
|
|
|
|
fun scheduleInstant(context: Context) {
|
|
|
|
val workRequest = OneTimeWorkRequestBuilder<BackgroundPollWorker>()
|
2020-11-20 08:59:13 +01:00
|
|
|
.setConstraints(Constraints.Builder()
|
|
|
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
|
|
|
.build()
|
2020-09-24 06:48:51 +02:00
|
|
|
)
|
|
|
|
.build()
|
|
|
|
|
|
|
|
WorkManager
|
|
|
|
.getInstance(context)
|
|
|
|
.enqueue(workRequest)
|
|
|
|
}
|
|
|
|
|
|
|
|
@JvmStatic
|
|
|
|
fun schedulePeriodic(context: Context) {
|
|
|
|
Log.v(TAG, "Scheduling periodic work.")
|
|
|
|
val workRequest = PeriodicWorkRequestBuilder<BackgroundPollWorker>(15, TimeUnit.MINUTES)
|
2020-11-20 08:59:13 +01:00
|
|
|
.setConstraints(Constraints.Builder()
|
|
|
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
|
|
|
.build()
|
2020-09-24 06:48:51 +02:00
|
|
|
)
|
|
|
|
.build()
|
|
|
|
|
|
|
|
WorkManager
|
|
|
|
.getInstance(context)
|
|
|
|
.enqueueUniquePeriodicWork(
|
|
|
|
TAG,
|
|
|
|
ExistingPeriodicWorkPolicy.KEEP,
|
|
|
|
workRequest
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun doWork(): Result {
|
|
|
|
if (TextSecurePreferences.getLocalNumber(context) == null) {
|
|
|
|
Log.v(TAG, "Background poll is canceled due to the Session user is not set up yet.")
|
|
|
|
return Result.failure()
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
Log.v(TAG, "Performing background poll.")
|
|
|
|
val promises = mutableListOf<Promise<Unit, Exception>>()
|
|
|
|
|
|
|
|
// Private chats
|
2021-01-18 23:12:44 +01:00
|
|
|
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
|
2021-04-23 08:09:47 +02:00
|
|
|
val privateChatsPromise = SnodeAPI.getMessages(userPublicKey).map { envelopes ->
|
2021-03-23 01:12:37 +01:00
|
|
|
envelopes.map { envelope ->
|
2021-05-12 08:17:25 +02:00
|
|
|
// FIXME: Using a job here seems like a bad idea...
|
2021-03-23 01:12:37 +01:00
|
|
|
MessageReceiveJob(envelope.toByteArray(), false).executeAsync()
|
2020-09-24 06:48:51 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-23 01:12:37 +01:00
|
|
|
promises.addAll(privateChatsPromise.get())
|
2020-09-24 06:48:51 +02:00
|
|
|
|
|
|
|
// Closed groups
|
2021-04-26 07:55:13 +02:00
|
|
|
promises.addAll(ClosedGroupPoller().pollOnce())
|
2020-09-24 06:48:51 +02:00
|
|
|
|
|
|
|
// Open Groups
|
2021-03-23 01:12:37 +01:00
|
|
|
val openGroups = DatabaseFactory.getLokiThreadDatabase(context).getAllPublicChats().map { (_,chat)->
|
|
|
|
OpenGroup(chat.channel, chat.server, chat.displayName, chat.isDeletable)
|
|
|
|
}
|
2020-09-24 06:48:51 +02:00
|
|
|
for (openGroup in openGroups) {
|
2021-03-23 01:12:37 +01:00
|
|
|
val poller = OpenGroupPoller(openGroup)
|
2020-09-24 06:48:51 +02:00
|
|
|
promises.add(poller.pollForNewMessages())
|
|
|
|
}
|
|
|
|
|
2021-05-03 09:58:02 +02:00
|
|
|
val openGroupsV2 = DatabaseFactory.getLokiThreadDatabase(context).getAllV2OpenGroups().values.groupBy(OpenGroupV2::server)
|
|
|
|
|
|
|
|
openGroupsV2.values.map { groups ->
|
|
|
|
OpenGroupV2Poller(groups)
|
|
|
|
}.forEach { poller ->
|
|
|
|
promises.add(poller.compactPoll(true).map{ /*Unit*/ })
|
|
|
|
}
|
|
|
|
|
2020-09-24 06:48:51 +02:00
|
|
|
// Wait till all the promises get resolved
|
|
|
|
all(promises).get()
|
|
|
|
|
|
|
|
return Result.success()
|
|
|
|
} catch (exception: Exception) {
|
|
|
|
Log.v(TAG, "Background poll failed due to error: ${exception.message}.", exception)
|
|
|
|
|
|
|
|
return if (runAttemptCount < RETRY_ATTEMPTS) Result.retry() else Result.failure()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class BootBroadcastReceiver: BroadcastReceiver() {
|
|
|
|
|
|
|
|
override fun onReceive(context: Context, intent: Intent) {
|
|
|
|
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
|
|
|
|
Log.v(TAG, "Boot broadcast caught.")
|
|
|
|
BackgroundPollWorker.scheduleInstant(context)
|
|
|
|
BackgroundPollWorker.schedulePeriodic(context)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|