diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt index 500d3e1f0b..dcb70ac314 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt @@ -24,6 +24,8 @@ class TelegramHelper private constructor() { private const val CHAT_LIVE_USERS_LIMIT = 100 private const val IGNORED_ERROR_CODE = 406 private const val UPDATE_LIVE_MESSAGES_INTERVAL_SEC = 30L + private const val MESSAGE_ACTIVE_TIME_SEC = 24 * 60 * 60 // 24 hours + private const val OSMAND_BOT_USERNAME = "osmand_bot" private var helper: TelegramHelper? = null @@ -49,7 +51,8 @@ class TelegramHelper private constructor() { private val downloadChatFilesMap = ConcurrentHashMap() private val downloadUserFilesMap = ConcurrentHashMap() - private val usersLiveMessages = ConcurrentHashMap() + // Can contain TdApi.MessageLocation or TdApi.MessageText from osmand_bot + private val usersLocationMessages = ConcurrentHashMap() private val usersFullInfo = ConcurrentHashMap() private val basicGroupsFullInfo = ConcurrentHashMap() @@ -102,18 +105,13 @@ class TelegramHelper private constructor() { return users[id] } - fun getUserMessage(user: TdApi.User): TdApi.Message? { - for (message in usersLiveMessages.values) { - if (message.senderUserId == user.id) { - return message - } - } - return null - } + fun getUserMessage(user: TdApi.User) = usersLocationMessages[user.id] + + fun getMessageById(id: Long) = usersLocationMessages.values.firstOrNull { it.id == id } fun getChatMessages(chatTitle: String): List { val res = mutableListOf() - for (message in usersLiveMessages.values) { + for (message in usersLocationMessages.values) { val title = chats[message.chatId]?.title if (title == chatTitle) { res.add(message) @@ -123,12 +121,12 @@ class TelegramHelper private constructor() { } fun getMessages(): List { - return usersLiveMessages.values.toList() + return usersLocationMessages.values.toList() } fun getMessagesByChatIds(): Map> { val res = mutableMapOf>() - for (message in usersLiveMessages.values) { + for (message in usersLocationMessages.values) { var messages = res[message.chatId] if (messages != null) { messages.add(message) @@ -356,41 +354,31 @@ class TelegramHelper private constructor() { } } updateChatTitles() - getChatRecentLocationMessages(chatTitles.keys) listener?.onTelegramChatsRead() } - private fun getChatRecentLocationMessages(chatTitles: Set) { - if (haveAuthorization) { - for (chatTitle in chatTitles) { - val chatId = this.chatTitles[chatTitle] - if (chatId != null) { - val chat = chats[chatId] - if (chat == null || isChannel(chat)) { - continue - } - client?.send(TdApi.SearchChatRecentLocationMessages(chatId, CHAT_LIVE_USERS_LIMIT)) { obj -> - when (obj.constructor) { - TdApi.Error.CONSTRUCTOR -> { - val error = obj as TdApi.Error - val code = error.code - if (code != IGNORED_ERROR_CODE && code != 400) { - listener?.onTelegramError(code, error.message) - } - } - TdApi.Messages.CONSTRUCTOR -> { - val messages = (obj as TdApi.Messages).messages - for (message in messages) { - if (!message.isOutgoing && message.content is TdApi.MessageLocation) { - usersLiveMessages[message.id] = message - } - } - incomingMessagesListeners.forEach { it.onReceiveChatLocationMessages(chatTitle, *messages) } - } - else -> listener?.onTelegramError(-1, "Receive wrong response from TDLib: $obj") - } + private fun requestMessage(chatId: Long, messageId: Long, onComplete: (TdApi.Message) -> Unit) { + client?.send(TdApi.GetMessage(chatId, messageId)) { obj -> + when (obj.constructor) { + TdApi.Error.CONSTRUCTOR -> { + val error = obj as TdApi.Error + if (error.code != IGNORED_ERROR_CODE) { + listener?.onTelegramError(error.code, error.message) } } + TdApi.Message.CONSTRUCTOR -> onComplete(obj as TdApi.Message) + } + } + } + + private fun addNewMessage(message: TdApi.Message) { + if (message.isAppropriate()) { + usersLocationMessages[message.senderUserId] = message + val chatTitle = chats[message.chatId]?.title + if (chatTitle != null) { + incomingMessagesListeners.forEach { + it.onReceiveChatLocationMessages(chatTitle, message) + } } } } @@ -606,6 +594,30 @@ class TelegramHelper private constructor() { listener?.onTelegramStatusChanged(prevAuthState, newAuthState) } + private fun TdApi.Message.isAppropriate(): Boolean { + if (isOutgoing || isChannelPost) { + return false + } + val lastEdited = Math.max(date, editDate) + if (TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) - lastEdited > MESSAGE_ACTIVE_TIME_SEC) { + return false + } + val content = content + return when (content) { + is TdApi.MessageLocation -> true + is TdApi.MessageText -> { + if (content.text.text.startsWith("{")) { + // TODO: get user from library if null + if (users[senderUserId]?.username == OSMAND_BOT_USERNAME) { + return true + } + } + false + } + else -> false + } + } + class OrderedChat internal constructor(internal val order: Long, internal val chatId: Long, internal val isChannel: Boolean) : Comparable { override fun compareTo(other: OrderedChat): Int { @@ -789,8 +801,12 @@ class TelegramHelper private constructor() { } TdApi.UpdateMessageContent.CONSTRUCTOR -> { val updateMessageContent = obj as TdApi.UpdateMessageContent - val message = usersLiveMessages[updateMessageContent.messageId] - if (message != null && !message.isOutgoing) { + val message = getMessageById(updateMessageContent.messageId) + if (message == null) { + updateMessageContent.apply { + requestMessage(chatId, messageId, this@TelegramHelper::addNewMessage) + } + } else { synchronized(message) { message.content = updateMessageContent.newContent } @@ -800,21 +816,10 @@ class TelegramHelper private constructor() { it.onReceiveChatLocationMessages(chatTitle, message) } } - } } TdApi.UpdateNewMessage.CONSTRUCTOR -> { - val updateNewMessage = obj as TdApi.UpdateNewMessage - val message = updateNewMessage.message - if (!message.isOutgoing && message.content is TdApi.MessageLocation) { - usersLiveMessages[message.id] = message - val chatTitle = chats[message.chatId]?.title - if (chatTitle != null) { - incomingMessagesListeners.forEach { - it.onReceiveChatLocationMessages(chatTitle, message) - } - } - } + addNewMessage((obj as TdApi.UpdateNewMessage).message) } TdApi.UpdateMessageMentionRead.CONSTRUCTOR -> { val updateChat = obj as TdApi.UpdateMessageMentionRead