improve buffer updates

This commit is contained in:
Chumva 2019-01-29 19:03:44 +02:00
parent 256df2c866
commit d771c47fb8
9 changed files with 365 additions and 162 deletions

View file

@ -13,8 +13,6 @@ import android.os.*
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import net.osmand.PlatformUtil import net.osmand.PlatformUtil
import net.osmand.telegram.helpers.LocationMessages
import net.osmand.telegram.helpers.LocationMessages.LocationMessage
import net.osmand.telegram.helpers.TelegramHelper.TelegramIncomingMessagesListener import net.osmand.telegram.helpers.TelegramHelper.TelegramIncomingMessagesListener
import net.osmand.telegram.helpers.TelegramHelper.TelegramOutgoingMessagesListener import net.osmand.telegram.helpers.TelegramHelper.TelegramOutgoingMessagesListener
import net.osmand.telegram.notifications.TelegramNotification.NotificationType import net.osmand.telegram.notifications.TelegramNotification.NotificationType
@ -278,7 +276,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
override fun onReceiveChatLocationMessages(chatId: Long, vararg messages: TdApi.Message) { override fun onReceiveChatLocationMessages(chatId: Long, vararg messages: TdApi.Message) {
app().showLocationHelper.startShowMessagesTask(chatId, *messages) app().showLocationHelper.startShowMessagesTask(chatId, *messages)
messages.forEach { messages.forEach {
val locationMessage = OsmandLocationUtils.parseMessage(it, app().telegramHelper, LocationMessages.STATUS_PREPARED) val locationMessage = OsmandLocationUtils.parseMessage(it, app().telegramHelper)
if (locationMessage != null) { if (locationMessage != null) {
app().locationMessages.addIngoingMessage(locationMessage) app().locationMessages.addIngoingMessage(locationMessage)
} }
@ -296,6 +294,13 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
override fun onUpdateMessages(messages: List<TdApi.Message>) { override fun onUpdateMessages(messages: List<TdApi.Message>) {
messages.forEach { messages.forEach {
app().settings.updateShareInfo(it) app().settings.updateShareInfo(it)
app().shareLocationHelper.checkAndSendBufferMessagesToChat(it.chatId)
if (it.sendingState == null && (it.content is TdApi.MessageLocation || it.content is TdApi.MessageText)) {
val locationMessage = OsmandLocationUtils.parseMessage(it, app().telegramHelper)
if (locationMessage != null) {
app().locationMessages.addOutgoingMessage(locationMessage)
}
}
} }
} }

View file

@ -7,6 +7,7 @@ import android.support.annotation.DrawableRes
import android.support.annotation.StringRes import android.support.annotation.StringRes
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import net.osmand.PlatformUtil
import net.osmand.telegram.helpers.OsmandAidlHelper import net.osmand.telegram.helpers.OsmandAidlHelper
import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramHelper
import net.osmand.telegram.utils.AndroidUtils import net.osmand.telegram.utils.AndroidUtils
@ -87,6 +88,8 @@ private const val GPS_UPDATE_EXPIRED_TIME = 60 * 3L // 3 minutes
class TelegramSettings(private val app: TelegramApplication) { class TelegramSettings(private val app: TelegramApplication) {
private val log = PlatformUtil.getLog(TelegramSettings::class.java)
private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>() private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>()
private var hiddenOnMapChats: Set<Long> = emptySet() private var hiddenOnMapChats: Set<Long> = emptySet()
private var shareDevices: Set<DeviceBot> = emptySet() private var shareDevices: Set<DeviceBot> = emptySet()
@ -247,16 +250,51 @@ class TelegramSettings(private val app: TelegramApplication) {
if (shareChatInfo != null) { if (shareChatInfo != null) {
when (content) { when (content) {
is TdApi.MessageLocation -> { is TdApi.MessageLocation -> {
shareChatInfo.currentMapMessageId = message.id val state = message.sendingState
shareChatInfo.pendingMapMessage = false if (state != null) {
if (state.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR) {
shareChatInfo.pendingMapMessage = true
log.debug("updateShareInfo MAP ${message.id} MessageSendingStatePending")
shareChatInfo.oldMapMessageId = message.id
} else if (state.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR) {
shareChatInfo.hasSharingError = true
shareChatInfo.pendingMapMessage = false
log.debug("updateShareInfo MAP ${message.id} MessageSendingStateFailed")
}
} else {
log.debug("updateShareInfo MAP ${message.id} SUCCESS")
shareChatInfo.currentMapMessageId = message.id
shareChatInfo.pendingMapMessage = false
shareChatInfo.pendingTdLib--
shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L
if (shareTypeValue == SHARE_TYPE_MAP) {
shareChatInfo.sentMessages++
}
}
} }
is TdApi.MessageText -> { is TdApi.MessageText -> {
shareChatInfo.currentTextMessageId = message.id val state = message.sendingState
shareChatInfo.updateTextMessageId++ if (state != null) {
shareChatInfo.pendingTextMessage = false if (state.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR) {
log.debug("updateShareInfo TEXT ${message.id} MessageSendingStatePending")
shareChatInfo.pendingTextMessage = true
shareChatInfo.oldTextMessageId = message.id
} else if (state.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR) {
log.debug("updateShareInfo TEXT ${message.id} MessageSendingStateFailed")
shareChatInfo.hasSharingError = true
shareChatInfo.pendingTextMessage = false
}
} else {
log.debug("updateShareInfo TEXT ${message.id} SUCCESS")
shareChatInfo.currentTextMessageId = message.id
shareChatInfo.updateTextMessageId++
shareChatInfo.pendingTextMessage = false
shareChatInfo.pendingTdLib--
shareChatInfo.sentMessages++
shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L
}
} }
} }
shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L
} }
} }
@ -540,6 +578,10 @@ class TelegramSettings(private val app: TelegramApplication) {
obj.put(ShareChatInfo.LAST_SUCCESSFUL_SEND_TIME_KEY, chatInfo.lastSuccessfulSendTimeMs) obj.put(ShareChatInfo.LAST_SUCCESSFUL_SEND_TIME_KEY, chatInfo.lastSuccessfulSendTimeMs)
obj.put(ShareChatInfo.LAST_SEND_MAP_TIME_KEY, chatInfo.lastSendMapMessageTime) obj.put(ShareChatInfo.LAST_SEND_MAP_TIME_KEY, chatInfo.lastSendMapMessageTime)
obj.put(ShareChatInfo.LAST_SEND_TEXT_TIME_KEY, chatInfo.lastSendTextMessageTime) obj.put(ShareChatInfo.LAST_SEND_TEXT_TIME_KEY, chatInfo.lastSendTextMessageTime)
obj.put(ShareChatInfo.PENDING_TEXT_MESSAGE_KEY, chatInfo.pendingTextMessage)
obj.put(ShareChatInfo.PENDING_MAP_MESSAGE_KEY, chatInfo.pendingMapMessage)
obj.put(ShareChatInfo.COLLECTED_MESSAGES_KEY, chatInfo.collectedMessages)
obj.put(ShareChatInfo.SENT_MESSAGES_KEY, chatInfo.sentMessages)
jArray.put(obj) jArray.put(obj)
} }
jArray jArray
@ -566,6 +608,10 @@ class TelegramSettings(private val app: TelegramApplication) {
lastSuccessfulSendTimeMs = obj.optLong(ShareChatInfo.LAST_SUCCESSFUL_SEND_TIME_KEY) lastSuccessfulSendTimeMs = obj.optLong(ShareChatInfo.LAST_SUCCESSFUL_SEND_TIME_KEY)
lastSendMapMessageTime = obj.optInt(ShareChatInfo.LAST_SEND_MAP_TIME_KEY) lastSendMapMessageTime = obj.optInt(ShareChatInfo.LAST_SEND_MAP_TIME_KEY)
lastSendTextMessageTime = obj.optInt(ShareChatInfo.LAST_SEND_TEXT_TIME_KEY) lastSendTextMessageTime = obj.optInt(ShareChatInfo.LAST_SEND_TEXT_TIME_KEY)
pendingTextMessage = obj.optBoolean(ShareChatInfo.PENDING_TEXT_MESSAGE_KEY)
pendingMapMessage = obj.optBoolean(ShareChatInfo.PENDING_MAP_MESSAGE_KEY)
collectedMessages = obj.optInt(ShareChatInfo.COLLECTED_MESSAGES_KEY)
sentMessages = obj.optInt(ShareChatInfo.SENT_MESSAGES_KEY)
} }
shareChatsInfo[shareInfo.chatId] = shareInfo shareChatsInfo[shareInfo.chatId] = shareInfo
} }
@ -853,6 +899,8 @@ class TelegramSettings(private val app: TelegramApplication) {
var lastSuccessfulSendTimeMs = -1L var lastSuccessfulSendTimeMs = -1L
var lastSendTextMessageTime = -1 var lastSendTextMessageTime = -1
var lastSendMapMessageTime = -1 var lastSendMapMessageTime = -1
var collectedMessages = 0
var sentMessages = 0
var pendingTdLib = 0 var pendingTdLib = 0
var pendingTextMessage = false var pendingTextMessage = false
var pendingMapMessage = false var pendingMapMessage = false
@ -890,6 +938,10 @@ class TelegramSettings(private val app: TelegramApplication) {
internal const val LAST_SUCCESSFUL_SEND_TIME_KEY = "lastSuccessfulSendTime" internal const val LAST_SUCCESSFUL_SEND_TIME_KEY = "lastSuccessfulSendTime"
internal const val LAST_SEND_MAP_TIME_KEY = "lastSendMapMessageTime" internal const val LAST_SEND_MAP_TIME_KEY = "lastSendMapMessageTime"
internal const val LAST_SEND_TEXT_TIME_KEY = "lastSendTextMessageTime" internal const val LAST_SEND_TEXT_TIME_KEY = "lastSendTextMessageTime"
internal const val PENDING_TEXT_MESSAGE_KEY = "pendingTextMessage"
internal const val PENDING_MAP_MESSAGE_KEY = "pendingMapMessage"
internal const val COLLECTED_MESSAGES_KEY = "collectedMessages"
internal const val SENT_MESSAGES_KEY = "sentMessages"
} }
} }
} }

