Add ability to send location messages via bot

This commit is contained in:
Chumva 2018-10-26 17:06:30 +03:00
parent 7a33de1c0d
commit aff20dbc2b
6 changed files with 135 additions and 17 deletions

View file

@ -84,6 +84,7 @@ class TelegramSettings(private val app: TelegramApplication) {
var sharingStatusChanges = ConcurrentLinkedQueue<SharingStatus>()
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"
}
}
}

View file

@ -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<Long, TelegramSettings.ShareChatInfo>) {
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<Long, TelegramSettings.ShareChatInfo>, 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)

View file

@ -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

View file

@ -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())
}
}
}

View file

@ -209,7 +209,7 @@ class SettingsDialogFragment : BaseDialogFragment() {
isChecked = checked
}
setOnClickListener {
settings.currentSharingMode = tag
settings.updateCurrentSharingMode(tag)
updateSelectedSharingMode()
}
this.tag = tag

View file

@ -55,16 +55,17 @@ class SharingStatusBottomSheet : DialogFragment() {
findViewById<TextView>(R.id.status_change_time).text = OsmandFormatter.getFormattedTime(sharingStatus.statusChangeTime, false)
findViewById<TextView>(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<TextView>(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<TextView>(R.id.last_location_line_time).text = descriptionTime
}
findViewById<TextView>(R.id.last_location_line_time).text = descriptionTime
} else {
findViewById<TextView>(R.id.last_location_line_time).visibility = View.GONE
}