mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-11 15:17:43 +00:00
Fixed a few issues with the OpenGroupPoller
Fixed an issue where the admin/moderator status wasn't getting stored if set before joining a community Fixed an issue where multiple pollers for the same server could run at the same time when joining multiple rooms within the same app run (very noticeable when restoring/linking)
This commit is contained in:
@@ -39,13 +39,7 @@ class BackgroundGroupAddJob(val joinUrl: String): Job {
|
||||
delegate?.handleJobFailed(this, dispatcherName, DuplicateGroupException())
|
||||
return
|
||||
}
|
||||
// get image
|
||||
storage.setOpenGroupPublicKey(openGroup.server, openGroup.serverPublicKey)
|
||||
val info = storage.addOpenGroup(openGroup.joinUrl())
|
||||
val imageId = info?.imageId
|
||||
if (imageId != null && storage.getGroupAvatarDownloadJob(openGroup.server, openGroup.room, imageId) == null) {
|
||||
JobQueue.shared.add(GroupAvatarDownloadJob(openGroup.server, openGroup.room, imageId))
|
||||
}
|
||||
storage.addOpenGroup(openGroup.joinUrl())
|
||||
Log.d(KEY, "onOpenGroupAdded(${openGroup.server})")
|
||||
storage.onOpenGroupAdded(openGroup.server)
|
||||
} catch (e: Exception) {
|
||||
|
@@ -109,7 +109,26 @@ object OpenGroupApi {
|
||||
val defaultWrite: Boolean = false,
|
||||
val upload: Boolean = false,
|
||||
val defaultUpload: Boolean = false,
|
||||
)
|
||||
) {
|
||||
fun toPollInfo(): RoomPollInfo {
|
||||
return RoomPollInfo(
|
||||
token = token,
|
||||
activeUsers = activeUsers,
|
||||
admin = admin,
|
||||
globalAdmin = globalAdmin,
|
||||
moderator = moderator,
|
||||
globalModerator = globalModerator,
|
||||
read = read,
|
||||
defaultRead = defaultRead,
|
||||
defaultAccessible = defaultAccessible,
|
||||
write = write,
|
||||
defaultWrite = defaultWrite,
|
||||
upload = upload,
|
||||
defaultUpload = defaultUpload,
|
||||
details = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class)
|
||||
data class PinnedMessage(
|
||||
|
@@ -30,6 +30,7 @@ import org.session.libsignal.protos.SignalServiceProtos
|
||||
import org.session.libsignal.utilities.Base64
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.successBackground
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.ScheduledFuture
|
||||
import java.util.concurrent.TimeUnit
|
||||
@@ -39,15 +40,97 @@ class OpenGroupPoller(private val server: String, private val executorService: S
|
||||
var isCaughtUp = false
|
||||
var secondToLastJob: MessageReceiveJob? = null
|
||||
private var future: ScheduledFuture<*>? = null
|
||||
private var runId: UUID = UUID.randomUUID()
|
||||
|
||||
companion object {
|
||||
private const val pollInterval: Long = 4000L
|
||||
const val maxInactivityPeriod = 14 * 24 * 60 * 60 * 1000
|
||||
|
||||
public fun handleRoomPollInfo(
|
||||
server: String,
|
||||
roomToken: String,
|
||||
pollInfo: OpenGroupApi.RoomPollInfo,
|
||||
createGroupIfMissingWithPublicKey: String? = null
|
||||
) {
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val groupId = "$server.$roomToken"
|
||||
val dbGroupId = GroupUtil.getEncodedOpenGroupID(groupId.toByteArray())
|
||||
val existingOpenGroup = storage.getOpenGroup(roomToken, server)
|
||||
|
||||
// If we don't have an existing group and don't have a 'createGroupIfMissingWithPublicKey'
|
||||
// value then don't process the poll info
|
||||
val publicKey = ((existingOpenGroup?.publicKey ?: createGroupIfMissingWithPublicKey) ?: return)
|
||||
|
||||
val openGroup = OpenGroup(
|
||||
server = server,
|
||||
room = pollInfo.token,
|
||||
name = ((pollInfo.details?.name ?: existingOpenGroup?.name) ?: ""),
|
||||
publicKey = publicKey,
|
||||
imageId = (pollInfo.details?.imageId ?: existingOpenGroup?.imageId),
|
||||
canWrite = pollInfo.write,
|
||||
infoUpdates = ((pollInfo.details?.infoUpdates ?: existingOpenGroup?.infoUpdates) ?: 0)
|
||||
)
|
||||
// - Open Group changes
|
||||
storage.updateOpenGroup(openGroup)
|
||||
|
||||
// - User Count
|
||||
storage.setUserCount(roomToken, server, pollInfo.activeUsers)
|
||||
|
||||
// - Moderators
|
||||
pollInfo.details?.moderators?.let { moderatorList ->
|
||||
storage.setGroupMemberRoles(moderatorList.map {
|
||||
GroupMember(groupId, it, GroupMemberRole.MODERATOR)
|
||||
})
|
||||
}
|
||||
pollInfo.details?.hiddenModerators?.let { moderatorList ->
|
||||
storage.setGroupMemberRoles(moderatorList.map {
|
||||
GroupMember(groupId, it, GroupMemberRole.HIDDEN_MODERATOR)
|
||||
})
|
||||
}
|
||||
// - Admins
|
||||
pollInfo.details?.admins?.let { moderatorList ->
|
||||
storage.setGroupMemberRoles(moderatorList.map {
|
||||
GroupMember(groupId, it, GroupMemberRole.ADMIN)
|
||||
})
|
||||
}
|
||||
pollInfo.details?.hiddenAdmins?.let { moderatorList ->
|
||||
storage.setGroupMemberRoles(moderatorList.map {
|
||||
GroupMember(groupId, it, GroupMemberRole.HIDDEN_ADMIN)
|
||||
})
|
||||
}
|
||||
|
||||
// Update the group avatar
|
||||
if (
|
||||
(
|
||||
pollInfo.details != null &&
|
||||
pollInfo.details.imageId != null && (
|
||||
pollInfo.details.imageId != existingOpenGroup?.imageId ||
|
||||
!storage.hasDownloadedProfilePicture(dbGroupId)
|
||||
) &&
|
||||
storage.getGroupAvatarDownloadJob(openGroup.server, openGroup.room, pollInfo.details.imageId) == null
|
||||
) || (
|
||||
pollInfo.details == null &&
|
||||
existingOpenGroup?.imageId != null &&
|
||||
!storage.hasDownloadedProfilePicture(dbGroupId) &&
|
||||
storage.getGroupAvatarDownloadJob(openGroup.server, openGroup.room, existingOpenGroup.imageId) == null
|
||||
)
|
||||
) {
|
||||
JobQueue.shared.add(GroupAvatarDownloadJob(server, roomToken, openGroup.imageId))
|
||||
}
|
||||
else if (
|
||||
pollInfo.details != null &&
|
||||
pollInfo.details.imageId == null &&
|
||||
existingOpenGroup?.imageId != null
|
||||
) {
|
||||
storage.removeProfilePicture(dbGroupId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun startIfNeeded() {
|
||||
if (hasStarted) { return }
|
||||
hasStarted = true
|
||||
runId = UUID.randomUUID()
|
||||
future = executorService?.schedule(::poll, 0, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
|
||||
@@ -57,6 +140,7 @@ class OpenGroupPoller(private val server: String, private val executorService: S
|
||||
}
|
||||
|
||||
fun poll(isPostCapabilitiesRetry: Boolean = false): Promise<Unit, Exception> {
|
||||
val currentRunId = runId
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val rooms = storage.getAllOpenGroups().values.filter { it.server == server }.map { it.room }
|
||||
|
||||
@@ -86,22 +170,30 @@ class OpenGroupPoller(private val server: String, private val executorService: S
|
||||
isCaughtUp = true
|
||||
}
|
||||
}
|
||||
executorService?.schedule(this@OpenGroupPoller::poll, pollInterval, TimeUnit.MILLISECONDS)
|
||||
|
||||
// Only poll again if it's the same poller run
|
||||
if (currentRunId == runId) {
|
||||
future = executorService?.schedule(this@OpenGroupPoller::poll, pollInterval, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}.fail {
|
||||
updateCapabilitiesIfNeeded(isPostCapabilitiesRetry, it)
|
||||
updateCapabilitiesIfNeeded(isPostCapabilitiesRetry, currentRunId, it)
|
||||
}.map { }
|
||||
}
|
||||
|
||||
private fun updateCapabilitiesIfNeeded(isPostCapabilitiesRetry: Boolean, exception: Exception) {
|
||||
private fun updateCapabilitiesIfNeeded(isPostCapabilitiesRetry: Boolean, currentRunId: UUID, exception: Exception) {
|
||||
if (exception is OnionRequestAPI.HTTPRequestFailedBlindingRequiredException) {
|
||||
if (!isPostCapabilitiesRetry) {
|
||||
OpenGroupApi.getCapabilities(server).map {
|
||||
handleCapabilities(server, it)
|
||||
}
|
||||
executorService?.schedule({ poll(isPostCapabilitiesRetry = true) }, pollInterval, TimeUnit.MILLISECONDS)
|
||||
|
||||
// Only poll again if it's the same poller run
|
||||
if (currentRunId == runId) {
|
||||
future = executorService?.schedule({ poll(isPostCapabilitiesRetry = true) }, pollInterval, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
executorService?.schedule(this@OpenGroupPoller::poll, pollInterval, TimeUnit.MILLISECONDS)
|
||||
} else if (currentRunId == runId) {
|
||||
future = executorService?.schedule(this@OpenGroupPoller::poll, pollInterval, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,82 +202,6 @@ class OpenGroupPoller(private val server: String, private val executorService: S
|
||||
storage.setServerCapabilities(server, capabilities.capabilities)
|
||||
}
|
||||
|
||||
private fun handleRoomPollInfo(
|
||||
server: String,
|
||||
roomToken: String,
|
||||
pollInfo: OpenGroupApi.RoomPollInfo
|
||||
) {
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val groupId = "$server.$roomToken"
|
||||
val dbGroupId = GroupUtil.getEncodedOpenGroupID(groupId.toByteArray())
|
||||
|
||||
val existingOpenGroup = storage.getOpenGroup(roomToken, server)
|
||||
val publicKey = existingOpenGroup?.publicKey ?: return
|
||||
val openGroup = OpenGroup(
|
||||
server = server,
|
||||
room = pollInfo.token,
|
||||
name = if (pollInfo.details != null) { pollInfo.details.name } else { existingOpenGroup.name },
|
||||
publicKey = publicKey,
|
||||
imageId = if (pollInfo.details != null) { pollInfo.details.imageId } else { existingOpenGroup.imageId },
|
||||
canWrite = pollInfo.write,
|
||||
infoUpdates = if (pollInfo.details != null) { pollInfo.details.infoUpdates } else { existingOpenGroup.infoUpdates }
|
||||
)
|
||||
// - Open Group changes
|
||||
storage.updateOpenGroup(openGroup)
|
||||
|
||||
// - User Count
|
||||
storage.setUserCount(roomToken, server, pollInfo.activeUsers)
|
||||
|
||||
// - Moderators
|
||||
pollInfo.details?.moderators?.let { moderatorList ->
|
||||
storage.setGroupMemberRoles(moderatorList.map {
|
||||
GroupMember(groupId, it, GroupMemberRole.MODERATOR)
|
||||
})
|
||||
}
|
||||
pollInfo.details?.hiddenModerators?.let { moderatorList ->
|
||||
storage.setGroupMemberRoles(moderatorList.map {
|
||||
GroupMember(groupId, it, GroupMemberRole.HIDDEN_MODERATOR)
|
||||
})
|
||||
}
|
||||
// - Admins
|
||||
pollInfo.details?.admins?.let { moderatorList ->
|
||||
storage.setGroupMemberRoles(moderatorList.map {
|
||||
GroupMember(groupId, it, GroupMemberRole.ADMIN)
|
||||
})
|
||||
}
|
||||
pollInfo.details?.hiddenAdmins?.let { moderatorList ->
|
||||
storage.setGroupMemberRoles(moderatorList.map {
|
||||
GroupMember(groupId, it, GroupMemberRole.HIDDEN_ADMIN)
|
||||
})
|
||||
}
|
||||
|
||||
// Update the group avatar
|
||||
if (
|
||||
(
|
||||
pollInfo.details != null &&
|
||||
pollInfo.details.imageId != null && (
|
||||
pollInfo.details.imageId != existingOpenGroup.imageId ||
|
||||
!storage.hasDownloadedProfilePicture(dbGroupId)
|
||||
) &&
|
||||
storage.getGroupAvatarDownloadJob(openGroup.server, openGroup.room, pollInfo.details.imageId) == null
|
||||
) || (
|
||||
pollInfo.details == null &&
|
||||
existingOpenGroup.imageId != null &&
|
||||
!storage.hasDownloadedProfilePicture(dbGroupId) &&
|
||||
storage.getGroupAvatarDownloadJob(openGroup.server, openGroup.room, existingOpenGroup.imageId) == null
|
||||
)
|
||||
) {
|
||||
JobQueue.shared.add(GroupAvatarDownloadJob(server, roomToken, existingOpenGroup.imageId))
|
||||
}
|
||||
else if (
|
||||
pollInfo.details != null &&
|
||||
pollInfo.details.imageId == null &&
|
||||
existingOpenGroup.imageId != null
|
||||
) {
|
||||
storage.removeProfilePicture(dbGroupId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleMessages(
|
||||
server: String,
|
||||
roomToken: String,
|
||||
|
Reference in New Issue
Block a user