View file

@ -4,12 +4,13 @@ import android.content.Context
import android.database.Cursor import android.database.Cursor
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper import android.database.sqlite.SQLiteOpenHelper
import net.osmand.PlatformUtil
import net.osmand.telegram.TelegramApplication import net.osmand.telegram.TelegramApplication
import java.util.*
import kotlin.collections.ArrayList
class LocationMessages(val app: TelegramApplication) { class LocationMessages(val app: TelegramApplication) {
private val log = PlatformUtil.getLog(LocationMessages::class.java)
// todo - bufferedMessages is for prepared/pending messages only. On app start we read prepared/pending messages to bufferedMessages. After status changed to sent/error - remove message from buffered. // todo - bufferedMessages is for prepared/pending messages only. On app start we read prepared/pending messages to bufferedMessages. After status changed to sent/error - remove message from buffered.
private var bufferedMessages = emptyList<BufferMessage>() private var bufferedMessages = emptyList<BufferMessage>()
@ -21,7 +22,12 @@ class LocationMessages(val app: TelegramApplication) {
} }
fun getPreparedMessages(): List<BufferMessage> { fun getPreparedMessages(): List<BufferMessage> {
return bufferedMessages.sortedBy { it.date } return bufferedMessages.sortedBy { it.time }
}
fun getPreparedMessagesForChat(chatId: Long): List<BufferMessage> {
log.debug("getPreparedMessagesForChat chatId")
return bufferedMessages.filter { it.chatId==chatId }.sortedBy { it.time }
} }
// // todo - drop method. add collected / sent messages count to ShareChatInfo // // todo - drop method. add collected / sent messages count to ShareChatInfo
@ -30,21 +36,21 @@ class LocationMessages(val app: TelegramApplication) {
// return bufferedMessages.filter { it.userId == currentUserId && it.chatId == chatId }.sortedBy { it.date } // return bufferedMessages.filter { it.userId == currentUserId && it.chatId == chatId }.sortedBy { it.date }
// } // }
fun updateBufferedMessageStatus(oldMessage: BufferMessage, status: Int){ // todo - read from db by date (Victor's suggestion - filter by one day only. Need to be changed in UI also.
val messages = mutableListOf(*this.bufferedMessages.toTypedArray()) fun getIngoingMessages(currentUserId: Int, start: Long, end: Long): List<LocationMessage> {
messages.remove(oldMessage) return dbHelper.getIngoingMessages(currentUserId, start, end)
val newMessage = BufferMessage(oldMessage.chatId,oldMessage.lat,oldMessage.lon,oldMessage.altitude,oldMessage.speed,oldMessage.hdop,oldMessage.bearing,oldMessage.date,oldMessage.type,status)
messages.add(newMessage)
this.bufferedMessages = messages
// dbHelper.addBufferedMessage(newMessage)
} }
// todo - read from db by date (Victor's suggestion - filter by one day only. Need to be changed in UI also. fun getIngoingMessagesForUser(userId: Int, chatId: Long, start: Long, end: Long): List<LocationMessage> {
fun getIngoingMessages(userId: Int, date: Date): List<LocationMessage> { return dbHelper.getIngoingMessagesForUser(userId, chatId, start, end)
return emptyList() }
fun getOutgoingMessages(userId: Int, start: Long, end: Long): List<LocationMessage> {
return dbHelper.getOutgoingMessagesForUser(userId, start, end)
} }
fun addBufferedMessage(message: BufferMessage) { fun addBufferedMessage(message: BufferMessage) {
log.debug("addBufferedMessage $message")
val messages = mutableListOf(*this.bufferedMessages.toTypedArray()) val messages = mutableListOf(*this.bufferedMessages.toTypedArray())
messages.add(message) messages.add(message)
this.bufferedMessages = messages this.bufferedMessages = messages
@ -52,29 +58,28 @@ class LocationMessages(val app: TelegramApplication) {
} }
fun addIngoingMessage(message: LocationMessage) { fun addIngoingMessage(message: LocationMessage) {
log.debug("addIngoingMessage $message")
dbHelper.addIngoingMessage(message) dbHelper.addIngoingMessage(message)
} }
fun addOutgoingMessage(message: LocationMessage) {
log.debug("addOutgoingMessage $message")
dbHelper.addOutgoingMessage(message)
}
fun clearBufferedMessages() { fun clearBufferedMessages() {
log.debug("clearBufferedMessages")
dbHelper.clearBufferedMessages() dbHelper.clearBufferedMessages()
bufferedMessages = emptyList() bufferedMessages = emptyList()
} }
// todo - both methods should be refactored since we have two tables now for outgoing/ingoing messages. Data should be read from db. fun removeBufferedMessage(message: BufferMessage) {
// fun collectRecordedDataForUser(userId: Int, chatId: Long, start: Long, end: Long): List<LocationMessage> { log.debug("removeBufferedMessage $message")
// return if (chatId == 0L) { val messages = mutableListOf(*this.bufferedMessages.toTypedArray())
// bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter { it.userId == userId && it.date in (start + 1)..(end - 1) } messages.remove(message)
// } else { this.bufferedMessages = messages
// bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter { dbHelper.removeBufferedMessage(message)
// it.chatId == chatId && it.userId == userId&&it.date in (start + 1)..(end - 1) } }
// }
// }
//
// fun collectRecordedDataForUsers(start: Long, end: Long, ignoredUsersIds: ArrayList<Int>): List<LocationMessage> {
// return bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter {
// it.date in (start + 1)..(end - 1) && !ignoredUsersIds.contains(it.userId)
// }
// }
private fun readBufferedMessages() { private fun readBufferedMessages() {
this.bufferedMessages = dbHelper.getBufferedMessages() this.bufferedMessages = dbHelper.getBufferedMessages()
@ -95,22 +100,67 @@ class LocationMessages(val app: TelegramApplication) {
onCreate(db) onCreate(db)
} }
internal fun getOutgoingMessagesForUser(userId: Int, start: Long, end: Long): List<LocationMessage> {
val res = arrayListOf<LocationMessage>()
readableDatabase?.rawQuery(
"$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID = ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_TIME ASC ",
arrayOf(userId.toString()))?.apply {
if (moveToFirst()) {
do {
res.add(readLocationMessage(this@apply))
} while (moveToNext())
}
close()
}
return res
}
internal fun getIngoingMessages(currentUserId: Int, start: Long, end: Long): List<LocationMessage> {
val res = arrayListOf<LocationMessage>()
readableDatabase?.rawQuery(
"$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID != ? AND $COL_CHAT_ID = ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_TIME ASC ",
arrayOf(currentUserId.toString()))?.apply {
if (moveToFirst()) {
do {
res.add(readLocationMessage(this@apply))
} while (moveToNext())
}
close()
}
return res
}
internal fun getIngoingMessagesForUser(userId: Int, chatId: Long, start: Long, end: Long): List<LocationMessage> {
val res = arrayListOf<LocationMessage>()
readableDatabase?.rawQuery(
"$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID = ? AND $COL_CHAT_ID = ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_TIME ASC ",
arrayOf(userId.toString(), chatId.toString(), start.toString(), end.toString()))?.apply {
if (moveToFirst()) {
do {
res.add(readLocationMessage(this@apply))
} while (moveToNext())
}
close()
}
return res
}
internal fun addBufferedMessage(message: BufferMessage) { internal fun addBufferedMessage(message: BufferMessage) {
writableDatabase?.execSQL(BUFFER_TABLE_INSERT, writableDatabase?.execSQL(BUFFER_TABLE_INSERT,
arrayOf(message.chatId, message.lat, message.lon, message.altitude, message.speed, arrayOf(message.chatId, message.lat, message.lon, message.altitude, message.speed,
message.hdop, message.bearing, message.date, message.type)) message.hdop, message.bearing, message.time, message.type))
} }
internal fun addIngoingMessage(message: LocationMessage) { internal fun addIngoingMessage(message: LocationMessage) {
writableDatabase?.execSQL(TIMELINE_TABLE_INSERT, writableDatabase?.execSQL(TIMELINE_TABLE_INSERT,
arrayOf(message.userId, message.chatId, message.lat, message.lon, message.altitude, message.speed, arrayOf(message.userId, message.chatId, message.lat, message.lon, message.altitude, message.speed,
message.hdop, message.bearing, message.date, message.type)) message.hdop, message.bearing, message.time, message.type))
} }
internal fun addOutgoingMessage(message: LocationMessage) { internal fun addOutgoingMessage(message: LocationMessage) {
writableDatabase?.execSQL(TIMELINE_TABLE_INSERT, writableDatabase?.execSQL(TIMELINE_TABLE_INSERT,
arrayOf(message.userId, message.chatId, message.lat, message.lon, message.altitude, message.speed, arrayOf(message.userId, message.chatId, message.lat, message.lon, message.altitude, message.speed,
message.hdop, message.bearing, message.date, message.type)) message.hdop, message.bearing, message.time, message.type))
} }
internal fun getOutgoingMessages(): List<LocationMessage> { internal fun getOutgoingMessages(): List<LocationMessage> {
@ -155,24 +205,41 @@ class LocationMessages(val app: TelegramApplication) {
} }
internal fun readBufferMessage(cursor: Cursor): BufferMessage { internal fun readBufferMessage(cursor: Cursor): BufferMessage {
val chatId = cursor.getLong(1) val chatId = cursor.getLong(0)
val lat = cursor.getDouble(2) val lat = cursor.getDouble(1)
val lon = cursor.getDouble(3) val lon = cursor.getDouble(2)
val altitude = cursor.getDouble(4) val altitude = cursor.getDouble(3)
val speed = cursor.getDouble(5) val speed = cursor.getDouble(4)
val hdop = cursor.getDouble(6) val hdop = cursor.getDouble(5)
val bearing = cursor.getDouble(7) val bearing = cursor.getDouble(6)
val date = cursor.getLong(8) val date = cursor.getLong(7)
val type = cursor.getInt(9) val type = cursor.getInt(8)
val status = cursor.getInt(10)
return BufferMessage(chatId, lat, lon, altitude, speed, hdop, bearing, date, type,status) return BufferMessage(chatId, lat, lon, altitude, speed, hdop, bearing, date, type)
} }
internal fun clearBufferedMessages() { internal fun clearBufferedMessages() {
writableDatabase?.execSQL(BUFFER_TABLE_CLEAR) writableDatabase?.execSQL(BUFFER_TABLE_CLEAR)
} }
internal fun removeBufferedMessage(message: BufferMessage) {
writableDatabase?.execSQL(
BUFFER_TABLE_REMOVE,
arrayOf(
message.chatId,
message.lat,
message.lon,
message.altitude,
message.speed,
message.hdop,
message.bearing,
message.time,
message.type
)
)
}
companion object { companion object {
private const val DATABASE_NAME = "location_messages" private const val DATABASE_NAME = "location_messages"
@ -191,7 +258,6 @@ class LocationMessages(val app: TelegramApplication) {
private const val COL_HDOP = "hdop" private const val COL_HDOP = "hdop"
private const val COL_BEARING = "bearing" private const val COL_BEARING = "bearing"
private const val COL_TYPE = "type" // 0 = user map message, 1 = user text message, 2 = bot map message, 3 = bot text message private const val COL_TYPE = "type" // 0 = user map message, 1 = user text message, 2 = bot map message, 3 = bot text message
private const val COL_MESSAGE_STATUS = "status" // 0 = preparing , 1 = pending, 2 = sent, 3 = error
private const val COL_MESSAGE_ID = "message_id" private const val COL_MESSAGE_ID = "message_id"
private const val DATE_INDEX = "date_index" private const val DATE_INDEX = "date_index"
@ -212,16 +278,18 @@ class LocationMessages(val app: TelegramApplication) {
// Buffer messages table // Buffer messages table
private const val BUFFER_TABLE_INSERT = private const val BUFFER_TABLE_INSERT =
("INSERT INTO $BUFFER_TABLE_NAME ($COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_STATUS) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") ("INSERT INTO $BUFFER_TABLE_NAME ($COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
private const val BUFFER_TABLE_CREATE = private const val BUFFER_TABLE_CREATE =
("CREATE TABLE IF NOT EXISTS $BUFFER_TABLE_NAME ($COL_CHAT_ID long, $COL_LAT double, $COL_LON double, $COL_ALTITUDE double, $COL_SPEED float, $COL_HDOP double, $COL_BEARING double, $COL_TIME long, $COL_TYPE int, $COL_MESSAGE_STATUS int)") ("CREATE TABLE IF NOT EXISTS $BUFFER_TABLE_NAME ($COL_CHAT_ID long, $COL_LAT double, $COL_LON double, $COL_ALTITUDE double, $COL_SPEED float, $COL_HDOP double, $COL_BEARING double, $COL_TIME long, $COL_TYPE int)")
private const val BUFFER_TABLE_SELECT = private const val BUFFER_TABLE_SELECT =
"SELECT $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_STATUS FROM $BUFFER_TABLE_NAME" "SELECT $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE FROM $BUFFER_TABLE_NAME"
private const val BUFFER_TABLE_CLEAR = "DELETE FROM $BUFFER_TABLE_NAME" private const val BUFFER_TABLE_CLEAR = "DELETE FROM $BUFFER_TABLE_NAME"
private const val BUFFER_TABLE_REMOVE = "DELETE FROM $BUFFER_TABLE_NAME WHERE $COL_CHAT_ID = ? AND $COL_LAT = ? AND $COL_LON = ? AND $COL_ALTITUDE = ? AND $COL_SPEED = ? AND $COL_HDOP = ? AND $COL_BEARING = ? AND $COL_TIME = ? AND $COL_TYPE = ?"
private const val BUFFER_TABLE_DELETE = "DROP TABLE IF EXISTS $BUFFER_TABLE_NAME" private const val BUFFER_TABLE_DELETE = "DROP TABLE IF EXISTS $BUFFER_TABLE_NAME"
} }
} }
@ -235,7 +303,7 @@ class LocationMessages(val app: TelegramApplication) {
val speed: Double, val speed: Double,
val hdop: Double, val hdop: Double,
val bearing: Double, val bearing: Double,
val date: Long, val time: Long,
val type: Int) val type: Int)
data class BufferMessage ( data class BufferMessage (
@ -246,21 +314,16 @@ class LocationMessages(val app: TelegramApplication) {
val speed: Double, val speed: Double,
val hdop: Double, val hdop: Double,
val bearing: Double, val bearing: Double,
val date: Long, val time: Long,
val type: Int, val type: Int)
// todo - status and messageId should be updated in db right away. Make them val instead of var.
val status: Int)
companion object { companion object {
const val STATUS_PREPARED = 0
const val STATUS_PENDING = 1
const val STATUS_SENT = 2
const val STATUS_ERROR = 3
const val TYPE_USER_MAP = 0 const val TYPE_USER_MAP = 0
const val TYPE_USER_TEXT = 1 const val TYPE_USER_TEXT = 1
const val TYPE_BOT_MAP = 2 const val TYPE_USER_BOTH = 2
const val TYPE_BOT_TEXT = 3 const val TYPE_BOT_MAP = 3
const val TYPE_BOT_TEXT = 4
const val TYPE_BOT_BOTH = 5
} }
} }

View file

@ -95,6 +95,38 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
} }
fun checkAndSendBufferMessagesToChat(chatId: Long) {
log.debug("checkAndSendBufferMessagesToChat $chatId")
val shareInfo = app.settings.getChatsShareInfo()[chatId]
if (shareInfo != null && shareInfo.pendingTdLib < 10) {
app.locationMessages.getPreparedMessagesForChat(shareInfo.chatId).forEach {
if (it.type == LocationMessages.TYPE_USER_TEXT && !shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) {
app.telegramHelper.editTextLocation(shareInfo, it)
app.locationMessages.removeBufferedMessage(it)
} else if (it.type == LocationMessages.TYPE_USER_MAP && !shareInfo.pendingMapMessage && shareInfo.currentMapMessageId != -1L) {
app.telegramHelper.editMapLocation(shareInfo, it)
app.locationMessages.removeBufferedMessage(it)
} else if (it.type == LocationMessages.TYPE_USER_BOTH) {
var messageSent = false
if (!shareInfo.pendingMapMessage && shareInfo.currentMapMessageId != -1L) {
app.telegramHelper.editMapLocation(shareInfo, it)
messageSent = true
}
if (!shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) {
app.telegramHelper.editTextLocation(shareInfo, it)
messageSent = true
}
if (messageSent) {
app.locationMessages.removeBufferedMessage(it)
}
}
if (shareInfo.pendingTdLib >= 10) {
return
}
}
}
}
fun startSharingLocation() { fun startSharingLocation() {
if (!sharingLocation) { if (!sharingLocation) {
sharingLocation = true sharingLocation = true
@ -102,6 +134,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
app.startMyLocationService() app.startMyLocationService()
refreshNotification() refreshNotification()
checkAndSendBufferMessages()
} else { } else {
app.forceUpdateMyLocation() app.forceUpdateMyLocation()
} }
@ -131,47 +165,59 @@ class ShareLocationHelper(private val app: TelegramApplication) {
refreshNotification() refreshNotification()
} }
private fun checkAndSendBufferMessages(){
log.debug("checkAndSendBufferMessages")
app.settings.getChatsShareInfo().forEach loop@{ (chatId, shareInfo) ->
if (shareInfo.pendingTdLib < 10) {
app.locationMessages.getPreparedMessagesForChat(chatId).forEach {
if (it.type == LocationMessages.TYPE_USER_TEXT && !shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) {
app.telegramHelper.editTextLocation(shareInfo, it)
app.locationMessages.removeBufferedMessage(it)
} else if (it.type == LocationMessages.TYPE_USER_MAP && !shareInfo.pendingMapMessage && shareInfo.currentMapMessageId != -1L) {
app.telegramHelper.editMapLocation(shareInfo, it)
app.locationMessages.removeBufferedMessage(it)
}
if (shareInfo.pendingTdLib >= 10) {
return@loop
}
}
}
}
}
private fun shareLocationMessages(location: Location, userId: Int) { private fun shareLocationMessages(location: Location, userId: Int) {
val chatsShareInfo = app.settings.getChatsShareInfo() val chatsShareInfo = app.settings.getChatsShareInfo()
val latitude = location.latitude val latitude = location.latitude
val longitude = location.longitude val longitude = location.longitude
val sharingMode = app.settings.currentSharingMode val sharingMode = app.settings.currentSharingMode
val isBot = sharingMode != userId.toString() val isBot = sharingMode != userId.toString()
val types = mutableListOf<Int>()
var bufferedMessagesFull = false var bufferedMessagesFull = false
val type = when (app.settings.shareTypeValue) {
when (app.settings.shareTypeValue) {
SHARE_TYPE_MAP -> { SHARE_TYPE_MAP -> {
types.add(if (isBot) LocationMessages.TYPE_BOT_MAP else LocationMessages.TYPE_USER_MAP) if (isBot) LocationMessages.TYPE_BOT_MAP else LocationMessages.TYPE_USER_MAP
} }
SHARE_TYPE_TEXT -> { SHARE_TYPE_TEXT -> {
types.add(if (isBot) LocationMessages.TYPE_BOT_TEXT else LocationMessages.TYPE_USER_TEXT) if (isBot) LocationMessages.TYPE_BOT_TEXT else LocationMessages.TYPE_USER_TEXT
} }
SHARE_TYPE_MAP_AND_TEXT -> { SHARE_TYPE_MAP_AND_TEXT -> {
types.add(if (isBot) LocationMessages.TYPE_BOT_MAP else LocationMessages.TYPE_USER_MAP) if (isBot) LocationMessages.TYPE_BOT_BOTH else LocationMessages.TYPE_USER_BOTH
types.add(if (isBot) LocationMessages.TYPE_BOT_TEXT else LocationMessages.TYPE_USER_TEXT) } else -> -1
}
} }
chatsShareInfo.values.forEach { shareInfo -> chatsShareInfo.values.forEach { shareInfo ->
if (shareInfo.pendingTdLib >= 10) { if (shareInfo.pendingTdLib >= 10) {
bufferedMessagesFull = true bufferedMessagesFull = true
} }
types.forEach { val message = BufferMessage(
val message = BufferMessage(shareInfo.chatId, latitude, longitude, location.altitude, location.speed.toDouble(), shareInfo.chatId, latitude, longitude, location.altitude, location.speed.toDouble(),
location.accuracy.toDouble(), location.bearing.toDouble(), location.time, it, LocationMessages.STATUS_PREPARED) location.accuracy.toDouble(), location.bearing.toDouble(), System.currentTimeMillis(), type
)
when (app.settings.shareTypeValue) { if (type == LocationMessages.TYPE_USER_MAP || type == LocationMessages.TYPE_BOT_MAP) {
SHARE_TYPE_MAP -> { prepareMapMessage(shareInfo, message, isBot, sharingMode)
prepareMapMessage(shareInfo, message, isBot, sharingMode) } else if (type == LocationMessages.TYPE_USER_TEXT || type == LocationMessages.TYPE_BOT_TEXT) {
} prepareTextMessage(shareInfo, message, isBot, sharingMode)
SHARE_TYPE_TEXT -> { } else if (type == LocationMessages.TYPE_USER_BOTH || type == LocationMessages.TYPE_BOT_BOTH) {
prepareTextMessage(shareInfo, message, isBot, sharingMode) prepareMapAndTextMessage(shareInfo, message, isBot, sharingMode)
}
SHARE_TYPE_MAP_AND_TEXT -> {
prepareMapMessage(shareInfo, message, isBot, sharingMode)
prepareTextMessage(shareInfo, message, isBot, sharingMode)
}
}
} }
} }
if (bufferedMessagesFull) { if (bufferedMessagesFull) {
@ -180,6 +226,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
private fun prepareTextMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) { private fun prepareTextMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) {
log.debug("prepareTextMessage $message")
shareInfo.collectedMessages++
if (shareInfo.currentTextMessageId == -1L) { if (shareInfo.currentTextMessageId == -1L) {
if (shareInfo.pendingTextMessage) { if (shareInfo.pendingTextMessage) {
app.locationMessages.addBufferedMessage(message) app.locationMessages.addBufferedMessage(message)
@ -187,7 +235,6 @@ class ShareLocationHelper(private val app: TelegramApplication) {
if (isBot) { if (isBot) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_TEXT) sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_TEXT)
} else { } else {
shareInfo.pendingTdLib++
app.telegramHelper.sendNewTextLocation(shareInfo, message) app.telegramHelper.sendNewTextLocation(shareInfo, message)
} }
} }
@ -196,7 +243,6 @@ class ShareLocationHelper(private val app: TelegramApplication) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_TEXT) sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_TEXT)
} else { } else {
if (shareInfo.pendingTdLib < 10) { if (shareInfo.pendingTdLib < 10) {
shareInfo.pendingTdLib++
app.telegramHelper.editTextLocation(shareInfo, message) app.telegramHelper.editTextLocation(shareInfo, message)
} else { } else {
app.locationMessages.addBufferedMessage(message) app.locationMessages.addBufferedMessage(message)
@ -206,6 +252,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
private fun prepareMapMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) { private fun prepareMapMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) {
log.debug("prepareMapMessage $message")
shareInfo.collectedMessages++
if (shareInfo.currentMapMessageId == -1L) { if (shareInfo.currentMapMessageId == -1L) {
if (shareInfo.pendingMapMessage) { if (shareInfo.pendingMapMessage) {
app.locationMessages.addBufferedMessage(message) app.locationMessages.addBufferedMessage(message)
@ -213,7 +261,6 @@ class ShareLocationHelper(private val app: TelegramApplication) {
if (isBot) { if (isBot) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_MAP) sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_MAP)
} else { } else {
shareInfo.pendingTdLib++
app.telegramHelper.sendNewMapLocation(shareInfo, message) app.telegramHelper.sendNewMapLocation(shareInfo, message)
} }
} }
@ -222,15 +269,38 @@ class ShareLocationHelper(private val app: TelegramApplication) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_MAP) sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_MAP)
} else { } else {
if (shareInfo.pendingTdLib < 10) { if (shareInfo.pendingTdLib < 10) {
shareInfo.pendingTdLib++
app.telegramHelper.editMapLocation(shareInfo, message) app.telegramHelper.editMapLocation(shareInfo, message)
} else { } else {
shareInfo.collectedMessages++
app.locationMessages.addBufferedMessage(message) app.locationMessages.addBufferedMessage(message)
} }
} }
} }
} }
private fun prepareMapAndTextMessage(shareInfo: TelegramSettings.ShareChatInfo, message: BufferMessage, isBot:Boolean, sharingMode: String) {
log.debug("prepareMapAndTextMessage $message")
shareInfo.collectedMessages++
if (shareInfo.pendingMapMessage || shareInfo.pendingTextMessage || shareInfo.pendingTdLib >= 10) {
app.locationMessages.addBufferedMessage(message)
} else {
if (isBot) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_MAP_AND_TEXT)
} else {
if (shareInfo.currentMapMessageId == -1L) {
app.telegramHelper.sendNewMapLocation(shareInfo, message)
} else {
app.telegramHelper.editMapLocation(shareInfo, message)
}
if (shareInfo.currentTextMessageId == -1L) {
app.telegramHelper.sendNewTextLocation(shareInfo, message)
} else {
app.telegramHelper.editTextLocation(shareInfo, message)
}
}
}
}
private fun checkNetworkType(){ private fun checkNetworkType(){
if (app.isInternetConnectionAvailable) { if (app.isInternetConnectionAvailable) {
val networkType = when { val networkType = when {
@ -244,7 +314,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
private fun sendLocationToBot(locationMessage: BufferMessage, sharingMode: String, shareInfo: TelegramSettings.ShareChatInfo, shareType: String) { private fun sendLocationToBot(locationMessage: BufferMessage, sharingMode: String, shareInfo: TelegramSettings.ShareChatInfo, shareType: String) {
if (app.isInternetConnectionAvailable) { if (app.isInternetConnectionAvailable) {
// locationMessage.status = LocationMessage.STATUS_PENDING log.debug("sendLocationToBot $locationMessage")
val url = getDeviceSharingUrl(locationMessage, sharingMode) val url = getDeviceSharingUrl(locationMessage, sharingMode)
AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false, AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false,
object : AndroidNetworkUtils.OnRequestResultListener { object : AndroidNetworkUtils.OnRequestResultListener {
@ -254,7 +324,6 @@ class ShareLocationHelper(private val app: TelegramApplication) {
val osmandBotId = app.telegramHelper.getOsmandBot()?.id ?: -1 val osmandBotId = app.telegramHelper.getOsmandBot()?.id ?: -1
val device = app.settings.getCurrentSharingDevice() val device = app.settings.getCurrentSharingDevice()
// locationMessage.status = if (success) LocationMessage.STATUS_SENT else LocationMessage.STATUS_ERROR
if (success && shareInfo.shouldSendViaBotMessage && osmandBotId != -1 && device != null) { if (success && shareInfo.shouldSendViaBotMessage && osmandBotId != -1 && device != null) {
app.telegramHelper.sendViaBotLocationMessage(osmandBotId, shareInfo, TdApi.Location(locationMessage.lat, locationMessage.lon), device, shareType) app.telegramHelper.sendViaBotLocationMessage(osmandBotId, shareInfo, TdApi.Location(locationMessage.lat, locationMessage.lon), device, shareType)
shareInfo.shouldSendViaBotMessage = false shareInfo.shouldSendViaBotMessage = false

View file

@ -293,7 +293,7 @@ class TelegramHelper private constructor() {
try { try {
log.debug("Loading native tdlib...") log.debug("Loading native tdlib...")
System.loadLibrary("tdjni") System.loadLibrary("tdjni")
Client.setLogVerbosityLevel(0) Client.setLogVerbosityLevel(1)
libraryLoaded = true libraryLoaded = true
} catch (e: Throwable) { } catch (e: Throwable) {
log.error("Failed to load tdlib", e) log.error("Failed to load tdlib", e)
@ -539,7 +539,7 @@ class TelegramHelper private constructor() {
resultArticles.forEach { resultArticles.forEach {
client?.send(TdApi.SendInlineQueryResultMessage(shareInfo.chatId, 0, true, client?.send(TdApi.SendInlineQueryResultMessage(shareInfo.chatId, 0, true,
true, inlineQueryResults.inlineQueryId, it.id)) { obj -> true, inlineQueryResults.inlineQueryId, it.id)) { obj ->
handleTextLocationMessageUpdate(obj, shareInfo, null) handleTextLocationMessageUpdate(obj, shareInfo)
} }
} }
} }
@ -765,7 +765,7 @@ class TelegramHelper private constructor() {
if (shareInfo.currentMapMessageId != -1L && shareInfo.chatId != -1L) { if (shareInfo.currentMapMessageId != -1L && shareInfo.chatId != -1L) {
client?.send( client?.send(
TdApi.EditMessageLiveLocation(shareInfo.chatId, shareInfo.currentMapMessageId, null, null)) { obj -> TdApi.EditMessageLiveLocation(shareInfo.chatId, shareInfo.currentMapMessageId, null, null)) { obj ->
handleMapLocationMessageUpdate(obj, shareInfo, null) handleMapLocationMessageUpdate(obj, shareInfo)
} }
} }
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
@ -808,10 +808,7 @@ class TelegramHelper private constructor() {
} }
} }
private fun recreateLiveLocationMessage( private fun recreateLiveLocationMessage(shareInfo: TelegramSettings.ShareChatInfo, content: TdApi.InputMessageContent) {
shareInfo: TelegramSettings.ShareChatInfo,
content: TdApi.InputMessageContent,locationMessage: LocationMessages.BufferMessage?
) {
if (shareInfo.chatId != -1L) { if (shareInfo.chatId != -1L) {
val array = LongArray(1) val array = LongArray(1)
if (content is TdApi.InputMessageLocation) { if (content is TdApi.InputMessageLocation) {
@ -823,7 +820,7 @@ class TelegramHelper private constructor() {
log.debug("recreateLiveLocationMessage - ${array[0]}") log.debug("recreateLiveLocationMessage - ${array[0]}")
client?.send(TdApi.DeleteMessages(shareInfo.chatId, array, true)) { obj -> client?.send(TdApi.DeleteMessages(shareInfo.chatId, array, true)) { obj ->
when (obj.constructor) { when (obj.constructor) {
TdApi.Ok.CONSTRUCTOR -> sendNewLiveLocationMessage(shareInfo, content,locationMessage) TdApi.Ok.CONSTRUCTOR -> sendNewLiveLocationMessage(shareInfo, content)
TdApi.Error.CONSTRUCTOR -> { TdApi.Error.CONSTRUCTOR -> {
val error = obj as TdApi.Error val error = obj as TdApi.Error
if (error.code != IGNORED_ERROR_CODE) { if (error.code != IGNORED_ERROR_CODE) {
@ -840,14 +837,14 @@ class TelegramHelper private constructor() {
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
} }
private fun sendNewLiveLocationMessage(shareInfo: TelegramSettings.ShareChatInfo, content: TdApi.InputMessageContent, locationMessage: LocationMessages.BufferMessage?) { private fun sendNewLiveLocationMessage(shareInfo: TelegramSettings.ShareChatInfo, content: TdApi.InputMessageContent) {
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
log.debug("sendNewLiveLocationMessage") log.debug("sendNewLiveLocationMessage")
client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj -> client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj ->
if (locationMessage?.type == LocationMessages.TYPE_USER_TEXT || locationMessage?.type == LocationMessages.TYPE_BOT_TEXT) { if (content is TdApi.InputMessageText) {
handleTextLocationMessageUpdate(obj, shareInfo, locationMessage) handleTextLocationMessageUpdate(obj, shareInfo)
} else if (locationMessage?.type == LocationMessages.TYPE_USER_MAP || locationMessage?.type == LocationMessages.TYPE_BOT_MAP) { } else if (content is TdApi.InputMessageLocation) {
handleMapLocationMessageUpdate(obj, shareInfo, locationMessage) handleMapLocationMessageUpdate(obj, shareInfo)
} }
} }
} }
@ -857,8 +854,10 @@ class TelegramHelper private constructor() {
val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, location) val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, location)
if (!shareInfo.pendingTextMessage) { if (!shareInfo.pendingTextMessage) {
shareInfo.pendingTextMessage = true shareInfo.pendingTextMessage = true
shareInfo.pendingTdLib++
log.error("sendNewTextLocation ${shareInfo.pendingTdLib}")
client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj -> client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj ->
handleTextLocationMessageUpdate(obj, shareInfo, location) handleTextLocationMessageUpdate(obj, shareInfo)
} }
} }
} }
@ -866,8 +865,10 @@ class TelegramHelper private constructor() {
fun editTextLocation(shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.BufferMessage) { fun editTextLocation(shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.BufferMessage) {
val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, location) val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, location)
if (shareInfo.currentTextMessageId!=-1L) { if (shareInfo.currentTextMessageId!=-1L) {
shareInfo.pendingTdLib++
log.info("editTextLocation ${shareInfo.currentTextMessageId} pendingTdLib: ${shareInfo.pendingTdLib}")
client?.send(TdApi.EditMessageText(shareInfo.chatId, shareInfo.currentTextMessageId, null, content)) { obj -> client?.send(TdApi.EditMessageText(shareInfo.chatId, shareInfo.currentTextMessageId, null, content)) { obj ->
handleTextLocationMessageUpdate(obj, shareInfo, location) handleTextLocationMessageUpdate(obj, shareInfo)
} }
} }
} }
@ -884,8 +885,10 @@ class TelegramHelper private constructor() {
val content = TdApi.InputMessageLocation(location, livePeriod) val content = TdApi.InputMessageLocation(location, livePeriod)
if (!shareInfo.pendingMapMessage) { if (!shareInfo.pendingMapMessage) {
shareInfo.pendingMapMessage = true shareInfo.pendingMapMessage = true
shareInfo.pendingTdLib++
log.error("sendNewMapLocation ${shareInfo.pendingTdLib}")
client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj -> client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj ->
handleMapLocationMessageUpdate(obj, shareInfo, locationMessage) handleMapLocationMessageUpdate(obj, shareInfo)
} }
} }
} }
@ -894,16 +897,18 @@ class TelegramHelper private constructor() {
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
val location = TdApi.Location(locationMessage.lat, locationMessage.lon) val location = TdApi.Location(locationMessage.lat, locationMessage.lon)
if (shareInfo.currentMapMessageId!=-1L) { if (shareInfo.currentMapMessageId!=-1L) {
client?.send( shareInfo.pendingTdLib++
TdApi.EditMessageLiveLocation(shareInfo.chatId, shareInfo.currentMapMessageId, null, location)) { obj -> log.info("editMapLocation ${shareInfo.currentMapMessageId} pendingTdLib: ${shareInfo.pendingTdLib}")
handleMapLocationMessageUpdate(obj, shareInfo, locationMessage) client?.send(TdApi.EditMessageLiveLocation(shareInfo.chatId, shareInfo.currentMapMessageId, null, location)) { obj ->
handleMapLocationMessageUpdate(obj, shareInfo)
} }
} }
} }
private fun handleMapLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.BufferMessage?) { private fun handleMapLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo) {
when (obj.constructor) { when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> { TdApi.Error.CONSTRUCTOR -> {
log.debug("handleMapLocationMessageUpdate - ERROR")
val error = obj as TdApi.Error val error = obj as TdApi.Error
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
if (error.code == MESSAGE_CANNOT_BE_EDITED_ERROR_CODE) { if (error.code == MESSAGE_CANNOT_BE_EDITED_ERROR_CODE) {
@ -922,7 +927,7 @@ class TelegramHelper private constructor() {
shareInfo.hasSharingError = true shareInfo.hasSharingError = true
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
shareInfo.pendingMapMessage = false shareInfo.pendingMapMessage = false
// location?.status = LocationMessages.LocationMessage.STATUS_ERROR log.debug("handleTextLocationMessageUpdate - MessageSendingStateFailed")
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(-1, "Map location message ${obj.id} failed to send") it.onSendLiveLocationError(-1, "Map location message ${obj.id} failed to send")
} }
@ -930,15 +935,15 @@ class TelegramHelper private constructor() {
obj.sendingState?.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR -> { obj.sendingState?.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR -> {
shareInfo.pendingMapMessage = true shareInfo.pendingMapMessage = true
shareInfo.lastSendMapMessageTime = obj.date shareInfo.lastSendMapMessageTime = obj.date
// location?.status = LocationMessages.LocationMessage.STATUS_PENDING
log.debug("handleMapLocationMessageUpdate - MessageSendingStatePending") log.debug("handleMapLocationMessageUpdate - MessageSendingStatePending")
outgoingMessagesListeners.forEach {
it.onUpdateMessages(listOf(obj))
}
} }
else -> { else -> {
shareInfo.hasSharingError = false shareInfo.hasSharingError = false
shareInfo.pendingTdLib--
shareInfo.pendingMapMessage = false shareInfo.pendingMapMessage = false
// location?.messageId = obj.id log.debug("handleMapLocationMessageUpdate - MessageSendingStateSuccess")
// location?.status = LocationMessages.LocationMessage.STATUS_SENT
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onUpdateMessages(listOf(obj)) it.onUpdateMessages(listOf(obj))
} }
@ -949,9 +954,10 @@ class TelegramHelper private constructor() {
} }
} }
private fun handleTextLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.BufferMessage?) { private fun handleTextLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo) {
when (obj.constructor) { when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> { TdApi.Error.CONSTRUCTOR -> {
log.debug("handleTextLocationMessageUpdate - ERROR")
val error = obj as TdApi.Error val error = obj as TdApi.Error
if (error.code == MESSAGE_CANNOT_BE_EDITED_ERROR_CODE) { if (error.code == MESSAGE_CANNOT_BE_EDITED_ERROR_CODE) {
shareInfo.shouldDeletePreviousTextMessage = true shareInfo.shouldDeletePreviousTextMessage = true
@ -970,7 +976,7 @@ class TelegramHelper private constructor() {
shareInfo.pendingTdLib-- shareInfo.pendingTdLib--
shareInfo.pendingTextMessage = false shareInfo.pendingTextMessage = false
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
// location?.status = LocationMessages.LocationMessage.STATUS_ERROR log.debug("handleTextLocationMessageUpdate - MessageSendingStateFailed")
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(-1, "Text location message ${obj.id} failed to send") it.onSendLiveLocationError(-1, "Text location message ${obj.id} failed to send")
} }
@ -978,15 +984,15 @@ class TelegramHelper private constructor() {
obj.sendingState?.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR -> { obj.sendingState?.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR -> {
shareInfo.pendingTextMessage = true shareInfo.pendingTextMessage = true
shareInfo.lastSendTextMessageTime = obj.date shareInfo.lastSendTextMessageTime = obj.date
// location?.status = LocationMessages.LocationMessage.STATUS_PENDING
log.debug("handleTextLocationMessageUpdate - MessageSendingStatePending") log.debug("handleTextLocationMessageUpdate - MessageSendingStatePending")
outgoingMessagesListeners.forEach {
it.onUpdateMessages(listOf(obj))
}
} }
else -> { else -> {
shareInfo.hasSharingError = false shareInfo.hasSharingError = false
shareInfo.pendingTdLib--
shareInfo.pendingTextMessage = false shareInfo.pendingTextMessage = false
// location?.messageId = obj.id log.debug("handleTextLocationMessageUpdate - MessageSendingStateSuccess")
// location?.status = LocationMessages.LocationMessage.STATUS_SENT
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onUpdateMessages(listOf(obj)) it.onUpdateMessages(listOf(obj))
} }
@ -1464,9 +1470,9 @@ class TelegramHelper private constructor() {
} }
} }
TdApi.UpdateMessageSendSucceeded.CONSTRUCTOR -> { TdApi.UpdateMessageSendSucceeded.CONSTRUCTOR -> {
val udateMessageSendSucceeded = obj as TdApi.UpdateMessageSendSucceeded val updateSucceeded = obj as TdApi.UpdateMessageSendSucceeded
val message = udateMessageSendSucceeded.message val message = updateSucceeded.message
log.debug("UpdateMessageSendSucceeded: $message") log.debug("UpdateMessageSendSucceeded: ${message.id} oldId: ${updateSucceeded.oldMessageId}")
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onUpdateMessages(listOf(message)) it.onUpdateMessages(listOf(message))
} }

View file

@ -294,7 +294,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
} }
if (app.telegramService == null) { if (app.telegramService == null) {
messages.forEach { messages.forEach {
val locationMessage = OsmandLocationUtils.parseMessage(it, telegramHelper, LocationMessages.STATUS_PREPARED) val locationMessage = OsmandLocationUtils.parseMessage(it, telegramHelper)
if (locationMessage != null) { if (locationMessage != null) {
app.locationMessages.addIngoingMessage(locationMessage) app.locationMessages.addIngoingMessage(locationMessage)
} }

View file

@ -599,6 +599,9 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
} }
holder.title?.text = title holder.title?.text = title
holder.icon?.setOnClickListener {
app.forceUpdateMyLocation()
}
if (holder is ChatViewHolder) { if (holder is ChatViewHolder) {
holder.description?.visibility = View.GONE holder.description?.visibility = View.GONE
if (live) { if (live) {
@ -716,14 +719,12 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
} }
holder.gpsPointsCollected?.apply { holder.gpsPointsCollected?.apply {
if (shareInfo != null) { if (shareInfo != null) {
val all = app.locationMessages.getOutgoingMessages(shareInfo.chatId) text = "${shareInfo.collectedMessages}"
text = "${all.size}"
} }
} }
holder.gpsPointsSent?.apply { holder.gpsPointsSent?.apply {
if (shareInfo != null) { if (shareInfo != null) {
val sent = app.locationMessages.getSentMessages(shareInfo.chatId, shareInfo.start * 1000) text = "${shareInfo.sentMessages}"
text = "${sent.size}"
} }
} }
} }

View file

@ -190,22 +190,22 @@ class TimelineTabFragment : Fragment() {
val res = mutableListOf<ListItem>() val res = mutableListOf<ListItem>()
val ignoredUsersIds = ArrayList<Int>() val ignoredUsersIds = ArrayList<Int>()
val currentUserId = telegramHelper.getCurrentUser()?.id val currentUserId = telegramHelper.getCurrentUser()?.id
// if (currentUserId != null) { if (currentUserId != null) {
// val locationMessages = app.locationMessages.collectRecordedDataForUser(currentUserId, 0, start, end) val outgoingMessages = app.locationMessages.getOutgoingMessages(currentUserId, start, end)
// // todo - why do we need convert to gpx on update? Is locationMessages not enough to display info? // todo - why do we need convert to gpx on update? Is locationMessages not enough to display info?
// OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages, false).forEach { OsmandLocationUtils.convertLocationMessagesToGpxFiles(outgoingMessages, false).forEach {
// TelegramUiHelper.gpxToChatItem(telegramHelper, it, true)?.also { chatItem -> TelegramUiHelper.gpxToChatItem(telegramHelper, it, true)?.also { chatItem ->
// res.add(chatItem) res.add(chatItem)
// } }
// } }
// ignoredUsersIds.add(currentUserId) ignoredUsersIds.add(currentUserId)
// } val ingoingMessages = app.locationMessages.getIngoingMessages(currentUserId, start, end)
// val locationMessages = app.locationMessages.collectRecordedDataForUsers(start, end, ignoredUsersIds) OsmandLocationUtils.convertLocationMessagesToGpxFiles(ingoingMessages).forEach {
// OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages).forEach { TelegramUiHelper.gpxToChatItem(telegramHelper, it, false)?.also { chatItem ->
// TelegramUiHelper.gpxToChatItem(telegramHelper, it,false)?.also { chatItem -> res.add(chatItem)
// res.add(chatItem) }
// } }
// } }
adapter.items = sortAdapterItems(res) adapter.items = sortAdapterItems(res)
} }

View file

@ -4,8 +4,8 @@ import android.os.AsyncTask
import net.osmand.Location import net.osmand.Location
import net.osmand.telegram.TelegramApplication import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.helpers.LocationMessages import net.osmand.telegram.helpers.LocationMessages
import net.osmand.telegram.helpers.LocationMessages.LocationMessage
import net.osmand.telegram.helpers.LocationMessages.BufferMessage import net.osmand.telegram.helpers.LocationMessages.BufferMessage
import net.osmand.telegram.helpers.LocationMessages.LocationMessage
import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramHelper
import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.util.GeoPointParserUtil import net.osmand.util.GeoPointParserUtil
@ -76,7 +76,7 @@ object OsmandLocationUtils {
} }
} }
fun parseMessage(message: TdApi.Message, helper: TelegramHelper, status: Int): LocationMessage? { fun parseMessage(message: TdApi.Message, helper: TelegramHelper): LocationMessage? {
var locationMessage: LocationMessage? = null var locationMessage: LocationMessage? = null
val oldContent = message.content val oldContent = message.content
@ -88,17 +88,17 @@ object OsmandLocationUtils {
if (oldContent is TdApi.MessageText) { if (oldContent is TdApi.MessageText) {
when { when {
oldContent.text.text.startsWith(DEVICE_PREFIX) -> { oldContent.text.text.startsWith(DEVICE_PREFIX) -> {
messageType = 3 messageType = LocationMessages.TYPE_BOT_TEXT
parseTextLocation(oldContent.text) parseTextLocation(oldContent.text)
} }
oldContent.text.text.startsWith(USER_TEXT_LOCATION_TITLE) -> { oldContent.text.text.startsWith(USER_TEXT_LOCATION_TITLE) -> {
messageType = 1 messageType = LocationMessages.TYPE_USER_TEXT
parseTextLocation(oldContent.text, false) parseTextLocation(oldContent.text, false)
} }
else -> null else -> null
} }
} else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) { } else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) {
messageType = 2 messageType = LocationMessages.TYPE_BOT_MAP
parseOsmAndBotLocation(message) parseOsmAndBotLocation(message)
} else if (oldContent is MessageLocation) { } else if (oldContent is MessageLocation) {
messageType = 0 messageType = 0
@ -111,6 +111,10 @@ object OsmandLocationUtils {
locationMessage = LocationMessage(helper.getSenderMessageId(message), message.chatId, parsedMessageContent.lat, locationMessage = LocationMessage(helper.getSenderMessageId(message), message.chatId, parsedMessageContent.lat,
parsedMessageContent.lon, parsedMessageContent.altitude, parsedMessageContent.speed, parsedMessageContent.hdop, parsedMessageContent.lon, parsedMessageContent.altitude, parsedMessageContent.speed, parsedMessageContent.hdop,
parsedMessageContent.bearing, parsedMessageContent.lastUpdated * 1000L, messageType) parsedMessageContent.bearing, parsedMessageContent.lastUpdated * 1000L, messageType)
} else if(oldContent is TdApi.MessageLocation){
locationMessage = LocationMessage(helper.getSenderMessageId(message), message.chatId, oldContent.location.latitude,
oldContent.location.longitude, 0.0, 0.0, 0.0,
0.0, getLastUpdatedTime(message) * 1000L, LocationMessages.TYPE_USER_MAP)
} }
return locationMessage return locationMessage
} }
@ -139,12 +143,13 @@ object OsmandLocationUtils {
lat = messageLocation.location.latitude lat = messageLocation.location.latitude
lon = messageLocation.location.longitude lon = messageLocation.location.longitude
lastUpdated = (System.currentTimeMillis() / 1000).toInt() lastUpdated = (System.currentTimeMillis() / 1000).toInt()
type = LocationMessages.TYPE_BOT_MAP
} }
} }
fun parseTextLocation(text: TdApi.FormattedText, botLocation: Boolean = true): MessageLocation { fun parseTextLocation(text: TdApi.FormattedText, botLocation: Boolean = true): MessageLocation {
val res = if (botLocation) MessageOsmAndBotLocation() else MessageUserTextLocation() val res = if (botLocation) MessageOsmAndBotLocation() else MessageUserTextLocation()
res.type = if (botLocation) LocationMessages.TYPE_BOT_TEXT else LocationMessages.TYPE_USER_TEXT
var locationNA = false var locationNA = false
for (s in text.text.lines()) { for (s in text.text.lines()) {
when { when {
@ -310,9 +315,9 @@ object OsmandLocationUtils {
builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt())) builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt()))
} }
if (updateId == 0) { if (updateId == 0) {
builder.append(String.format("$UPDATED_PREFIX%s\n", formatFullTime(location.date))) builder.append(String.format("$UPDATED_PREFIX%s\n", formatFullTime(location.time)))
} else { } else {
builder.append(String.format("$UPDATED_PREFIX%s (%d)\n", formatFullTime(location.date), updateId)) builder.append(String.format("$UPDATED_PREFIX%s (%d)\n", formatFullTime(location.time), updateId))
} }
val textMessage = builder.toString().trim() val textMessage = builder.toString().trim()
@ -349,9 +354,9 @@ object OsmandLocationUtils {
builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt())) builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt()))
} }
if (updateId == 0) { if (updateId == 0) {
builder.append(String.format("$UPDATED_PREFIX%s\n", formatFullTime(location.date))) builder.append(String.format("$UPDATED_PREFIX%s\n", formatFullTime(location.time)))
} else { } else {
builder.append(String.format("$UPDATED_PREFIX%s (%d)\n", formatFullTime(location.date), updateId)) builder.append(String.format("$UPDATED_PREFIX%s (%d)\n", formatFullTime(location.time), updateId))
} }
val textMessage = builder.toString().trim() val textMessage = builder.toString().trim()
@ -371,7 +376,7 @@ object OsmandLocationUtils {
items.forEach { items.forEach {
val userId = it.userId val userId = it.userId
val chatId = it.chatId val chatId = it.chatId
val time = it.date val time = it.time
if (previousUserId != userId || (newGpxPerChat && previousChatId != chatId)) { if (previousUserId != userId || (newGpxPerChat && previousChatId != chatId)) {
gpx = GPXUtilities.GPXFile() gpx = GPXUtilities.GPXFile()
gpx!!.chatId = chatId gpx!!.chatId = chatId
@ -439,6 +444,8 @@ object OsmandLocationUtils {
internal set internal set
var bearing: Double = 0.0 var bearing: Double = 0.0
internal set internal set
var type: Int = -1
internal set
override fun getConstructor() = -1 override fun getConstructor() = -1