fix: harden captcha and long poll parsing
This commit is contained in:
@@ -21,8 +21,8 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
internal class LongPollEventParser(
|
||||
private val coroutineScope: CoroutineScope,
|
||||
@@ -35,7 +35,7 @@ internal class LongPollEventParser(
|
||||
val eventId = event.first().asInt()
|
||||
|
||||
when (val eventType = ApiEvent.parseOrNull(eventId)) {
|
||||
null -> Log.d("LongPollEventParser", "parseNextUpdate: unknownEvent: $event")
|
||||
null -> Unit
|
||||
|
||||
ApiEvent.MESSAGE_SET_FLAGS -> parseMessageSetFlags(eventType, event)
|
||||
ApiEvent.MESSAGE_CLEAR_FLAGS -> parseMessageClearFlags(eventType, event)
|
||||
@@ -62,8 +62,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseMessageSetFlags(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val cmId = event[1].asLong()
|
||||
val flags = event[2].asInt()
|
||||
val peerId = event[3].asLong()
|
||||
@@ -128,8 +126,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseMessageClearFlags(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val cmId = event[1].asLong()
|
||||
val flags = event[2].asInt()
|
||||
val peerId = event[3].asLong()
|
||||
@@ -192,8 +188,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseMessageNew(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val cmId = event[1].asLong()
|
||||
val peerId = event[4].asLong()
|
||||
|
||||
@@ -223,8 +217,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseMessageEdit(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val cmId = event[1].asLong()
|
||||
val peerId = event[3].asLong()
|
||||
|
||||
@@ -239,40 +231,28 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseMessageReadIncoming(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
val peerId = event[1].asLong()
|
||||
val cmId = event[2].asLong()
|
||||
val unreadCount = event[3].asInt()
|
||||
|
||||
dispatch(
|
||||
LongPollEvent.INCOMING_MESSAGE_READ,
|
||||
LongPollParsedEvent.IncomingMessageRead(
|
||||
peerId = peerId,
|
||||
cmId = cmId,
|
||||
unreadCount = unreadCount
|
||||
dispatchMessageRead(
|
||||
longPollEvent = LongPollEvent.INCOMING_MESSAGE_READ,
|
||||
parsedEvent = LongPollParsedEvent.IncomingMessageRead(
|
||||
peerId = event[1].asLong(),
|
||||
cmId = event[2].asLong(),
|
||||
unreadCount = event[3].asInt()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseMessageReadOutgoing(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
val peerId = event[1].asLong()
|
||||
val cmId = event[2].asLong()
|
||||
val unreadCount = event[3].asInt()
|
||||
|
||||
dispatch(
|
||||
LongPollEvent.OUTGOING_MESSAGE_READ,
|
||||
LongPollParsedEvent.OutgoingMessageRead(
|
||||
peerId = peerId,
|
||||
cmId = cmId,
|
||||
unreadCount = unreadCount
|
||||
dispatchMessageRead(
|
||||
longPollEvent = LongPollEvent.OUTGOING_MESSAGE_READ,
|
||||
parsedEvent = LongPollParsedEvent.OutgoingMessageRead(
|
||||
peerId = event[1].asLong(),
|
||||
cmId = event[2].asLong(),
|
||||
unreadCount = event[3].asInt()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseChatClearFlags(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val peerId = event[1].asLong()
|
||||
val flags = event[2].asInt()
|
||||
|
||||
@@ -284,23 +264,11 @@ internal class LongPollEventParser(
|
||||
parsedFlags.forEach { flag ->
|
||||
when (flag) {
|
||||
ConvoFlags.ARCHIVED -> {
|
||||
val convo = loadConvo(
|
||||
handleArchivedChat(
|
||||
peerId = peerId,
|
||||
extended = true,
|
||||
fields = VkConstants.ALL_FIELDS
|
||||
) ?: return@forEach
|
||||
|
||||
val message = loadMessage(
|
||||
peerId = peerId,
|
||||
cmId = convo.lastCmId
|
||||
archived = false,
|
||||
eventsToSend = eventsToSend
|
||||
)
|
||||
|
||||
val eventToSend = LongPollParsedEvent.ChatArchived(
|
||||
convo = convo.copy(lastMessage = message),
|
||||
archived = false
|
||||
)
|
||||
eventsToSend += eventToSend
|
||||
dispatch(LongPollEvent.CHAT_ARCHIVED, eventToSend)
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
@@ -312,8 +280,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseChatSetFlags(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val peerId = event[1].asLong()
|
||||
val flags = event[2].asInt()
|
||||
|
||||
@@ -325,23 +291,11 @@ internal class LongPollEventParser(
|
||||
parsedFlags.forEach { flag ->
|
||||
when (flag) {
|
||||
ConvoFlags.ARCHIVED -> {
|
||||
val convo = loadConvo(
|
||||
handleArchivedChat(
|
||||
peerId = peerId,
|
||||
extended = true,
|
||||
fields = VkConstants.ALL_FIELDS
|
||||
) ?: return@forEach
|
||||
|
||||
val message = loadMessage(
|
||||
peerId = peerId,
|
||||
cmId = convo.lastCmId
|
||||
archived = true,
|
||||
eventsToSend = eventsToSend
|
||||
)
|
||||
|
||||
val eventToSend = LongPollParsedEvent.ChatArchived(
|
||||
convo = convo.copy(lastMessage = message),
|
||||
archived = true
|
||||
)
|
||||
eventsToSend += eventToSend
|
||||
dispatch(LongPollEvent.CHAT_ARCHIVED, eventToSend)
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
@@ -353,8 +307,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseMessagesDeleted(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val peerId = event[1].asLong()
|
||||
val cmId = event[2].asLong()
|
||||
|
||||
@@ -368,8 +320,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseChatMajorChanged(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val peerId = event[1].asLong()
|
||||
val majorId = event[2].asInt()
|
||||
|
||||
@@ -383,8 +333,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseChatMinorChanged(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val peerId = event[1].asLong()
|
||||
val minorId = event[2].asInt()
|
||||
|
||||
@@ -398,8 +346,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseInteraction(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType: $event")
|
||||
|
||||
val interactionType = when (eventType) {
|
||||
ApiEvent.TYPING -> InteractionType.Typing
|
||||
ApiEvent.AUDIO_MESSAGE_RECORDING -> InteractionType.VoiceMessage
|
||||
@@ -438,8 +384,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseUnreadCounterUpdate(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType $event")
|
||||
|
||||
val unreadCount = event[1].asInt()
|
||||
val unreadUnmutedCount = event[2].asInt()
|
||||
val showOnlyMuted = event[3].asInt() == 1
|
||||
@@ -463,8 +407,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseMessageUpdated(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType $event")
|
||||
|
||||
val cmId = event[1].asLong()
|
||||
val peerId = event[4].asLong()
|
||||
|
||||
@@ -479,8 +421,6 @@ internal class LongPollEventParser(
|
||||
}
|
||||
|
||||
private fun parseMessageCacheClear(eventType: ApiEvent, event: List<Any>) {
|
||||
Log.d("LongPollEventParser", "$eventType $event")
|
||||
|
||||
val messageId = event[1].asLong()
|
||||
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
@@ -497,10 +437,10 @@ internal class LongPollEventParser(
|
||||
peerId: Long? = null,
|
||||
cmId: Long? = null,
|
||||
messageId: Long? = null
|
||||
): VkMessage? = suspendCoroutine { continuation ->
|
||||
): VkMessage? = suspendCancellableCoroutine { continuation ->
|
||||
require((peerId != null && cmId != null) || messageId != null)
|
||||
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
val job = coroutineScope.launch(Dispatchers.IO) {
|
||||
messagesUseCase.getById(
|
||||
peerCmIds = null,
|
||||
peerId = peerId,
|
||||
@@ -525,14 +465,18 @@ internal class LongPollEventParser(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
continuation.invokeOnCancellation {
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadConvo(
|
||||
peerId: Long,
|
||||
extended: Boolean = false,
|
||||
fields: String? = null
|
||||
): VkConvo? = suspendCoroutine { continuation ->
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
): VkConvo? = suspendCancellableCoroutine { continuation ->
|
||||
val job = coroutineScope.launch(Dispatchers.IO) {
|
||||
convoUseCase.getById(
|
||||
peerIds = listOf(peerId),
|
||||
extended = extended,
|
||||
@@ -554,5 +498,40 @@ internal class LongPollEventParser(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
continuation.invokeOnCancellation {
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleArchivedChat(
|
||||
peerId: Long,
|
||||
archived: Boolean,
|
||||
eventsToSend: MutableList<LongPollParsedEvent>
|
||||
) {
|
||||
val convo = loadConvo(
|
||||
peerId = peerId,
|
||||
extended = true,
|
||||
fields = VkConstants.ALL_FIELDS
|
||||
) ?: return
|
||||
|
||||
val message = loadMessage(
|
||||
peerId = peerId,
|
||||
cmId = convo.lastCmId
|
||||
)
|
||||
|
||||
val eventToSend = LongPollParsedEvent.ChatArchived(
|
||||
convo = convo.copy(lastMessage = message),
|
||||
archived = archived
|
||||
)
|
||||
eventsToSend += eventToSend
|
||||
dispatch(LongPollEvent.CHAT_ARCHIVED, eventToSend)
|
||||
}
|
||||
|
||||
private fun dispatchMessageRead(
|
||||
longPollEvent: LongPollEvent,
|
||||
parsedEvent: LongPollParsedEvent
|
||||
) {
|
||||
dispatch(longPollEvent, parsedEvent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,22 +22,35 @@ class OAuthUseCaseImpl(
|
||||
): Flow<State<AuthInfo>> = flow {
|
||||
emit(State.Loading)
|
||||
|
||||
val newState = oAuthRepository.auth(
|
||||
val newState = when (val authResult = oAuthRepository.auth(
|
||||
login = login,
|
||||
password = password,
|
||||
forceSms = forceSms,
|
||||
validationCode = validationCode,
|
||||
captchaSid = captchaSid,
|
||||
captchaKey = captchaKey
|
||||
).asState(
|
||||
successMapper = {
|
||||
AuthInfo(
|
||||
userId = it.userId!!,
|
||||
accessToken = it.accessToken!!,
|
||||
validationHash = it.validationHash!!
|
||||
)
|
||||
)) {
|
||||
is com.slack.eithernet.ApiResult.Success -> {
|
||||
val value = authResult.value
|
||||
val userId = value.userId
|
||||
val accessToken = value.accessToken
|
||||
val validationHash = value.validationHash
|
||||
|
||||
if (userId == null || accessToken == null || validationHash == null) {
|
||||
State.Error.InternalError
|
||||
} else {
|
||||
State.Success(
|
||||
AuthInfo(
|
||||
userId = userId,
|
||||
accessToken = accessToken,
|
||||
validationHash = validationHash
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
else -> authResult.asState()
|
||||
}
|
||||
|
||||
emit(newState)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user