diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt index 4ec4e839be..c487f33877 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt @@ -84,6 +84,7 @@ class TelegramSettings(private val app: TelegramApplication) { var sharingStatusChanges = ConcurrentLinkedQueue() var currentSharingMode = "" + private set var metricsConstants = MetricsConstants.KILOMETERS_AND_METERS var speedConstants = SpeedConstants.KILOMETERS_PER_HOUR @@ -138,6 +139,11 @@ class TelegramSettings(private val app: TelegramApplication) { shareChatInfo = ShareChatInfo() } val currentTime = System.currentTimeMillis() / 1000 + val user = app.telegramHelper.getCurrentUser() + if (user != null && currentSharingMode != user.id.toString() && shareChatInfo.start == -1L) { + shareChatInfo.shouldSendViaBotMessage = true + } + shareChatInfo.chatId = chatId shareChatInfo.start = currentTime if (shareChatInfo.livePeriod == -1L) { @@ -157,6 +163,15 @@ class TelegramSettings(private val app: TelegramApplication) { shareDevices = list.toHashSet() } + fun updateCurrentSharingMode(sharingMode: String) { + if (currentSharingMode != sharingMode) { + shareChatsInfo.forEach { (_, shareInfo) -> + shareInfo.shouldSendViaBotMessage = true + } + } + currentSharingMode = sharingMode + } + fun getChatLivePeriod(chatId: Long) = shareChatsInfo[chatId]?.livePeriod fun getChatsShareInfo() = shareChatsInfo @@ -172,6 +187,10 @@ class TelegramSettings(private val app: TelegramApplication) { return false } + fun getShareDeviceNameWithExternalId(externalId: String): String? { + return shareDevices.singleOrNull { it.externalId == externalId }?.deviceName + } + fun getLastSuccessfulSendTime() = shareChatsInfo.values.maxBy { it.lastSuccessfulSendTimeMs }?.lastSuccessfulSendTimeMs ?: -1 fun stopSharingLocationToChats() { @@ -279,6 +298,9 @@ class TelegramSettings(private val app: TelegramApplication) { when { !gpsEnabled -> { locationTime = app.shareLocationHelper.lastLocationMessageSentTime + if (locationTime <= 0) { + locationTime = getLastSuccessfulSendTime() + } title = app.getString(R.string.no_gps_connection) description = app.getString(R.string.last_updated_location) statusType = SharingStatusType.NO_GPS @@ -441,6 +463,7 @@ class TelegramSettings(private val app: TelegramApplication) { obj.put(ShareChatInfo.CURRENT_MESSAGE_ID_KEY, chatInfo.currentMessageId) obj.put(ShareChatInfo.USER_SET_LIVE_PERIOD_KEY, chatInfo.userSetLivePeriod) obj.put(ShareChatInfo.USER_SET_LIVE_PERIOD_START_KEY, chatInfo.userSetLivePeriodStart) + obj.put(ShareChatInfo.LAST_SUCCESSFUL_SEND_TIME_KEY, chatInfo.lastSuccessfulSendTimeMs) jArray.put(obj) } jArray @@ -461,6 +484,7 @@ class TelegramSettings(private val app: TelegramApplication) { currentMessageId = obj.optLong(ShareChatInfo.CURRENT_MESSAGE_ID_KEY) userSetLivePeriod = obj.optLong(ShareChatInfo.USER_SET_LIVE_PERIOD_KEY) userSetLivePeriodStart = obj.optLong(ShareChatInfo.USER_SET_LIVE_PERIOD_START_KEY) + lastSuccessfulSendTimeMs = obj.optLong(ShareChatInfo.LAST_SUCCESSFUL_SEND_TIME_KEY) } shareChatsInfo[shareInfo.chatId] = shareInfo } @@ -708,8 +732,9 @@ class TelegramSettings(private val app: TelegramApplication) { var lastSuccessfulLocation: LatLon? = null var lastSuccessfulSendTimeMs = -1L var shouldDeletePreviousMessage = false - var additionalActiveTime = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0] + var shouldSendViaBotMessage = false var hasSharingError = false + var additionalActiveTime = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0] fun getNextAdditionalActiveTime(): Long { var index = ADDITIONAL_ACTIVE_TIME_VALUES_SEC.indexOf(additionalActiveTime) @@ -733,6 +758,7 @@ class TelegramSettings(private val app: TelegramApplication) { internal const val CURRENT_MESSAGE_ID_KEY = "currentMessageId" internal const val USER_SET_LIVE_PERIOD_KEY = "userSetLivePeriod" internal const val USER_SET_LIVE_PERIOD_START_KEY = "userSetLivePeriodStart" + internal const val LAST_SUCCESSFUL_SEND_TIME_KEY = "lastSuccessfulSendTime" } } } \ No newline at end of file diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt index 7994dbdd70..71b220f91a 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt @@ -3,9 +3,13 @@ package net.osmand.telegram.helpers import net.osmand.Location import net.osmand.PlatformUtil import net.osmand.telegram.TelegramApplication +import net.osmand.telegram.TelegramSettings import net.osmand.telegram.notifications.TelegramNotification.NotificationType import net.osmand.telegram.utils.AndroidNetworkUtils import net.osmand.telegram.utils.BASE_URL +import org.drinkless.td.libcore.telegram.TdApi +import org.json.JSONException +import org.json.JSONObject private const val USER_SET_LIVE_PERIOD_DELAY_MS = 5000 // 5 sec @@ -47,13 +51,26 @@ class ShareLocationHelper(private val app: TelegramApplication) { if (location != null) { val chatsShareInfo = app.settings.getChatsShareInfo() if (chatsShareInfo.isNotEmpty()) { + val latitude = location.latitude + val longitude = location.longitude val user = app.telegramHelper.getCurrentUser() val sharingMode = app.settings.currentSharingMode + if (user != null && sharingMode == user.id.toString()) { - app.telegramHelper.sendLiveLocationMessage(chatsShareInfo, location.latitude, location.longitude) + app.telegramHelper.sendLiveLocationMessage(chatsShareInfo, latitude, longitude) } else if (sharingMode.isNotEmpty()) { - val url = "$BASE_URL/device/$sharingMode/send?lat=${location.latitude}&lon=${location.longitude}" - AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false, null) + val url = "$BASE_URL/device/$sharingMode/send?lat=$latitude&lon=$longitude" + AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false, + object : AndroidNetworkUtils.OnRequestResultListener { + override fun onResult(result: String?) { + updateShareInfoSuccessfulSendTime(result, chatsShareInfo) + } + }) + + val osmandBot = app.telegramHelper.getOsmandBot() + if (osmandBot != null) { + checkAndSendViaBotMessages(chatsShareInfo, TdApi.Location(latitude, longitude), osmandBot) + } } } lastLocationMessageSentTime = System.currentTimeMillis() @@ -133,6 +150,34 @@ class ShareLocationHelper(private val app: TelegramApplication) { refreshNotification() } + private fun updateShareInfoSuccessfulSendTime(result: String?, chatsShareInfo: Map) { + if (result != null) { + try { + val jsonResult = JSONObject(result) + val status = jsonResult.getString("status") + val currentTime = System.currentTimeMillis() + if (status == "OK") { + chatsShareInfo.forEach { (_, shareInfo) -> + shareInfo.lastSuccessfulSendTimeMs = currentTime + } + } + } catch (e: JSONException) { + } + } + } + + private fun checkAndSendViaBotMessages(chatsShareInfo: Map, location: TdApi.Location, osmandBot: TdApi.User) { + val deviceName = app.settings.getShareDeviceNameWithExternalId(app.settings.currentSharingMode) + if (deviceName != null) { + chatsShareInfo.forEach { (_, shareInfo) -> + if (shareInfo.shouldSendViaBotMessage) { + app.telegramHelper.sendViaBotLocationMessage(osmandBot.id, shareInfo, location, deviceName) + shareInfo.shouldSendViaBotMessage = false + } + } + } + } + private fun refreshNotification() { app.runInUIThread { app.notificationHelper.refreshNotification(NotificationType.LOCATION) diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt index cf21651e84..dd30557979 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt @@ -89,6 +89,7 @@ class TelegramHelper private constructor() { private var client: Client? = null private var currentUser: TdApi.User? = null + private var osmandBot: TdApi.User? = null private var haveFullChatList: Boolean = false private var needRefreshActiveLiveLocationMessages: Boolean = true @@ -144,6 +145,8 @@ class TelegramHelper private constructor() { fun getUser(id: Int) = users[id] + fun getOsmandBot() = osmandBot + fun getCurrentUser() = currentUser fun getUserMessage(user: TdApi.User) = @@ -480,6 +483,44 @@ class TelegramHelper private constructor() { } } + fun sendViaBotLocationMessage(userId: Int, shareInfo: TelegramSettings.ShareChatInfo, location: TdApi.Location, query: String) { + log.debug("sendViaBotLocationMessage - ${shareInfo.chatId}") + client?.send(TdApi.GetInlineQueryResults(userId, shareInfo.chatId, location, query, "")) { 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) + } else { + shareInfo.shouldSendViaBotMessage = true + } + } + TdApi.InlineQueryResults.CONSTRUCTOR -> { + sendViaBotMessageFromQueryResults(shareInfo, obj as TdApi.InlineQueryResults, query) + } + } + } + } + + private fun sendViaBotMessageFromQueryResults( + shareInfo: TelegramSettings.ShareChatInfo, + inlineQueryResults: TdApi.InlineQueryResults, + query: String + ) { + val queryResults = inlineQueryResults.results.asList() + if (queryResults.isNotEmpty()) { + val resultArticle = queryResults.firstOrNull { + (it is TdApi.InlineQueryResultArticle && it.id.startsWith("t") && it.title == query) + } + if (resultArticle != null && resultArticle is TdApi.InlineQueryResultArticle) { + client?.send(TdApi.SendInlineQueryResultMessage(shareInfo.chatId, 0, true, + true, inlineQueryResults.inlineQueryId, resultArticle.id)) { obj -> + handleLiveLocationMessageUpdate(obj, shareInfo) + } + } + } + } + private fun requestSupergroupFullInfo(id: Int) { client?.send(TdApi.GetSupergroupFullInfo(id)) { obj -> when (obj.constructor) { @@ -939,7 +980,8 @@ class TelegramHelper private constructor() { s.startsWith(UPDATED_PREFIX) -> { if (res.lastUpdated == 0) { val updatedStr = s.removePrefix(UPDATED_PREFIX) - val updatedS = updatedStr.substring(0, updatedStr.indexOf("(")) + val endIndex = updatedStr.indexOf("(") + val updatedS = updatedStr.substring(0, if (endIndex != -1) endIndex else updatedStr.length) res.lastUpdated = (parseTime(updatedS.trim()) / 1000).toInt() } } @@ -1036,7 +1078,11 @@ class TelegramHelper private constructor() { TdApi.UpdateUser.CONSTRUCTOR -> { val updateUser = obj as TdApi.UpdateUser - users[updateUser.user.id] = updateUser.user + val user = updateUser.user + users[updateUser.user.id] = user + if (isOsmAndBot(user.id)) { + osmandBot = user + } } TdApi.UpdateUserStatus.CONSTRUCTOR -> { val updateUserStatus = obj as TdApi.UpdateUserStatus diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt index 9d372ca24d..d3a84743d8 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt @@ -218,7 +218,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene if (user != null) { OsmandApiUtils.updateSharingDevices(app, user.id) if (settings.currentSharingMode.isEmpty()) { - settings.currentSharingMode = user.id.toString() + settings.updateCurrentSharingMode(user.id.toString()) } } } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt index 8a1734733d..c7e5dabcf8 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt @@ -209,7 +209,7 @@ class SettingsDialogFragment : BaseDialogFragment() { isChecked = checked } setOnClickListener { - settings.currentSharingMode = tag + settings.updateCurrentSharingMode(tag) updateSelectedSharingMode() } this.tag = tag diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/SharingStatusBottomSheet.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/SharingStatusBottomSheet.kt index 279c90b370..eaf2bc98b3 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/SharingStatusBottomSheet.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/SharingStatusBottomSheet.kt @@ -55,16 +55,17 @@ class SharingStatusBottomSheet : DialogFragment() { findViewById(R.id.status_change_time).text = OsmandFormatter.getFormattedTime(sharingStatus.statusChangeTime, false) findViewById(R.id.last_location_line).text = sharingStatus.description - if (sharingStatusType != TelegramSettings.SharingStatusType.INITIALIZING - && (sharingStatusType == TelegramSettings.SharingStatusType.SENDING && time != -1L)) { - val descriptionTime = when { - time > 0 -> OsmandFormatter.getFormattedTime(time, false) - sharingStatusType == TelegramSettings.SharingStatusType.NO_GPS -> getString( - R.string.not_found_yet - ) - else -> getString(R.string.not_sent_yet) + if (sharingStatusType != TelegramSettings.SharingStatusType.INITIALIZING) { + if ((sharingStatusType == TelegramSettings.SharingStatusType.SENDING && time <= 0)) { + findViewById(R.id.last_location_line_time).visibility = View.GONE + } else { + val descriptionTime = when { + time > 0 -> OsmandFormatter.getFormattedTime(time, false) + sharingStatusType == TelegramSettings.SharingStatusType.NO_GPS -> getString(R.string.not_found_yet) + else -> getString(R.string.not_sent_yet) + } + findViewById(R.id.last_location_line_time).text = descriptionTime } - findViewById(R.id.last_location_line_time).text = descriptionTime } else { findViewById(R.id.last_location_line_time).visibility = View.GONE }