diff --git a/CHANGELOG.md b/CHANGELOG.md index f39c66dac2..69d289ea47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,24 @@ * Limits for dices has been changed * `commonDiceResultLimit` has been deprecated * New field `DiceAnimationType#valueLimits` + * Locations updates: + * New interface `Headed` with property `heading` + * New interface `HorizontallyAccured` with property `horizontalAccuracy` + * New interface `ProximityAlertable` with property `proximityAlertRadius` + * `Location` class has been separated: + * `StaticLocation` for static locations + * `LiveLocation` for live locations + * Property `Livable#livePeriod` now use typealias type `Seconds` (the same by meaning - `Int`) + * `EditLocationMessage` now extends `Locationed`, `HorizontallyAccured`, `ProximityAlertable` and `Headed` interfaces + * New properties in `EditChatMessageLiveLocation`: `horizontalAccuracy`, `heading`, `proximityAlertRadius` + * New properties in `EditInlineMessageLiveLocation`: `horizontalAccuracy`, `heading`, `proximityAlertRadius` + * Main constructor of `SendLocation` now is internal. Instead of that currently available next factories: + * `SendLocation` - sending of static location without live parameters + * `SendStaticLocation` - sending of static location without live parameters + * `SendLiveLocation` - sending of live location with live parameters + * `PositionedSendMessageRequest` now extends `Locationed` + * `LocationContent#createResend` now can create `LiveLocation` + * Support of `ProximityAlertTriggered`. It is `CommonEvent` * `API`: * Extensions `TelegramBot#pinChatMessage` now support any `Chat` and `Message`s from any `Chat` * New extensions `TelegramBot#unpinAllChatMessages` diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/Headed.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/Headed.kt new file mode 100644 index 0000000000..629c19c285 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/Headed.kt @@ -0,0 +1,7 @@ +package dev.inmo.tgbotapi.CommonAbstracts + +import dev.inmo.tgbotapi.types.Degrees + +interface Headed { + val heading: Degrees? +} \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/HorizontallyAccured.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/HorizontallyAccured.kt new file mode 100644 index 0000000000..6f64e012a1 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/HorizontallyAccured.kt @@ -0,0 +1,7 @@ +package dev.inmo.tgbotapi.CommonAbstracts + +import dev.inmo.tgbotapi.types.Meters + +interface HorizontallyAccured { + val horizontalAccuracy: Meters? +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/Livable.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/Livable.kt index 228adeb9f8..2eef14eea2 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/Livable.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/Livable.kt @@ -1,8 +1,10 @@ package dev.inmo.tgbotapi.CommonAbstracts +import dev.inmo.tgbotapi.types.Seconds + interface Livable { /** - * Period in SECONDS + * Period in [Seconds] */ - val livePeriod: Int? + val livePeriod: Seconds? } \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/ProximityAlertable.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/ProximityAlertable.kt new file mode 100644 index 0000000000..413ff99b87 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/ProximityAlertable.kt @@ -0,0 +1,7 @@ +package dev.inmo.tgbotapi.CommonAbstracts + +import dev.inmo.tgbotapi.types.Meters + +interface ProximityAlertable { + val proximityAlertRadius: Meters? +} \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/LiveLocation/EditChatMessageLiveLocation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/LiveLocation/EditChatMessageLiveLocation.kt index 0bc1869d0d..ba93fd4206 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/LiveLocation/EditChatMessageLiveLocation.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/LiveLocation/EditChatMessageLiveLocation.kt @@ -6,6 +6,7 @@ import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass import dev.inmo.tgbotapi.types.message.content.LocationContent +import dev.inmo.tgbotapi.utils.throwRangeError import kotlinx.serialization.* private val commonResultDeserializer = TelegramBotAPIMessageDeserializationStrategyClass>() @@ -20,6 +21,12 @@ data class EditChatMessageLiveLocation( override val latitude: Double, @SerialName(longitudeField) override val longitude: Double, + @SerialName(horizontalAccuracyField) + override val horizontalAccuracy: Meters? = null, + @SerialName(headingField) + override val heading: Degrees? = null, + @SerialName(proximityAlertRadiusField) + override val proximityAlertRadius: Meters? = null, @SerialName(replyMarkupField) override val replyMarkup: InlineKeyboardMarkup? = null ) : EditChatMessage, EditReplyMessage, EditLocationMessage { @@ -28,4 +35,10 @@ data class EditChatMessageLiveLocation( get() = commonResultDeserializer override val requestSerializer: SerializationStrategy<*> get() = serializer() + + init { + if (horizontalAccuracy != null && horizontalAccuracy !in horizontalAccuracyLimit) { + throwRangeError("horizontalAccuracy", horizontalAccuracyLimit, horizontalAccuracy) + } + } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/LiveLocation/EditInlineMessageLiveLocation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/LiveLocation/EditInlineMessageLiveLocation.kt index 60bcf9a122..f12c2d522d 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/LiveLocation/EditInlineMessageLiveLocation.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/LiveLocation/EditInlineMessageLiveLocation.kt @@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.requests.edit.LiveLocation import dev.inmo.tgbotapi.requests.edit.abstracts.* import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup +import dev.inmo.tgbotapi.utils.throwRangeError import kotlinx.serialization.* @Serializable @@ -13,10 +14,22 @@ data class EditInlineMessageLiveLocation( override val latitude: Double, @SerialName(longitudeField) override val longitude: Double, + @SerialName(horizontalAccuracyField) + override val horizontalAccuracy: Meters? = null, + @SerialName(headingField) + override val heading: Degrees? = null, + @SerialName(proximityAlertRadiusField) + override val proximityAlertRadius: Meters? = null, @SerialName(replyMarkupField) override val replyMarkup: InlineKeyboardMarkup? = null ) : EditInlineMessage, EditReplyMessage, EditLocationMessage { override fun method(): String = "editMessageLiveLocation" override val requestSerializer: SerializationStrategy<*> get() = serializer() + + init { + if (horizontalAccuracy != null && horizontalAccuracy !in horizontalAccuracyLimit) { + throwRangeError("horizontalAccuracy", horizontalAccuracyLimit, horizontalAccuracy) + } + } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/abstracts/EditLocationMessage.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/abstracts/EditLocationMessage.kt index b41276c47d..853d39ee5b 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/abstracts/EditLocationMessage.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/edit/abstracts/EditLocationMessage.kt @@ -1,6 +1,5 @@ package dev.inmo.tgbotapi.requests.edit.abstracts -interface EditLocationMessage { - val latitude: Double - val longitude: Double -} +import dev.inmo.tgbotapi.CommonAbstracts.* + +interface EditLocationMessage : Locationed, HorizontallyAccured, ProximityAlertable, Headed diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/SendLocation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/SendLocation.kt index 9a765ca175..ef44f81ab0 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/SendLocation.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/SendLocation.kt @@ -1,19 +1,74 @@ package dev.inmo.tgbotapi.requests.send +import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass import dev.inmo.tgbotapi.types.message.content.LocationContent +import dev.inmo.tgbotapi.utils.throwRangeError import kotlinx.serialization.* private val commonResultDeserializer: DeserializationStrategy> = TelegramBotAPIMessageDeserializationStrategyClass() +fun SendLocation( + chatId: ChatIdentifier, + latitude: Double, + longitude: Double, + disableNotification: Boolean = false, + replyToMessageId: MessageIdentifier? = null, + replyMarkup: KeyboardMarkup? = null +) = SendLocation( + chatId, + latitude, + longitude, + null, + null, + null, + null, + disableNotification, + replyToMessageId, + replyMarkup +) + +fun SendStaticLocation( + chatId: ChatIdentifier, + latitude: Double, + longitude: Double, + disableNotification: Boolean = false, + replyToMessageId: MessageIdentifier? = null, + replyMarkup: KeyboardMarkup? = null +) = SendLocation(chatId, latitude, longitude, disableNotification, replyToMessageId, replyMarkup) + +fun SendLiveLocation( + chatId: ChatIdentifier, + latitude: Double, + longitude: Double, + livePeriod: Seconds, + horizontalAccuracy: Meters? = null, + heading: Degrees? = null, + proximityAlertRadius: Meters? = null, + disableNotification: Boolean = false, + replyToMessageId: MessageIdentifier? = null, + replyMarkup: KeyboardMarkup? = null +) = SendLocation( + chatId, + latitude, + longitude, + livePeriod, + horizontalAccuracy, + heading, + proximityAlertRadius, + disableNotification, + replyToMessageId, + replyMarkup +) + @Serializable -data class SendLocation( +data class SendLocation internal constructor( @SerialName(chatIdField) override val chatId: ChatIdentifier, @SerialName(latitudeField) @@ -21,7 +76,13 @@ data class SendLocation( @SerialName(longitudeField) override val longitude: Double, @SerialName(livePeriodField) - val livePeriod: Long? = null, + override val livePeriod: Seconds? = null, + @SerialName(horizontalAccuracyField) + override val horizontalAccuracy: Meters? = null, + @SerialName(headingField) + override val heading: Degrees? = null, + @SerialName(proximityAlertRadiusField) + override val proximityAlertRadius: Meters? = null, @SerialName(disableNotificationField) override val disableNotification: Boolean = false, @SerialName(replyToMessageIdField) @@ -30,7 +91,11 @@ data class SendLocation( override val replyMarkup: KeyboardMarkup? = null ) : SendMessageRequest>, ReplyingMarkupSendMessageRequest>, - PositionedSendMessageRequest> + PositionedSendMessageRequest>, + HorizontallyAccured, + Livable, + ProximityAlertable, + Headed { override fun method(): String = "sendLocation" override val resultDeserializer: DeserializationStrategy> @@ -42,5 +107,8 @@ data class SendLocation( if (livePeriod != null && livePeriod !in livePeriodLimit) { error("Live period for sending location must be in $livePeriodLimit, but was $livePeriod") } + if (horizontalAccuracy != null && horizontalAccuracy !in horizontalAccuracyLimit) { + throwRangeError("horizontalAccuracy", horizontalAccuracyLimit, horizontalAccuracy) + } } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/abstracts/PositionedSendMessageRequest.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/abstracts/PositionedSendMessageRequest.kt index e2823f307e..533d2b515d 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/abstracts/PositionedSendMessageRequest.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/abstracts/PositionedSendMessageRequest.kt @@ -1,6 +1,5 @@ package dev.inmo.tgbotapi.requests.send.abstracts -interface PositionedSendMessageRequest: SendMessageRequest { - val latitude: Double - val longitude: Double -} \ No newline at end of file +import dev.inmo.tgbotapi.CommonAbstracts.Locationed + +interface PositionedSendMessageRequest: SendMessageRequest, Locationed \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/ChatLocation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/ChatLocation.kt index 76c6558d0a..3d24f1eb8f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/ChatLocation.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/ChatLocation.kt @@ -1,5 +1,6 @@ package dev.inmo.tgbotapi.types +import dev.inmo.tgbotapi.types.location.StaticLocation import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -12,7 +13,7 @@ import kotlinx.serialization.Serializable @Serializable data class ChatLocation( @SerialName(locationField) - val location: Location, + val location: StaticLocation, @SerialName(addressField) val address: String ) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt index c113b6be23..76ec3d21c3 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt @@ -28,6 +28,12 @@ typealias FoursquareType = String typealias Seconds = Int typealias LongSeconds = Long +typealias Meters = Float +typealias Degrees = Int + +val degreesLimit = 1 .. 360 +val horizontalAccuracyLimit = 0F .. 1500F + val getUpdatesLimit = 1 .. 100 val callbackQueryAnswerLength = 0 until 200 val captionLength = 0 .. 1024 @@ -93,6 +99,7 @@ const val replyMarkupField = "reply_markup" const val disableContentTypeDetectionField = "disable_content_type_detection" const val supportStreamingField = "support_streaming" const val livePeriodField = "live_period" +const val proximityAlertRadiusField = "proximity_alert_radius" const val isBotField = "is_bot" const val firstNameField = "first_name" const val lastNameField = "last_name" @@ -152,6 +159,7 @@ const val customTitleField = "custom_title" const val optionIdsField = "option_ids" const val ipAddressField = "ip_address" const val linkedChatIdField = "linked_chat_id" +const val horizontalAccuracyField = "horizontal_accuracy" const val requestContactField = "request_contact" const val requestLocationField = "request_location" @@ -249,6 +257,7 @@ const val heightField = "height" const val lengthField = "length" const val latitudeField = "latitude" const val longitudeField = "longitude" +const val headingField = "heading" const val fromField = "from" const val userField = "user" const val dateField = "date" diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/ChosenInlineResult/LocationChosenInlineResult.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/ChosenInlineResult/LocationChosenInlineResult.kt index 92623a6402..16324e7e85 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/ChosenInlineResult/LocationChosenInlineResult.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/ChosenInlineResult/LocationChosenInlineResult.kt @@ -2,11 +2,12 @@ package dev.inmo.tgbotapi.types.InlineQueries.ChosenInlineResult import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.InlineQueries.abstracts.ChosenInlineResult +import dev.inmo.tgbotapi.types.location.StaticLocation data class LocationChosenInlineResult( override val resultId: InlineQueryIdentifier, override val user: User, - val location: Location, + val location: StaticLocation, override val inlineMessageId: InlineMessageIdentifier?, override val query: String ) : ChosenInlineResult diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/ChosenInlineResult/RawChosenInlineResult.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/ChosenInlineResult/RawChosenInlineResult.kt index 4900c189b4..4db078be40 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/ChosenInlineResult/RawChosenInlineResult.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/ChosenInlineResult/RawChosenInlineResult.kt @@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.InlineQueries.ChosenInlineResult import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.InlineQueries.abstracts.ChosenInlineResult +import dev.inmo.tgbotapi.types.location.StaticLocation import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -14,7 +15,7 @@ internal data class RawChosenInlineResult( @SerialName(queryField) val query: String, @SerialName(locationField) - val location: Location? = null, + val location: StaticLocation? = null, @SerialName(inlineMessageIdField) val inlineMessageId: InlineMessageIdentifier? = null ) { diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/InlineQueryResult/InlineQueryResultLocation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/InlineQueryResult/InlineQueryResultLocation.kt index e7eebe43ab..5b6d19776f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/InlineQueryResult/InlineQueryResultLocation.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/InlineQueryResult/InlineQueryResultLocation.kt @@ -1,7 +1,6 @@ package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult -import dev.inmo.tgbotapi.CommonAbstracts.Livable -import dev.inmo.tgbotapi.CommonAbstracts.Locationed +import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.* import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InputMessageContent @@ -17,10 +16,16 @@ data class InlineQueryResultLocation( override val latitude: Double, @SerialName(longitudeField) override val longitude: Double, + @SerialName(horizontalAccuracyField) + override val horizontalAccuracy: Meters? = null, @SerialName(titleField) override val title: String, @SerialName(livePeriodField) - override val livePeriod: Int? = null, + override val livePeriod: Seconds? = null, + @SerialName(headingField) + override val heading: Degrees? = null, + @SerialName(proximityAlertRadiusField) + override val proximityAlertRadius: Meters? = null, @SerialName(thumbUrlField) override val thumbUrl: String? = null, @SerialName(thumbWidthField) @@ -33,7 +38,10 @@ data class InlineQueryResultLocation( override val inputMessageContent: InputMessageContent? = null ) : InlineQueryResult, Locationed, + HorizontallyAccured, Livable, + ProximityAlertable, + Headed, TitledInlineQueryResult, WithInputMessageContentInlineQueryResult, ThumbedInlineQueryResult, diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/InputMessageContent/InputLocationMessageContent.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/InputMessageContent/InputLocationMessageContent.kt index 9096ab0eac..eda3152abf 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/InputMessageContent/InputLocationMessageContent.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/InputMessageContent/InputLocationMessageContent.kt @@ -1,7 +1,6 @@ package dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent -import dev.inmo.tgbotapi.CommonAbstracts.Livable -import dev.inmo.tgbotapi.CommonAbstracts.Locationed +import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InputMessageContent import kotlinx.serialization.SerialName @@ -13,6 +12,12 @@ data class InputLocationMessageContent( override val latitude: Double, @SerialName(longitudeField) override val longitude: Double, + @SerialName(horizontalAccuracyField) + override val horizontalAccuracy: Meters? = null, @SerialName(livePeriodField) - override val livePeriod: Int? = null -) : Locationed, Livable, InputMessageContent \ No newline at end of file + override val livePeriod: Seconds? = null, + @SerialName(headingField) + override val heading: Degrees? = null, + @SerialName(proximityAlertRadiusField) + override val proximityAlertRadius: Meters? = null +) : Locationed, HorizontallyAccured, ProximityAlertable, Livable, Headed, InputMessageContent \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/query/LocationInlineQuery.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/query/LocationInlineQuery.kt index 260eb39cc2..cc0cd4772d 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/query/LocationInlineQuery.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/query/LocationInlineQuery.kt @@ -2,11 +2,12 @@ package dev.inmo.tgbotapi.types.InlineQueries.query import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InlineQuery +import dev.inmo.tgbotapi.types.location.StaticLocation data class LocationInlineQuery( override val id: InlineQueryIdentifier, override val from: User, override val query: String, override val offset: String, - val location: Location + val location: StaticLocation ) : InlineQuery diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/query/RawInlineQuery.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/query/RawInlineQuery.kt index 2d15827909..2b4473486a 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/query/RawInlineQuery.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/query/RawInlineQuery.kt @@ -1,6 +1,7 @@ package dev.inmo.tgbotapi.types.InlineQueries.query import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.location.StaticLocation import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -15,7 +16,7 @@ internal data class RawInlineQuery( @SerialName(offsetField) val offset: String, @SerialName(locationField) - val location: Location? = null + val location: StaticLocation? = null ) { val asInlineQuery by lazy { location ?.let { diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Location.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Location.kt deleted file mode 100644 index 0571bfaf1e..0000000000 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Location.kt +++ /dev/null @@ -1,13 +0,0 @@ -package dev.inmo.tgbotapi.types - -import dev.inmo.tgbotapi.CommonAbstracts.Locationed -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class Location( - @SerialName(longitudeField) - override val longitude: Double, - @SerialName(latitudeField) - override val latitude: Double -) : Locationed diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt new file mode 100644 index 0000000000..b8b9878429 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt @@ -0,0 +1,57 @@ +package dev.inmo.tgbotapi.types.location + +import dev.inmo.tgbotapi.CommonAbstracts.* +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.utils.nonstrictJsonFormat +import kotlinx.serialization.* +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.JsonObject + +@Serializable(LocationSerializer::class) +sealed class Location : Locationed, HorizontallyAccured + +@Serializable +data class StaticLocation( + @SerialName(longitudeField) + override val longitude: Double, + @SerialName(latitudeField) + override val latitude: Double, + @SerialName(horizontalAccuracyField) + override val horizontalAccuracy: Meters? = null +) : Location() + +@Serializable +data class LiveLocation( + @SerialName(longitudeField) + override val longitude: Double, + @SerialName(latitudeField) + override val latitude: Double, + @SerialName(horizontalAccuracyField) + override val horizontalAccuracy: Meters? = null, + @SerialName(livePeriodField) + override val livePeriod: Seconds, + @SerialName(headingField) + override val heading: Degrees? = null, + @SerialName(proximityAlertRadiusField) + override val proximityAlertRadius: Meters? = null +) : Location(), Livable, ProximityAlertable, Headed + +@Serializer(Location::class) +object LocationSerializer : KSerializer { + override fun deserialize(decoder: Decoder): Location = JsonObject.serializer().deserialize(decoder).let { + if (it.containsKey(livePeriodField) && it[livePeriodField] != JsonNull) { + nonstrictJsonFormat.decodeFromJsonElement(LiveLocation.serializer(), it) + } else { + nonstrictJsonFormat.decodeFromJsonElement(StaticLocation.serializer(), it) + } + } + + override fun serialize(encoder: Encoder, value: Location) { + when (value) { + is StaticLocation -> StaticLocation.serializer().serialize(encoder, value) + is LiveLocation -> LiveLocation.serializer().serialize(encoder, value) + } + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ChatEvents/ProximityAlertTriggered.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ChatEvents/ProximityAlertTriggered.kt new file mode 100644 index 0000000000..557908240a --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ChatEvents/ProximityAlertTriggered.kt @@ -0,0 +1,16 @@ +package dev.inmo.tgbotapi.types.message.ChatEvents + +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.CommonEvent +import kotlinx.serialization.Serializable + +/** + * This object represents the content of a service message, sent whenever a user in the chat triggers a proximity alert + * set by another user. + */ +@Serializable +data class ProximityAlertTriggered( + val traveler: User, + val watcher: User, + val distance: Meters +) : CommonEvent diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt index 5f6991b77a..e771b4cdc1 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt @@ -8,6 +8,9 @@ import dev.inmo.tgbotapi.types.chat.abstracts.* import dev.inmo.tgbotapi.types.dice.Dice import dev.inmo.tgbotapi.types.files.* import dev.inmo.tgbotapi.types.games.RawGame +import dev.inmo.tgbotapi.types.location.Location +import dev.inmo.tgbotapi.types.message.ChatEvents.ProximityAlertTriggered +import dev.inmo.tgbotapi.types.location.StaticLocation import dev.inmo.tgbotapi.types.message.ChatEvents.* import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.* import dev.inmo.tgbotapi.types.message.abstracts.Message @@ -86,6 +89,7 @@ internal data class RawMessage( // passport property private val passport_data: Unit? = null, + private val proximity_alert_triggered: ProximityAlertTriggered? = null, private val reply_markup: InlineKeyboardMarkup? = null ) { @@ -180,6 +184,7 @@ internal data class RawMessage( ) channel_chat_created -> ChannelChatCreated() pinned_message != null -> PinnedMessage(pinned_message.asMessage) + proximity_alert_triggered != null -> proximity_alert_triggered else -> null } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/LocationContent.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/LocationContent.kt index 81f41ef536..f7a8750028 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/LocationContent.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/LocationContent.kt @@ -1,9 +1,10 @@ package dev.inmo.tgbotapi.types.message.content import dev.inmo.tgbotapi.requests.abstracts.Request -import dev.inmo.tgbotapi.requests.send.SendLocation +import dev.inmo.tgbotapi.requests.send.* import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup +import dev.inmo.tgbotapi.types.location.* import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent @@ -15,13 +16,26 @@ data class LocationContent( disableNotification: Boolean, replyToMessageId: MessageIdentifier?, replyMarkup: KeyboardMarkup? - ): Request> = SendLocation( - chatId, - location.latitude, - location.longitude, - null, - disableNotification, - replyToMessageId, - replyMarkup - ) + ): Request> = when (location) { + is StaticLocation -> SendStaticLocation( + chatId, + location.latitude, + location.longitude, + disableNotification, + replyToMessageId, + replyMarkup + ) + is LiveLocation -> SendLiveLocation( + chatId, + location.latitude, + location.longitude, + location.livePeriod, + location.horizontalAccuracy, + location.heading, + location.proximityAlertRadius, + disableNotification, + replyToMessageId, + replyMarkup + ) + } } \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/venue/Venue.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/venue/Venue.kt index 415a00e963..6482709d5c 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/venue/Venue.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/venue/Venue.kt @@ -3,13 +3,14 @@ package dev.inmo.tgbotapi.types.venue import dev.inmo.tgbotapi.CommonAbstracts.CommonVenueData import dev.inmo.tgbotapi.CommonAbstracts.Locationed import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.location.StaticLocation import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable data class Venue( @SerialName(locationField) - val location: Location, + val location: StaticLocation, @SerialName(titleField) override val title: String, @SerialName(addressField) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/ThrowErrorWithRange.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/ThrowErrorWithRange.kt index 88c9946627..03d00bc88b 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/ThrowErrorWithRange.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/ThrowErrorWithRange.kt @@ -1,7 +1,7 @@ package dev.inmo.tgbotapi.utils -internal fun throwRangeError( +internal fun > throwRangeError( valueName: String, - range: IntRange, - actualValue: Int + range: ClosedRange, + actualValue: T ): Nothing = error("$valueName must be in range $range, but was $actualValue") diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/LiveLocation.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/LiveLocation.kt index c480c38fe1..960993c312 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/LiveLocation.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/LiveLocation.kt @@ -13,6 +13,7 @@ import dev.inmo.tgbotapi.types.message.abstracts.Message import dev.inmo.tgbotapi.types.message.content.LocationContent import com.soywiz.klock.DateTime import com.soywiz.klock.TimeSpan +import dev.inmo.tgbotapi.types.location.StaticLocation import io.ktor.utils.io.core.Closeable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -39,13 +40,13 @@ class LiveLocation internal constructor( get() = field || leftUntilCloseMillis.millisecondsLong < 0L private var message: ContentMessage = initMessage - val lastLocation: Location + val lastLocation: StaticLocation get() = message.content.location suspend fun updateLocation( - location: Location, + location: StaticLocation, replyMarkup: InlineKeyboardMarkup? = null - ): Location { + ): StaticLocation { if (!isClosed) { message = requestsExecutor.editLiveLocation( message, @@ -114,7 +115,7 @@ suspend fun TelegramBot.startLiveLocation( suspend fun TelegramBot.startLiveLocation( scope: CoroutineScope, chatId: ChatId, - location: Location, + location: StaticLocation, liveTimeMillis: Long = defaultLivePeriodDelayMillis, disableNotification: Boolean = false, replyToMessageId: MessageIdentifier? = null, @@ -126,7 +127,7 @@ suspend fun TelegramBot.startLiveLocation( suspend fun TelegramBot.startLiveLocation( scope: CoroutineScope, chat: Chat, - location: Location, + location: StaticLocation, liveTimeMillis: Long = defaultLivePeriodDelayMillis, disableNotification: Boolean = false, replyToMessageId: MessageIdentifier? = null, @@ -148,7 +149,7 @@ suspend inline fun TelegramBot.replyWithLiveLocation( suspend inline fun TelegramBot.replyWithLiveLocation( to: Message, scope: CoroutineScope, - location: Location, + location: StaticLocation, liveTimeMillis: Long = defaultLivePeriodDelayMillis, disableNotification: Boolean = false, replyMarkup: KeyboardMarkup? = null diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/LiveLocation/EditChatMessageLiveLocation.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/LiveLocation/EditChatMessageLiveLocation.kt index 29b62ec4ff..f17ba6b8aa 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/LiveLocation/EditChatMessageLiveLocation.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/LiveLocation/EditChatMessageLiveLocation.kt @@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.requests.edit.LiveLocation.EditChatMessageLiveLocation import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup import dev.inmo.tgbotapi.types.chat.abstracts.Chat +import dev.inmo.tgbotapi.types.location.StaticLocation import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.content.LocationContent @@ -38,7 +39,7 @@ suspend fun TelegramBot.editLiveLocation( suspend fun TelegramBot.editLiveLocation( chatId: ChatIdentifier, messageId: MessageIdentifier, - location: Location, + location: StaticLocation, replyMarkup: InlineKeyboardMarkup? = null ) = execute( EditChatMessageLiveLocation( @@ -49,12 +50,12 @@ suspend fun TelegramBot.editLiveLocation( suspend fun TelegramBot.editLiveLocation( chat: Chat, messageId: MessageIdentifier, - location: Location, + location: StaticLocation, replyMarkup: InlineKeyboardMarkup? = null ) = editLiveLocation(chat.id, messageId, location.latitude, location.longitude, replyMarkup) suspend fun TelegramBot.editLiveLocation( message: ContentMessage, - location: Location, + location: StaticLocation, replyMarkup: InlineKeyboardMarkup? = null ) = editLiveLocation(message.chat, message.messageId, location.latitude, location.longitude, replyMarkup) diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/LiveLocation/EditInlineMessageLiveLocation.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/LiveLocation/EditInlineMessageLiveLocation.kt index fc0520b248..a518941806 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/LiveLocation/EditInlineMessageLiveLocation.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/edit/LiveLocation/EditInlineMessageLiveLocation.kt @@ -3,7 +3,7 @@ package dev.inmo.tgbotapi.extensions.api.edit.LiveLocation import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.requests.edit.LiveLocation.EditInlineMessageLiveLocation import dev.inmo.tgbotapi.types.InlineMessageIdentifier -import dev.inmo.tgbotapi.types.Location +import dev.inmo.tgbotapi.types.location.StaticLocation import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup suspend fun TelegramBot.editLiveLocation( @@ -18,6 +18,6 @@ suspend fun TelegramBot.editLiveLocation( ) suspend fun TelegramBot.editLiveLocation( inlineMessageId: InlineMessageIdentifier, - location: Location, + location: StaticLocation, replyMarkup: InlineKeyboardMarkup? = null ) = editLiveLocation(inlineMessageId, location.latitude, location.longitude, replyMarkup) diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/SendLocation.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/SendLocation.kt index b67be97035..a9abc0c4cb 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/SendLocation.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/SendLocation.kt @@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.requests.send.SendLocation import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.chat.abstracts.Chat +import dev.inmo.tgbotapi.types.location.StaticLocation import dev.inmo.tgbotapi.types.message.abstracts.Message suspend fun TelegramBot.sendLocation( @@ -27,7 +28,7 @@ suspend fun TelegramBot.sendLocation( suspend fun TelegramBot.sendLocation( chatId: ChatIdentifier, - location: Location, + location: StaticLocation, disableNotification: Boolean = false, replyToMessageId: MessageIdentifier? = null, replyMarkup: KeyboardMarkup? = null @@ -58,7 +59,7 @@ suspend fun TelegramBot.sendLocation( suspend fun TelegramBot.sendLocation( chat: Chat, - location: Location, + location: StaticLocation, disableNotification: Boolean = false, replyToMessageId: MessageIdentifier? = null, replyMarkup: KeyboardMarkup? = null @@ -88,7 +89,7 @@ suspend inline fun TelegramBot.reply( suspend inline fun TelegramBot.reply( to: Message, - location: Location, + location: StaticLocation, disableNotification: Boolean = false, replyMarkup: KeyboardMarkup? = null ) = sendLocation( diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/SendVenue.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/SendVenue.kt index 08495ad015..e05b942a9b 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/SendVenue.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/send/SendVenue.kt @@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.requests.send.SendVenue import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.chat.abstracts.Chat +import dev.inmo.tgbotapi.types.location.StaticLocation import dev.inmo.tgbotapi.types.message.abstracts.Message import dev.inmo.tgbotapi.types.venue.Venue @@ -40,7 +41,7 @@ suspend fun TelegramBot.sendVenue( suspend fun TelegramBot.sendVenue( chatId: ChatIdentifier, - location: Location, + location: StaticLocation, title: String, address: String, foursquareId: String? = null, @@ -53,7 +54,7 @@ suspend fun TelegramBot.sendVenue( suspend fun TelegramBot.sendVenue( chat: Chat, - location: Location, + location: StaticLocation, title: String, address: String, foursquareId: String? = null, @@ -101,7 +102,7 @@ suspend inline fun TelegramBot.reply( suspend inline fun TelegramBot.reply( to: Message, - location: Location, + location: StaticLocation, title: String, address: String, foursquareId: String? = null, diff --git a/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/venue/Foursquare.kt b/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/venue/Foursquare.kt index 091c0fec86..3651bb2581 100644 --- a/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/venue/Foursquare.kt +++ b/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/venue/Foursquare.kt @@ -1,6 +1,7 @@ package dev.inmo.tgbotapi.extensions.utils.extensions.venue import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.location.StaticLocation import dev.inmo.tgbotapi.types.venue.Venue import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -11,7 +12,7 @@ val Venue.foursquare: Foursquare? } fun Venue( - location: Location, + location: StaticLocation, title: String, address: String, foursquare: Foursquare