diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt index bdda6e388f..ff46e36e6a 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt @@ -18,7 +18,7 @@ class LocationMessages(val app: TelegramApplication) { private var bufferedMessages = emptyList() - private var lastLocationPoints = mutableMapOf() + private var lastLocationPoints = mutableListOf() private val dbHelper: SQLiteHelper @@ -85,30 +85,39 @@ class LocationMessages(val app: TelegramApplication) { } fun addNewLocationMessage(message: TdApi.Message) { - log.debug("addNewLocationMessage ${message.id}") + log.debug("try addNewLocationMessage ${message.id}") val type = OsmandLocationUtils.getMessageType(message) + val senderId = OsmandLocationUtils.getSenderMessageId(message) val content = OsmandLocationUtils.parseMessageContent(message, app.telegramHelper) - val deviceName = if (content is OsmandLocationUtils.MessageOsmAndBotLocation) content.deviceName else "" - val newItem = LocationHistoryPoint(OsmandLocationUtils.getSenderMessageId(message), message.chatId, type, deviceName) - val previousMessageLatLon = lastLocationPoints[newItem] - val locationMessage = OsmandLocationUtils.createLocationMessage(message, content, previousMessageLatLon) - if (locationMessage != null) { - dbHelper.addLocationMessage(locationMessage) - lastLocationPoints[newItem] = LatLon(locationMessage.lat, locationMessage.lon) + if (content != null) { + val deviceName = if (content is OsmandLocationUtils.MessageOsmAndBotLocation) content.deviceName else "" + val previousLocationMessage = lastLocationPoints.sortedBy { it.time }.firstOrNull { + it.userId == senderId && it.chatId == message.chatId && it.deviceName == deviceName && it.type == type + } + if (previousLocationMessage == null || content.lastUpdated * 1000L > previousLocationMessage.time) { + log.debug("addNewLocationMessage passed ${message.id}") + val previousMessageLatLon = if (previousLocationMessage != null) LatLon(previousLocationMessage.lat, previousLocationMessage.lon) else null + val locationMessage = OsmandLocationUtils.createLocationMessage(message, content, previousMessageLatLon) + if (locationMessage != null) { + dbHelper.addLocationMessage(locationMessage) + lastLocationPoints.remove(previousLocationMessage) + lastLocationPoints.add(locationMessage) + } + } } } fun addMyLocationMessage(loc: Location) { log.debug("addMyLocationMessage") val currentUserId = app.telegramHelper.getCurrentUserId() - val newItem = LocationHistoryPoint(currentUserId, 0, LocationMessages.TYPE_MY_LOCATION, "") - val previousMessageLatLon = lastLocationPoints[newItem] - val distance = if (previousMessageLatLon != null) { MapUtils.getDistance(previousMessageLatLon, loc.latitude, loc.longitude) } else 0.0 + val previousLocationMessage = lastLocationPoints.sortedBy { it.time }.firstOrNull { it.userId == currentUserId && it.type == TYPE_MY_LOCATION } + val distance = if (previousLocationMessage != null) MapUtils.getDistance(previousLocationMessage.lat, previousLocationMessage.lon, loc.latitude, loc.longitude) else 0.0 val message = LocationMessages.LocationMessage(currentUserId, 0, loc.latitude, loc.longitude, loc.altitude, loc.speed.toDouble(), loc.accuracy.toDouble(), loc.bearing.toDouble(), loc.time, TYPE_MY_LOCATION, 0, distance, "") dbHelper.addLocationMessage(message) - lastLocationPoints[newItem] = LatLon(message.lat, message.lon) + lastLocationPoints.remove(previousLocationMessage) + lastLocationPoints.add(message) } fun clearBufferedMessages() { @@ -291,21 +300,14 @@ class LocationMessages(val app: TelegramApplication) { return res } - internal fun getLastMessages(): MutableMap { - val res = mutableMapOf() - readableDatabase?.rawQuery("$TIMELINE_TABLE_SELECT_HISTORY_POINTS GROUP BY $COL_USER_ID, $COL_CHAT_ID, $COL_DEVICE_NAME, $COL_TYPE", null)?.apply { + internal fun getLastMessages(): MutableList { + val res = arrayListOf() + readableDatabase?.rawQuery("$TIMELINE_TABLE_SELECT_LAST_LOCATIONS GROUP BY $COL_USER_ID, $COL_CHAT_ID, $COL_DEVICE_NAME, $COL_TYPE", null)?.apply { if (moveToFirst()) { do { - val userId = getInt(0) - val chatId = getLong(1) - val lat = getDouble(2) - val lon = getDouble(3) - val time = getLong(4) - val type = getInt(5) - val deviceName = getString(6) - val locationHistoryPoint = LocationHistoryPoint(userId, chatId, type, deviceName) - res[locationHistoryPoint] = LatLon(lat, lon) - log.debug("$locationHistoryPoint time: $time coords: $lat, $lon") + val locationMessage = readLocationMessage(this@apply) + res.add(locationMessage) + log.debug("add last location message - $locationMessage") } while (moveToNext()) } close() @@ -403,8 +405,8 @@ class LocationMessages(val app: TelegramApplication) { private const val TIMELINE_TABLE_SELECT = "SELECT $COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_ID, $COL_DISTANCE_FROM_PREV, $COL_DEVICE_NAME FROM $TIMELINE_TABLE_NAME" - private const val TIMELINE_TABLE_SELECT_HISTORY_POINTS = - "SELECT $COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_TIME, $COL_TYPE, $COL_DEVICE_NAME, MAX($COL_TIME) FROM $TIMELINE_TABLE_NAME" + private const val TIMELINE_TABLE_SELECT_LAST_LOCATIONS = + "SELECT $COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_ID, $COL_DISTANCE_FROM_PREV, $COL_DEVICE_NAME, MAX($COL_TIME) FROM $TIMELINE_TABLE_NAME" private const val TIMELINE_TABLE_CLEAR = "DELETE FROM $TIMELINE_TABLE_NAME" @@ -505,36 +507,6 @@ class LocationMessages(val app: TelegramApplication) { } } - data class LocationHistoryPoint( - val userId: Int, - val chatId: Long, - val type: Int, - val deviceName: String - ) { - - override fun equals(other: Any?): Boolean { - if (other == null) { - return false - } - if (other !is LocationHistoryPoint) { - return false - } - val o = other as LocationHistoryPoint? - return this.userId == o!!.userId && this.chatId == o.chatId && this.type == o.type && this.deviceName == o.deviceName - } - - override fun hashCode(): Int { - val prime = 31 - var result = 1 - result = prime * result + userId.hashCode() - result = prime * result + chatId.hashCode() - result = prime * result + type.hashCode() - result = prime * result + deviceName.hashCode() - return result - } - } - - companion object { const val TYPE_MAP = 0 diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt index c36e7688a9..2b59ee14b1 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt @@ -574,7 +574,7 @@ class TelegramHelper private constructor() { fun scanChatsHistory() { log.debug("scanChatsHistory: chatList: ${chatList.size}") chatList.forEach { - scanChatHistory(it.chatId, 0, 0, 100) + scanChatHistory(it.chatId, 0, 0, 100, mutableListOf()) } } @@ -583,9 +583,9 @@ class TelegramHelper private constructor() { fromMessageId: Long, offset: Int, limit: Int, - onlyLocal: Boolean = false + locations: MutableList ) { - client?.send(TdApi.GetChatHistory(chatId, fromMessageId, offset, limit, onlyLocal)) { obj -> + client?.send(TdApi.GetChatHistory(chatId, fromMessageId, offset, limit, false)) { obj -> when (obj.constructor) { TdApi.Error.CONSTRUCTOR -> { val error = obj as TdApi.Error @@ -597,23 +597,35 @@ class TelegramHelper private constructor() { val messages = (obj as TdApi.Messages).messages log.debug("scanChatHistory: chatId: $chatId fromMessageId: $fromMessageId size: ${messages.size}") if (messages.isNotEmpty()) { - messages.forEach { - addNewMessage(it) - } + locations.addAll(messages.filter { it.isAppropriate() && !it.isOutgoing }) val lastMessage = messages.last() val currentTime = System.currentTimeMillis() / 1000 - if (currentTime-Math.max(lastMessage.date, lastMessage.editDate) < MAX_LOCATION_MESSAGE_HISTORY_SCAN_SEC) { - scanChatHistory(chatId, lastMessage.id, 0, 100) + if (currentTime - Math.max(lastMessage.date, lastMessage.editDate) < MAX_LOCATION_MESSAGE_HISTORY_SCAN_SEC) { + scanChatHistory(chatId, lastMessage.id, 0, 100, locations) log.debug("scanChatHistory searchMessageId: ${lastMessage.id}") } else { log.debug("scanChatHistory finishForChat: $chatId") + processScannedLocationsForChat(chatId, locations) } + } else { + log.debug("scanChatHistory finishForChat: $chatId") + processScannedLocationsForChat(chatId, locations) } } } } } + private fun processScannedLocationsForChat(chatId: Long, locations: MutableList) { + if (locations.isNotEmpty()) { + locations.sortBy { message -> OsmandLocationUtils.getLastUpdatedTime(message) } + updateLastMessage(locations.last()) + incomingMessagesListeners.forEach { + it.onReceiveChatLocationMessages(chatId, *locations.toTypedArray()) + } + } + } + private fun requestUser(id: Int) { client?.send(TdApi.GetUser(id)) { obj -> when (obj.constructor) { @@ -674,16 +686,7 @@ class TelegramHelper private constructor() { if (message.isOutgoing && !fromBot && !viaBot) { return } - removeOldMessages(message, fromBot, viaBot) - val oldMessage = usersLocationMessages.values.firstOrNull { - OsmandLocationUtils.getSenderMessageId(it) == OsmandLocationUtils.getSenderMessageId(message) && it.chatId == message.chatId - && OsmandLocationUtils.getOsmAndBotDeviceName(it) == OsmandLocationUtils.getOsmAndBotDeviceName(message) - } - val hasNewerMessage = oldMessage != null && (Math.max(message.editDate, message.date) < Math.max(oldMessage.editDate, oldMessage.date)) - if (!hasNewerMessage) { - message.content = OsmandLocationUtils.parseMessageContent(message, this) - usersLocationMessages[message.id] = message - } + updateLastMessage(message) if (message.isOutgoing) { if (fromBot||viaBot) { outgoingMessagesListeners.forEach { @@ -698,24 +701,17 @@ class TelegramHelper private constructor() { } } - private fun removeOldMessages(newMessage: TdApi.Message, fromBot: Boolean, viaBot: Boolean) { - val iterator = usersLocationMessages.entries.iterator() - while (iterator.hasNext()) { - val message = iterator.next().value - if (newMessage.chatId == message.chatId) { - val sameSender = OsmandLocationUtils.getSenderMessageId(newMessage) == OsmandLocationUtils.getSenderMessageId(message) - val viaSameBot = newMessage.viaBotUserId == message.viaBotUserId - if (fromBot || viaBot) { - if ((fromBot && sameSender) || (viaBot && viaSameBot)) { - val newDeviceName = OsmandLocationUtils.getOsmAndBotDeviceName(newMessage) - val contDeviceName = OsmandLocationUtils.getOsmAndBotDeviceName(newMessage) - if (newDeviceName == contDeviceName) { - iterator.remove() - } - } - } else if (sameSender && Math.max(newMessage.editDate, newMessage.date) >= Math.max(message.editDate, message.date)) { - iterator.remove() - } + private fun updateLastMessage(message: TdApi.Message) { + val oldMessage = usersLocationMessages.values.firstOrNull { + OsmandLocationUtils.getSenderMessageId(it) == OsmandLocationUtils.getSenderMessageId(message) + && it.chatId == message.chatId && message.viaBotUserId == message.viaBotUserId + && OsmandLocationUtils.getOsmAndBotDeviceName(it) == OsmandLocationUtils.getOsmAndBotDeviceName(message) + } + if (oldMessage == null || (Math.max(message.editDate, message.date) > Math.max(oldMessage.editDate, oldMessage.date))) { + message.content = OsmandLocationUtils.parseMessageContent(message, this) + usersLocationMessages[message.id] = message + oldMessage?.let { + usersLocationMessages.remove(it.id) } } }