Merge pull request #6556 from osmandapp/TelegramImprovements
Telegram scan improvements
This commit is contained in:
commit
13af951629
2 changed files with 62 additions and 94 deletions
|
@ -18,7 +18,7 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
|
|
||||||
private var bufferedMessages = emptyList<BufferMessage>()
|
private var bufferedMessages = emptyList<BufferMessage>()
|
||||||
|
|
||||||
private var lastLocationPoints = mutableMapOf<LocationHistoryPoint, LatLon>()
|
private var lastLocationPoints = mutableListOf<LocationMessage>()
|
||||||
|
|
||||||
private val dbHelper: SQLiteHelper
|
private val dbHelper: SQLiteHelper
|
||||||
|
|
||||||
|
@ -85,30 +85,39 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addNewLocationMessage(message: TdApi.Message) {
|
fun addNewLocationMessage(message: TdApi.Message) {
|
||||||
log.debug("addNewLocationMessage ${message.id}")
|
log.debug("try addNewLocationMessage ${message.id}")
|
||||||
val type = OsmandLocationUtils.getMessageType(message)
|
val type = OsmandLocationUtils.getMessageType(message)
|
||||||
|
val senderId = OsmandLocationUtils.getSenderMessageId(message)
|
||||||
val content = OsmandLocationUtils.parseMessageContent(message, app.telegramHelper)
|
val content = OsmandLocationUtils.parseMessageContent(message, app.telegramHelper)
|
||||||
val deviceName = if (content is OsmandLocationUtils.MessageOsmAndBotLocation) content.deviceName else ""
|
if (content != null) {
|
||||||
val newItem = LocationHistoryPoint(OsmandLocationUtils.getSenderMessageId(message), message.chatId, type, deviceName)
|
val deviceName = if (content is OsmandLocationUtils.MessageOsmAndBotLocation) content.deviceName else ""
|
||||||
val previousMessageLatLon = lastLocationPoints[newItem]
|
val previousLocationMessage = lastLocationPoints.sortedBy { it.time }.firstOrNull {
|
||||||
val locationMessage = OsmandLocationUtils.createLocationMessage(message, content, previousMessageLatLon)
|
it.userId == senderId && it.chatId == message.chatId && it.deviceName == deviceName && it.type == type
|
||||||
if (locationMessage != null) {
|
}
|
||||||
dbHelper.addLocationMessage(locationMessage)
|
if (previousLocationMessage == null || content.lastUpdated * 1000L > previousLocationMessage.time) {
|
||||||
lastLocationPoints[newItem] = LatLon(locationMessage.lat, locationMessage.lon)
|
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) {
|
fun addMyLocationMessage(loc: Location) {
|
||||||
log.debug("addMyLocationMessage")
|
log.debug("addMyLocationMessage")
|
||||||
val currentUserId = app.telegramHelper.getCurrentUserId()
|
val currentUserId = app.telegramHelper.getCurrentUserId()
|
||||||
val newItem = LocationHistoryPoint(currentUserId, 0, LocationMessages.TYPE_MY_LOCATION, "")
|
val previousLocationMessage = lastLocationPoints.sortedBy { it.time }.firstOrNull { it.userId == currentUserId && it.type == TYPE_MY_LOCATION }
|
||||||
val previousMessageLatLon = lastLocationPoints[newItem]
|
val distance = if (previousLocationMessage != null) MapUtils.getDistance(previousLocationMessage.lat, previousLocationMessage.lon, loc.latitude, loc.longitude) else 0.0
|
||||||
val distance = if (previousMessageLatLon != null) { MapUtils.getDistance(previousMessageLatLon, loc.latitude, loc.longitude) } else 0.0
|
|
||||||
val message = LocationMessages.LocationMessage(currentUserId, 0, loc.latitude, loc.longitude, loc.altitude,
|
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, "")
|
loc.speed.toDouble(), loc.accuracy.toDouble(), loc.bearing.toDouble(), loc.time, TYPE_MY_LOCATION, 0, distance, "")
|
||||||
|
|
||||||
dbHelper.addLocationMessage(message)
|
dbHelper.addLocationMessage(message)
|
||||||
lastLocationPoints[newItem] = LatLon(message.lat, message.lon)
|
lastLocationPoints.remove(previousLocationMessage)
|
||||||
|
lastLocationPoints.add(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearBufferedMessages() {
|
fun clearBufferedMessages() {
|
||||||
|
@ -291,21 +300,14 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getLastMessages(): MutableMap<LocationHistoryPoint, LatLon> {
|
internal fun getLastMessages(): MutableList<LocationMessage> {
|
||||||
val res = mutableMapOf<LocationHistoryPoint, LatLon>()
|
val res = arrayListOf<LocationMessage>()
|
||||||
readableDatabase?.rawQuery("$TIMELINE_TABLE_SELECT_HISTORY_POINTS GROUP BY $COL_USER_ID, $COL_CHAT_ID, $COL_DEVICE_NAME, $COL_TYPE", null)?.apply {
|
readableDatabase?.rawQuery("$TIMELINE_TABLE_SELECT_LAST_LOCATIONS GROUP BY $COL_USER_ID, $COL_CHAT_ID, $COL_DEVICE_NAME, $COL_TYPE", null)?.apply {
|
||||||
if (moveToFirst()) {
|
if (moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
val userId = getInt(0)
|
val locationMessage = readLocationMessage(this@apply)
|
||||||
val chatId = getLong(1)
|
res.add(locationMessage)
|
||||||
val lat = getDouble(2)
|
log.debug("add last location message - $locationMessage")
|
||||||
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")
|
|
||||||
} while (moveToNext())
|
} while (moveToNext())
|
||||||
}
|
}
|
||||||
close()
|
close()
|
||||||
|
@ -403,8 +405,8 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
private const val TIMELINE_TABLE_SELECT =
|
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"
|
"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 =
|
private const val TIMELINE_TABLE_SELECT_LAST_LOCATIONS =
|
||||||
"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"
|
"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"
|
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 {
|
companion object {
|
||||||
|
|
||||||
const val TYPE_MAP = 0
|
const val TYPE_MAP = 0
|
||||||
|
|
|
@ -574,7 +574,7 @@ class TelegramHelper private constructor() {
|
||||||
fun scanChatsHistory() {
|
fun scanChatsHistory() {
|
||||||
log.debug("scanChatsHistory: chatList: ${chatList.size}")
|
log.debug("scanChatsHistory: chatList: ${chatList.size}")
|
||||||
chatList.forEach {
|
chatList.forEach {
|
||||||
scanChatHistory(it.chatId, 0, 0, 100)
|
scanChatHistory(it.chatId, 0, 0, 100, mutableListOf<TdApi.Message>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,9 +583,9 @@ class TelegramHelper private constructor() {
|
||||||
fromMessageId: Long,
|
fromMessageId: Long,
|
||||||
offset: Int,
|
offset: Int,
|
||||||
limit: Int,
|
limit: Int,
|
||||||
onlyLocal: Boolean = false
|
locations: MutableList<TdApi.Message>
|
||||||
) {
|
) {
|
||||||
client?.send(TdApi.GetChatHistory(chatId, fromMessageId, offset, limit, onlyLocal)) { obj ->
|
client?.send(TdApi.GetChatHistory(chatId, fromMessageId, offset, limit, false)) { obj ->
|
||||||
when (obj.constructor) {
|
when (obj.constructor) {
|
||||||
TdApi.Error.CONSTRUCTOR -> {
|
TdApi.Error.CONSTRUCTOR -> {
|
||||||
val error = obj as TdApi.Error
|
val error = obj as TdApi.Error
|
||||||
|
@ -597,23 +597,35 @@ class TelegramHelper private constructor() {
|
||||||
val messages = (obj as TdApi.Messages).messages
|
val messages = (obj as TdApi.Messages).messages
|
||||||
log.debug("scanChatHistory: chatId: $chatId fromMessageId: $fromMessageId size: ${messages.size}")
|
log.debug("scanChatHistory: chatId: $chatId fromMessageId: $fromMessageId size: ${messages.size}")
|
||||||
if (messages.isNotEmpty()) {
|
if (messages.isNotEmpty()) {
|
||||||
messages.forEach {
|
locations.addAll(messages.filter { it.isAppropriate() && !it.isOutgoing })
|
||||||
addNewMessage(it)
|
|
||||||
}
|
|
||||||
val lastMessage = messages.last()
|
val lastMessage = messages.last()
|
||||||
val currentTime = System.currentTimeMillis() / 1000
|
val currentTime = System.currentTimeMillis() / 1000
|
||||||
if (currentTime-Math.max(lastMessage.date, lastMessage.editDate) < MAX_LOCATION_MESSAGE_HISTORY_SCAN_SEC) {
|
if (currentTime - Math.max(lastMessage.date, lastMessage.editDate) < MAX_LOCATION_MESSAGE_HISTORY_SCAN_SEC) {
|
||||||
scanChatHistory(chatId, lastMessage.id, 0, 100)
|
scanChatHistory(chatId, lastMessage.id, 0, 100, locations)
|
||||||
log.debug("scanChatHistory searchMessageId: ${lastMessage.id}")
|
log.debug("scanChatHistory searchMessageId: ${lastMessage.id}")
|
||||||
} else {
|
} else {
|
||||||
log.debug("scanChatHistory finishForChat: $chatId")
|
log.debug("scanChatHistory finishForChat: $chatId")
|
||||||
|
processScannedLocationsForChat(chatId, locations)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.debug("scanChatHistory finishForChat: $chatId")
|
||||||
|
processScannedLocationsForChat(chatId, locations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun processScannedLocationsForChat(chatId: Long, locations: MutableList<TdApi.Message>) {
|
||||||
|
if (locations.isNotEmpty()) {
|
||||||
|
locations.sortBy { message -> OsmandLocationUtils.getLastUpdatedTime(message) }
|
||||||
|
updateLastMessage(locations.last())
|
||||||
|
incomingMessagesListeners.forEach {
|
||||||
|
it.onReceiveChatLocationMessages(chatId, *locations.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun requestUser(id: Int) {
|
private fun requestUser(id: Int) {
|
||||||
client?.send(TdApi.GetUser(id)) { obj ->
|
client?.send(TdApi.GetUser(id)) { obj ->
|
||||||
when (obj.constructor) {
|
when (obj.constructor) {
|
||||||
|
@ -674,16 +686,7 @@ class TelegramHelper private constructor() {
|
||||||
if (message.isOutgoing && !fromBot && !viaBot) {
|
if (message.isOutgoing && !fromBot && !viaBot) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
removeOldMessages(message, fromBot, viaBot)
|
updateLastMessage(message)
|
||||||
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
|
|
||||||
}
|
|
||||||
if (message.isOutgoing) {
|
if (message.isOutgoing) {
|
||||||
if (fromBot||viaBot) {
|
if (fromBot||viaBot) {
|
||||||
outgoingMessagesListeners.forEach {
|
outgoingMessagesListeners.forEach {
|
||||||
|
@ -698,24 +701,17 @@ class TelegramHelper private constructor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeOldMessages(newMessage: TdApi.Message, fromBot: Boolean, viaBot: Boolean) {
|
private fun updateLastMessage(message: TdApi.Message) {
|
||||||
val iterator = usersLocationMessages.entries.iterator()
|
val oldMessage = usersLocationMessages.values.firstOrNull {
|
||||||
while (iterator.hasNext()) {
|
OsmandLocationUtils.getSenderMessageId(it) == OsmandLocationUtils.getSenderMessageId(message)
|
||||||
val message = iterator.next().value
|
&& it.chatId == message.chatId && message.viaBotUserId == message.viaBotUserId
|
||||||
if (newMessage.chatId == message.chatId) {
|
&& OsmandLocationUtils.getOsmAndBotDeviceName(it) == OsmandLocationUtils.getOsmAndBotDeviceName(message)
|
||||||
val sameSender = OsmandLocationUtils.getSenderMessageId(newMessage) == OsmandLocationUtils.getSenderMessageId(message)
|
}
|
||||||
val viaSameBot = newMessage.viaBotUserId == message.viaBotUserId
|
if (oldMessage == null || (Math.max(message.editDate, message.date) > Math.max(oldMessage.editDate, oldMessage.date))) {
|
||||||
if (fromBot || viaBot) {
|
message.content = OsmandLocationUtils.parseMessageContent(message, this)
|
||||||
if ((fromBot && sameSender) || (viaBot && viaSameBot)) {
|
usersLocationMessages[message.id] = message
|
||||||
val newDeviceName = OsmandLocationUtils.getOsmAndBotDeviceName(newMessage)
|
oldMessage?.let {
|
||||||
val contDeviceName = OsmandLocationUtils.getOsmAndBotDeviceName(newMessage)
|
usersLocationMessages.remove(it.id)
|
||||||
if (newDeviceName == contDeviceName) {
|
|
||||||
iterator.remove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (sameSender && Math.max(newMessage.editDate, newMessage.date) >= Math.max(message.editDate, message.date)) {
|
|
||||||
iterator.remove()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue