1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-17 04:20:13 +00:00

Compare commits

..

20 Commits
2.0.3 ... 2.1.1

Author SHA1 Message Date
100a76a832 Update CHANGELOG.md 2022-06-26 13:36:13 +06:00
c583ae6761 replace all the edits into one file 2022-06-26 13:18:22 +06:00
7429ffb514 add TelegramBot#send extensions 2022-06-25 23:06:41 +06:00
95aeedfb94 Update DeleteMessage.kt 2022-06-25 18:34:41 +06:00
095e318a78 Update DeleteMessage.kt 2022-06-25 18:04:20 +06:00
4aa2d2ae41 Update gradle.properties 2022-06-25 03:13:46 +06:00
e936d25c13 TelegramBot#edit 2022-06-25 02:49:38 +06:00
97a2a5d9fd exists methods of editing text/caption improvements 2022-06-25 02:19:20 +06:00
00ab532eac start 2.1.1 2022-06-25 02:11:23 +06:00
c2cc6ee1ec Merge pull request #613 from InsanusMokrassar/2.1.0
2.1.0
2022-06-21 23:09:27 +06:00
d20b94e52c rename PremiumChat -> PossiblyPremiumChat 2022-06-21 23:06:36 +06:00
9f3cc6eafb add mention about 6.1 telegram bot api support 2022-06-21 18:58:01 +06:00
f86a095421 CreateInvoiceLink 2022-06-21 18:52:55 +06:00
b0c6b80d8b small improvements 2022-06-21 18:30:31 +06:00
1df653f428 SetWebhook#secretToken 2022-06-21 17:55:21 +06:00
8dfaca7648 CommonUser#addedToAttachmentMenu 2022-06-21 17:52:16 +06:00
04db76831f add support of premium fields 2022-06-21 17:34:14 +06:00
f2e9bf6bd8 update webapps support 2022-06-21 16:35:48 +06:00
cde8fdeffd start 2.1.0 2022-06-21 15:22:34 +06:00
e74f339ae2 Merge pull request #609 from InsanusMokrassar/2.0.3
2.0.3
2022-06-17 14:34:23 +06:00
38 changed files with 2232 additions and 44 deletions

View File

@@ -1,5 +1,27 @@
# TelegramBotAPI changelog
## 2.1.1
* `API`:
* Now it is possible to edit any message text via `editMessageText` (but with warning)
* Now it is possible to edit any message caption via `editMessageCaption` (but with warning)
* Media message caption edit method (`editMessageCaption`) now returns the message with the same generic type (as it must be in telegram system)
* New extensions `TelegramBot#edit` has been added for all possible editions types
* New extensions `TelegramBot#send` has been added for all possible sending types
* New extensions `TelegramBot#delete` has been added
* `Versions`:
* `MicroUtils`: `0.11.3` -> `0.11.6`
## 2.1.0
__This update contains including of [Telegram Bot API 6.1](https://core.telegram.org/bots/api-changelog#june-20-2022)__
* Add support of functionality for `WebApp`s from [Bot API 6.1](https://core.telegram.org/bots/api-changelog#june-20-2022)
* Add support of functionality for premium feature from [Bot API 6.1](https://core.telegram.org/bots/api-changelog#june-20-2022)
* Add support of `addedToAttachmentMenu` in `CommonUser` from [Bot API 6.1](https://core.telegram.org/bots/api-changelog#june-20-2022)
* Add support of `secret_token` in `SetWebhook` request from [Bot API 6.1](https://core.telegram.org/bots/api-changelog#june-20-2022)
* Add support of `createInvoiceLink` request from [Bot API 6.1](https://core.telegram.org/bots/api-changelog#june-20-2022)
## 2.0.3
* `Core`:

View File

@@ -1,4 +1,4 @@
# TelegramBotAPI [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [![Supported version](https://img.shields.io/badge/Telegram%20Bot%20API-6.0-blue)](https://core.telegram.org/bots/api-changelog#april-16-2022)
# TelegramBotAPI [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [![Supported version](https://img.shields.io/badge/Telegram%20Bot%20API-6.1-blue)](https://core.telegram.org/bots/api-changelog#june-20-2022)
| [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Build Status](https://github.com/InsanusMokrassar/TelegramBotAPI/workflows/Build/badge.svg)](https://github.com/InsanusMokrassar/TelegramBotAPI/actions) [![Small survey](https://img.shields.io/static/v1?label=Google&message=Survey&color=blue&logo=google-sheets)](https://docs.google.com/forms/d/e/1FAIpQLSctdJHT_aEniyYT0-IUAEfo1hsIlezX2owlkEAYX4KPl2V2_A/viewform?usp=sf_link) [![Chat in Telegram](https://img.shields.io/static/v1?label=Telegram&message=Chat&color=blue&logo=telegram)](https://t.me/InMoTelegramBotAPI) |
|:---:|

View File

@@ -12,7 +12,7 @@ korlibs_version=2.7.0
uuid_version=0.4.1
ktor_version=2.0.2
micro_utils_version=0.11.3
micro_utils_version=0.11.6
javax_activation_version=1.1.1
@@ -20,6 +20,6 @@ javax_activation_version=1.1.1
dokka_version=1.6.21
library_group=dev.inmo
library_version=2.0.3
library_version=2.1.1
github_release_plugin_version=2.4.1

View File

@@ -23,6 +23,20 @@ suspend fun TelegramBot.deleteMessage(
message: Message
) = deleteMessage(message.chat, message.messageId)
suspend fun TelegramBot.delete(
chatId: ChatIdentifier,
messageId: MessageIdentifier
) = deleteMessage(chatId, messageId)
suspend fun TelegramBot.delete(
chat: Chat,
messageId: MessageIdentifier
) = deleteMessage(chat, messageId)
suspend fun TelegramBot.delete(
message: Message
) = deleteMessage(message)
suspend fun Message.delete(
requestsExecutor: TelegramBot
) = requestsExecutor.deleteMessage(this)

View File

@@ -0,0 +1,207 @@
package dev.inmo.tgbotapi.extensions.api.edit
import dev.inmo.tgbotapi.abstracts.TextedWithTextSources
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.edit.caption.editMessageCaption
import dev.inmo.tgbotapi.extensions.api.edit.location.live.editLiveLocation
import dev.inmo.tgbotapi.extensions.api.edit.media.editMessageMedia
import dev.inmo.tgbotapi.extensions.api.edit.reply_markup.editMessageReplyMarkup
import dev.inmo.tgbotapi.extensions.api.edit.text.editMessageText
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.location.LiveLocation
import dev.inmo.tgbotapi.types.media.TelegramMedia
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.content.*
import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun <T> TelegramBot.edit(
message: ContentMessage<T>,
text: String,
parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null
): ContentMessage<T> where T : TextedWithTextSources, T : MediaContent {
return editMessageCaption(message, text, parseMode, replyMarkup)
}
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun <T> TelegramBot.edit(
message: ContentMessage<T>,
entities: List<TextSource>,
replyMarkup: InlineKeyboardMarkup? = null
): ContentMessage<T> where T : TextedWithTextSources, T : MediaContent {
return editMessageCaption(message, entities, replyMarkup)
}
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
chatId: ChatIdentifier,
messageId: MessageIdentifier,
latitude: Double,
longitude: Double,
horizontalAccuracy: Meters? = null,
heading: Degrees? = null,
proximityAlertRadius: Meters? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editLiveLocation(chatId, messageId, latitude, longitude, horizontalAccuracy, heading, proximityAlertRadius, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
chat: Chat,
messageId: MessageIdentifier,
latitude: Double,
longitude: Double,
horizontalAccuracy: Meters? = null,
heading: Degrees? = null,
proximityAlertRadius: Meters? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editLiveLocation(chat, messageId, latitude, longitude, horizontalAccuracy, heading, proximityAlertRadius, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
message: ContentMessage<LocationContent>,
latitude: Double,
longitude: Double,
horizontalAccuracy: Meters? = null,
heading: Degrees? = null,
proximityAlertRadius: Meters? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editLiveLocation(message, latitude, longitude, horizontalAccuracy, heading, proximityAlertRadius, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
chatId: ChatIdentifier,
messageId: MessageIdentifier,
location: LiveLocation,
replyMarkup: InlineKeyboardMarkup? = null
) = editLiveLocation(
chatId, messageId, location, replyMarkup
)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
chat: Chat,
messageId: MessageIdentifier,
location: LiveLocation,
replyMarkup: InlineKeyboardMarkup? = null
) = editLiveLocation(chat, messageId, location, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
message: ContentMessage<LocationContent>,
location: LiveLocation,
replyMarkup: InlineKeyboardMarkup? = null
) = editLiveLocation(message, location, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
chatId: ChatIdentifier,
messageId: MessageIdentifier,
media: TelegramMedia,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageMedia(chatId, messageId, media, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
chat: Chat,
messageId: MessageIdentifier,
media: TelegramMedia,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageMedia(chat, messageId, media, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
message: ContentMessage<MediaContent>,
media: TelegramMedia,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageMedia(message, media, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
chatId: ChatIdentifier,
messageId: MessageIdentifier,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageReplyMarkup(chatId, messageId, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
chat: Chat,
messageId: MessageIdentifier,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageReplyMarkup(chat, messageId, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
message: Message,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageReplyMarkup(message, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
message: ContentMessage<TextContent>,
text: String,
parseMode: ParseMode? = null,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageText(message, text, parseMode, disableWebPagePreview, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
message: ContentMessage<TextContent>,
entities: TextSourcesList,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageText(message, entities, disableWebPagePreview, replyMarkup)

View File

@@ -11,7 +11,9 @@ import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.content.MediaContent
import dev.inmo.tgbotapi.utils.RiskFeature
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
@@ -48,8 +50,9 @@ suspend fun <T> TelegramBot.editMessageCaption(
text: String,
parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null
): ContentMessage<MediaContent> where T : TextedWithTextSources, T : MediaContent {
return editMessageCaption(message.chat.id, message.messageId, text, parseMode, replyMarkup)
): ContentMessage<T> where T : TextedWithTextSources, T : MediaContent {
@Suppress("UNCHECKED_CAST")
return editMessageCaption(message.chat.id, message.messageId, text, parseMode, replyMarkup) as ContentMessage<T>
}
/**
@@ -84,6 +87,20 @@ suspend fun <T> TelegramBot.editMessageCaption(
message: ContentMessage<T>,
entities: List<TextSource>,
replyMarkup: InlineKeyboardMarkup? = null
): ContentMessage<T> where T : TextedWithTextSources, T : MediaContent {
@Suppress("UNCHECKED_CAST")
return editMessageCaption(message.chat.id, message.messageId, entities, replyMarkup) as ContentMessage<T>
}
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
@RiskFeature("This method is unsafe due to absence of any guaranties about the type of message. In case if message is not media message this method will throw an exception")
suspend fun <T> TelegramBot.editMessageCaption(
message: Message,
entities: List<TextSource>,
replyMarkup: InlineKeyboardMarkup? = null
): ContentMessage<MediaContent> where T : TextedWithTextSources, T : MediaContent {
return editMessageCaption(message.chat.id, message.messageId, entities, replyMarkup)
}

View File

@@ -9,7 +9,9 @@ import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.utils.RiskFeature
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
@@ -87,3 +89,15 @@ suspend fun TelegramBot.editMessageText(
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageText(message.chat.id, message.messageId, entities, disableWebPagePreview, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
@RiskFeature("This method is unsafe due to absence of any guaranties about the type of message. In case if message is not text message this method will throw an exception")
suspend fun TelegramBot.editMessageText(
message: Message,
entities: TextSourcesList,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageText(message.chat.id, message.messageId, entities, disableWebPagePreview, replyMarkup)

View File

@@ -22,7 +22,7 @@ suspend fun <T> TelegramBot.withAction(
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
val botActionJob = CoroutineScope(coroutineContext).launch {
val botActionJob = CoroutineScope(currentCoroutineContext()).launch {
while (isActive) {
delay(refreshTime)
safelyWithoutExceptions {

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
package dev.inmo.tgbotapi.extensions.api.send.payments
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.send.payments.CreateInvoiceLink
import dev.inmo.tgbotapi.requests.send.payments.SendInvoice
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.payments.LabeledPrice
import dev.inmo.tgbotapi.types.payments.abstracts.Currency
suspend fun TelegramBot.createInvoiceLink(
title: String,
description: String,
payload: String,
providerToken: String,
currency: Currency,
prices: List<LabeledPrice>,
maxTipAmount: Int? = null,
suggestedTipAmounts: List<Int>? = null,
providerData: String? = null,
requireName: Boolean = false,
requirePhoneNumber: Boolean = false,
requireEmail: Boolean = false,
requireShippingAddress: Boolean = false,
shouldSendPhoneNumberToProvider: Boolean = false,
shouldSendEmailToProvider: Boolean = false,
priceDependOnShipAddress: Boolean = false
) = execute(
CreateInvoiceLink(title, description, payload, providerToken, currency, prices, maxTipAmount, suggestedTipAmounts ?.sorted(), providerData, requireName, requirePhoneNumber, requireEmail, requireShippingAddress, shouldSendPhoneNumberToProvider, shouldSendEmailToProvider, priceDependOnShipAddress)
)

View File

@@ -13,10 +13,11 @@ suspend fun TelegramBot.setWebhookInfo(
ipAddress: String? = null,
maxAllowedConnections: Int? = null,
allowedUpdates: List<String>? = null,
dropPendingUpdates: Boolean? = null
dropPendingUpdates: Boolean? = null,
secretToken: String? = null
) = execute(
SetWebhook(
url, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates
url, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates, secretToken
)
)
@@ -29,10 +30,11 @@ suspend fun TelegramBot.setWebhookInfo(
ipAddress: String? = null,
maxAllowedConnections: Int? = null,
allowedUpdates: List<String>? = null,
dropPendingUpdates: Boolean? = null
dropPendingUpdates: Boolean? = null,
secretToken: String? = null
) = execute(
SetWebhook(
url, certificate, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates
url, certificate, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates, secretToken
)
)
@@ -45,9 +47,10 @@ suspend fun TelegramBot.setWebhookInfo(
ipAddress: String? = null,
maxAllowedConnections: Int? = null,
allowedUpdates: List<String>? = null,
dropPendingUpdates: Boolean? = null
dropPendingUpdates: Boolean? = null,
secretToken: String? = null
) = execute(
SetWebhook(
url, certificate, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates
url, certificate, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates, secretToken
)
)

View File

@@ -0,0 +1,105 @@
package dev.inmo.tgbotapi.requests.send.payments
import dev.inmo.tgbotapi.abstracts.CommonSendInvoiceData
import dev.inmo.tgbotapi.abstracts.types.*
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.InvoiceContent
import dev.inmo.tgbotapi.types.payments.LabeledPrice
import dev.inmo.tgbotapi.types.payments.LabeledPricesSerializer
import dev.inmo.tgbotapi.types.payments.abstracts.Currency
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
/**
* @param providerData - JSON-ENCODED FIELD
*/
@Serializable
data class CreateInvoiceLink(
@SerialName(titleField)
override val title: String,
@SerialName(descriptionField)
override val description: String,
@SerialName(payloadField)
override val payload: String,
@SerialName(providerTokenField)
override val providerToken: String,
@SerialName(currencyField)
override val currency: Currency,
@Serializable(LabeledPricesSerializer::class)
@SerialName(pricesField)
override val prices: List<LabeledPrice>,
@SerialName(maxTipAmountField)
override val maxTipAmount: Int? = null,
@SerialName(suggestedTipAmountsField)
override val suggestedTipAmounts: List<Int>? = null,
@SerialName(providerDataField)
override val providerData: String? = null,
@SerialName(requireNameField)
override val requireName: Boolean = false,
@SerialName(requirePhoneNumberField)
override val requirePhoneNumber: Boolean = false,
@SerialName(requireEmailField)
override val requireEmail: Boolean = false,
@SerialName(requireShippingAddressField)
override val requireShippingAddress: Boolean = false,
@SerialName(shouldSendPhoneNumberToProviderField)
override val shouldSendPhoneNumberToProvider: Boolean = false,
@SerialName(shouldSendEmailToProviderField)
override val shouldSendEmailToProvider: Boolean = false,
@SerialName(priceDependOnShipAddressField)
override val priceDependOnShipAddress: Boolean = false
) : CommonSendInvoiceData, SimpleRequest<String> {
override fun method(): String = "sendInvoice"
override val resultDeserializer: DeserializationStrategy<String>
get() = String.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
@SerialName(photoUrlField)
override var photoUrl: String? = null
private set
@SerialName(photoSizeField)
override var photoSize: Long? = null
private set
@SerialName(photoWidthField)
override var photoWidth: Int? = null
private set
@SerialName(photoHeightField)
override var photoHeight: Int? = null
private set
init {
suggestedTipAmounts ?.let { _ ->
require(suggestedTipAmounts.size in suggestedTipAmountsLimit)
maxTipAmount ?.let { _ ->
require(
suggestedTipAmounts.none { it > maxTipAmount }
)
}
}
}
override fun setPhoto(
photoUrl: String,
photoSize: Long?,
photoWidth: Int?,
photoHeight: Int?
) {
this.photoUrl = photoUrl
this.photoSize = photoSize
this.photoWidth = photoWidth
this.photoHeight = photoHeight
}
override fun unsetPhoto() {
photoUrl = null
photoSize = null
photoWidth = null
photoHeight = null
}
}

View File

@@ -20,7 +20,8 @@ class MultipartSetWebhookRequest(
ipAddress: String? = null,
maxAllowedConnections: Int? = null,
allowedUpdates: List<String>? = null,
dropPendingUpdates: Boolean? = null
dropPendingUpdates: Boolean? = null,
secretToken: String? = null
) : SetWebhookRequest(), MultipartRequest<Boolean> by MultipartRequestImpl(
SetWebhook(
correctWebhookUrl(url),
@@ -28,7 +29,8 @@ class MultipartSetWebhookRequest(
ipAddress,
maxAllowedConnections,
allowedUpdates,
dropPendingUpdates
dropPendingUpdates,
secretToken
),
mapOf(certificateField to certificate)
)
@@ -39,14 +41,16 @@ fun SetWebhook(
ipAddress: String? = null,
maxAllowedConnections: Int? = null,
allowedUpdates: List<String>? = null,
dropPendingUpdates: Boolean? = null
dropPendingUpdates: Boolean? = null,
secretToken: String? = null
): MultipartSetWebhookRequest = MultipartSetWebhookRequest(
correctWebhookUrl(url),
certificate,
ipAddress,
maxAllowedConnections,
allowedUpdates,
dropPendingUpdates
dropPendingUpdates,
secretToken
)
fun SetWebhook(
@@ -55,14 +59,16 @@ fun SetWebhook(
ipAddress: String? = null,
maxAllowedConnections: Int? = null,
allowedUpdates: List<String>? = null,
dropPendingUpdates: Boolean? = null
dropPendingUpdates: Boolean? = null,
secretToken: String? = null
): SetWebhook = SetWebhook(
correctWebhookUrl(url),
certificate.fileId,
ipAddress,
maxAllowedConnections,
allowedUpdates,
dropPendingUpdates
dropPendingUpdates,
secretToken
)
/**
@@ -79,10 +85,11 @@ fun SetWebhook(
ipAddress: String? = null,
maxAllowedConnections: Int? = null,
allowedUpdates: List<String>? = null,
dropPendingUpdates: Boolean? = null
dropPendingUpdates: Boolean? = null,
secretToken: String? = null
) = when (certificate) {
is MultipartFile -> SetWebhook(correctWebhookUrl(url), certificate as MultipartFile, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
is FileId -> SetWebhook(correctWebhookUrl(url), certificate as FileId, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
is MultipartFile -> SetWebhook(correctWebhookUrl(url), certificate as MultipartFile, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates, secretToken)
is FileId -> SetWebhook(correctWebhookUrl(url), certificate as FileId, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates, secretToken)
}
/**
@@ -98,14 +105,16 @@ fun SetWebhook(
ipAddress: String? = null,
maxAllowedConnections: Int? = null,
allowedUpdates: List<String>? = null,
dropPendingUpdates: Boolean? = null
dropPendingUpdates: Boolean? = null,
secretToken: String? = null
) = SetWebhook(
correctWebhookUrl(url),
null,
ipAddress,
maxAllowedConnections,
allowedUpdates,
dropPendingUpdates
dropPendingUpdates,
secretToken
)
/**
@@ -128,7 +137,9 @@ data class SetWebhook internal constructor(
@SerialName(allowedUpdatesField)
val allowedUpdates: List<String>? = null,
@SerialName(dropPendingUpdatesField)
val dropPendingUpdates: Boolean? = null
val dropPendingUpdates: Boolean? = null,
@SerialName(secretTokenField)
val secretToken: String? = null
) : SetWebhookRequest(), DataRequest<Boolean> {
override fun method(): String = "setWebhook"
override val resultDeserializer: DeserializationStrategy<Boolean>

View File

@@ -117,6 +117,8 @@ const val isBotField = "is_bot"
const val firstNameField = "first_name"
const val lastNameField = "last_name"
const val languageCodeField = "language_code"
const val addedToAttachmentMenuField = "added_to_attachment_menu"
const val isPremiumField = "is_premium"
const val hasPrivateForwardsField = "has_private_forwards"
const val canJoinGroupsField = "can_join_groups"
const val canReadAllGroupMessagesField = "can_read_all_group_messages"
@@ -124,6 +126,7 @@ const val supportInlineQueriesField = "supports_inline_queries"
const val textEntitiesField = "text_entities"
const val entitiesField = "entities"
const val stickerSetNameField = "set_name"
const val premiumAnimationField = "premium_animation"
const val stickerSetNameFullField = "sticker_set_name"
const val slowModeDelayField = "slow_mode_delay"
const val maskPositionField = "mask_position"
@@ -155,6 +158,7 @@ const val switchPmParameterField = "switch_pm_parameter"
const val maxAllowedConnectionsField = "max_connections"
const val allowedUpdatesField = "allowed_updates"
const val dropPendingUpdatesField = "drop_pending_updates"
const val secretTokenField = "secret_token"
const val hasCustomCertificateField = "has_custom_certificate"
const val pendingUpdateCountField = "pending_update_count"
const val lastErrorDateField = "last_error_date"
@@ -180,6 +184,8 @@ const val customTitleField = "custom_title"
const val optionIdsField = "option_ids"
const val ipAddressField = "ip_address"
const val linkedChatIdField = "linked_chat_id"
const val joinToSendMessagesField = "join_to_send_messages"
const val joinByRequestField = "join_by_request"
const val horizontalAccuracyField = "horizontal_accuracy"
const val revokeMessagesField = "revoke_messages"
const val messageAutoDeleteTimeField = "message_auto_delete_time"

View File

@@ -32,6 +32,16 @@ sealed interface UsernameChat : Chat {
val username: Username?
}
@Serializable(PreviewChatSerializer::class)
sealed interface PossiblyPremiumChat : Chat {
val isPremium: Boolean
}
@Serializable(PreviewChatSerializer::class)
sealed interface AbleToAddInAttachmentMenuChat : Chat {
val addedToAttachmentMenu: Boolean
}
@Serializable(PreviewChatSerializer::class)
sealed interface Chat {
val id: ChatId

View File

@@ -65,7 +65,8 @@ object PreviewChatSerializer : KSerializer<Chat> {
ChatType.ChannelChatType -> formatter.decodeFromJsonElement(ChannelChatImpl.serializer(), decodedJson)
is ChatType.UnknownChatType -> UnknownChatType(
formatter.decodeFromJsonElement(Long.serializer(), decodedJson[chatIdField] ?: JsonPrimitive(-1)).toChatId(),
decodedJson.toString()
decodedJson.toString(),
decodedJson
)
}
}
@@ -77,6 +78,10 @@ object PreviewChatSerializer : KSerializer<Chat> {
is GroupChatImpl -> GroupChatImpl.serializer().serialize(encoder, value)
is SupergroupChatImpl -> SupergroupChatImpl.serializer().serialize(encoder, value)
is ChannelChatImpl -> ChannelChatImpl.serializer().serialize(encoder, value)
is CommonBot -> CommonBot.serializer().serialize(encoder, value)
is ExtendedBot -> ExtendedBot.serializer().serialize(encoder, value)
is CommonUser -> CommonUser.serializer().serialize(encoder, value)
is UnknownChatType -> JsonObject.serializer().serialize(encoder, value.rawJson)
}
}
}
@@ -99,7 +104,8 @@ object ExtendedChatSerializer : KSerializer<ExtendedChat> {
ChatType.ChannelChatType -> formatter.decodeFromJsonElement(ExtendedChannelChatImpl.serializer(), decodedJson)
is ChatType.UnknownChatType -> UnknownExtendedChat(
formatter.decodeFromJsonElement(Long.serializer(), decodedJson[chatIdField] ?: JsonPrimitive(-1)).toChatId(),
decodedJson.toString()
decodedJson.toString(),
decodedJson
)
}
}
@@ -110,6 +116,7 @@ object ExtendedChatSerializer : KSerializer<ExtendedChat> {
is ExtendedGroupChatImpl -> ExtendedGroupChatImpl.serializer().serialize(encoder, value)
is ExtendedSupergroupChatImpl -> ExtendedSupergroupChatImpl.serializer().serialize(encoder, value)
is ExtendedChannelChatImpl -> ExtendedChannelChatImpl.serializer().serialize(encoder, value)
is UnknownExtendedChat -> JsonObject.serializer().serialize(encoder, value.rawJson)
}
}
}

View File

@@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
@Serializable
data class ExtendedChannelChatImpl(
@@ -94,7 +95,11 @@ data class ExtendedSupergroupChatImpl(
@SerialName(linkedChatIdField)
override val linkedChannelChatId: ChatId? = null,
@SerialName(locationField)
override val location: ChatLocation? = null
override val location: ChatLocation? = null,
@SerialName(joinToSendMessagesField)
override val requiresJoinForMessaging: Boolean = false,
@SerialName(joinByRequestField)
override val requireAdminApproveToJoin: Boolean = false
) : ExtendedSupergroupChat
@Serializable
@@ -119,7 +124,8 @@ data class ExtendedBot(
data class UnknownExtendedChat(
override val id: ChatId,
val raw: String
val raw: String,
val rawJson: JsonObject
) : ExtendedChat {
override val chatPhoto: ChatPhoto? = null
}

View File

@@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.types.chat
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.ExtendedChat
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer
import kotlinx.serialization.Serializable
@@ -39,6 +38,16 @@ sealed interface ExtendedSupergroupChat : SupergroupChat, ExtendedGroupChat {
val canSetStickerSet: Boolean
val linkedChannelChatId: ChatId?
val location: ChatLocation?
/**
* This field represents field "join_to_send_messages" from API
*/
val requiresJoinForMessaging: Boolean
/**
* This field represents field "join_by_request" from API
*/
val requireAdminApproveToJoin: Boolean
}
@Serializable(ExtendedChatSerializer::class)

View File

@@ -80,8 +80,12 @@ data class CommonUser(
override val username: Username? = null,
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : User(), WithOptionalLanguageCode {
override val ietfLanguageCode: IetfLanguageCode? = null,
@SerialName(isPremiumField)
override val isPremium: Boolean = false,
@SerialName(addedToAttachmentMenuField)
override val addedToAttachmentMenu: Boolean = false
) : User(), WithOptionalLanguageCode, PossiblyPremiumChat, AbleToAddInAttachmentMenuChat {
constructor(
id: UserId,
firstName: String,

View File

@@ -1,9 +1,10 @@
package dev.inmo.tgbotapi.types.chat
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.chat.Chat
import kotlinx.serialization.json.JsonObject
data class UnknownChatType(
override val id: ChatId,
val raw: String
val raw: String,
val rawJson: JsonObject
) : Chat

View File

@@ -22,7 +22,8 @@ data class StickerSurrogate(
val emoji: String? = null,
val set_name: StickerSetName? = null,
val mask_position: MaskPosition? = null,
val file_size: Long? = null
val file_size: Long? = null,
val premium_animation: File? = null
)
// TODO:: Serializer
@@ -31,6 +32,7 @@ sealed interface Sticker : TelegramMediaFile, SizedMediaFile, ThumbedMediaFile {
val emoji: String?
val maskPosition: MaskPosition?
val stickerSetName: StickerSetName?
val premiumAnimationFile: File?
val isAnimated
get() = this is AnimatedSticker
@@ -53,6 +55,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.thumb,
surrogate.emoji,
surrogate.set_name,
surrogate.premium_animation,
surrogate.mask_position,
surrogate.file_size
)
@@ -64,6 +67,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.thumb,
surrogate.emoji,
surrogate.set_name,
surrogate.premium_animation,
surrogate.mask_position,
surrogate.file_size
)
@@ -75,6 +79,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.thumb,
surrogate.emoji,
surrogate.set_name,
surrogate.premium_animation,
surrogate.mask_position,
surrogate.file_size
)
@@ -103,6 +108,8 @@ data class SimpleSticker(
override val emoji: String? = null,
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(premiumAnimationField)
override val premiumAnimationFile: File?,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null,
@SerialName(fileSizeField)
@@ -124,6 +131,8 @@ data class AnimatedSticker(
override val emoji: String? = null,
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(premiumAnimationField)
override val premiumAnimationFile: File?,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null,
@SerialName(fileSizeField)
@@ -145,6 +154,8 @@ data class VideoSticker(
override val emoji: String? = null,
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(premiumAnimationField)
override val premiumAnimationFile: File?,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null,
@SerialName(fileSizeField)

View File

@@ -3,6 +3,7 @@
package dev.inmo.tgbotapi.extensions.utils
import dev.inmo.tgbotapi.abstracts.*
import dev.inmo.tgbotapi.requests.send.payments.CreateInvoiceLink
import dev.inmo.tgbotapi.requests.send.payments.SendInvoice
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.queries.callback.*
@@ -235,6 +236,24 @@ inline fun Chat.asExtendedSupergroupChat(): ExtendedSupergroupChat? = this as? E
@PreviewFeature
inline fun Chat.requireExtendedSupergroupChat(): ExtendedSupergroupChat = this as ExtendedSupergroupChat
@PreviewFeature
inline fun <T> Chat.whenPossiblyPremiumChat(block: (PossiblyPremiumChat) -> T) = asPossiblyPremiumChat() ?.let(block)
@PreviewFeature
inline fun Chat.asPossiblyPremiumChat(): PossiblyPremiumChat? = this as? PossiblyPremiumChat
@PreviewFeature
inline fun Chat.requirePossiblyPremiumChat(): PossiblyPremiumChat = this as PossiblyPremiumChat
@PreviewFeature
inline fun <T> Chat.whenAbleToAddInAttachmentMenuChat(block: (AbleToAddInAttachmentMenuChat) -> T) = asAbleToAddInAttachmentMenuChat() ?.let(block)
@PreviewFeature
inline fun Chat.asAbleToAddInAttachmentMenuChat(): AbleToAddInAttachmentMenuChat? = this as? AbleToAddInAttachmentMenuChat
@PreviewFeature
inline fun Chat.requireAbleToAddInAttachmentMenuChat(): AbleToAddInAttachmentMenuChat = this as AbleToAddInAttachmentMenuChat
@PreviewFeature
inline fun <T> CallbackQuery.whenDataCallbackQuery(block: (DataCallbackQuery) -> T) = asDataCallbackQuery() ?.let(block)
@@ -3255,7 +3274,16 @@ inline fun <T> CommonSendInvoiceData.whenSendInvoice(block: (SendInvoice) -> T)
inline fun CommonSendInvoiceData.asSendInvoice(): SendInvoice? = this as? SendInvoice
@PreviewFeature
inline fun CommonSendInvoiceData.requireVoiceChatParticipantsInvited(): SendInvoice = this as SendInvoice
inline fun CommonSendInvoiceData.requireSendInvoice(): SendInvoice = this as SendInvoice
@PreviewFeature
inline fun <T> CommonSendInvoiceData.whenCreateInvoiceLink(block: (CreateInvoiceLink) -> T) = asCreateInvoiceLink() ?.let(block)
@PreviewFeature
inline fun CommonSendInvoiceData.asCreateInvoiceLink(): CreateInvoiceLink? = this as? CreateInvoiceLink
@PreviewFeature
inline fun CommonSendInvoiceData.requireCreateInvoiceLink(): CreateInvoiceLink = this as CreateInvoiceLink
@PreviewFeature
inline fun <T> CommonSendInvoiceData.whenInputInvoiceMessageContent(block: (InputInvoiceMessageContent) -> T) = asInputInvoiceMessageContent() ?.let(block)

View File

@@ -19,3 +19,5 @@ inline val Sticker.mask_position: MaskPosition?
get() = maskPosition
inline val Sticker.file_size: Long?
get() = fileSize
inline val Sticker.premium_animation: File?
get() = premiumAnimationFile

View File

@@ -0,0 +1,11 @@
package dev.inmo.tgbotapi.webapps
external interface BackButton {
val isVisible: Boolean
fun onClick(callback: () -> Unit)
fun offClick(callback: () -> Unit)
fun show()
fun hide()
}

View File

@@ -0,0 +1,20 @@
package dev.inmo.tgbotapi.webapps
import kotlinx.serialization.Serializable
sealed interface Color {
val value: String
@Serializable
value class BackgroundColor(override val value: String) : Color
@Serializable
value class Hex(override val value: String) : Color
companion object {
val BackgroundColor = BackgroundColor("bg_color")
val SecondaryBackgroundColor = BackgroundColor("secondary_bg_color")
@Suppress("NOTHING_TO_INLINE")
inline operator fun invoke(value: String) = Hex(value)
}
}

View File

@@ -1,4 +1,7 @@
package dev.inmo.tgbotapi.webapps
import dev.inmo.tgbotapi.webapps.invoice.InvoiceClosedInfo
typealias EventHandler = WebApp.() -> Unit
typealias ViewportChangedEventHandler = WebApp.(ViewportChangedData) -> Unit
typealias InvoiceClosedEventHandler = WebApp.(InvoiceClosedInfo) -> Unit

View File

@@ -4,4 +4,7 @@ sealed class EventType(val typeName: String) {
object ThemeChanged : EventType("themeChanged")
object ViewportChanged : EventType("viewportChanged")
object MainButtonClicked : EventType("mainButtonClicked")
object BackButtonClicked : EventType("backButtonClicked")
object SettingsButtonClicked : EventType("settingsButtonClicked")
object InvoiceClosed : EventType("invoiceClosed")
}

View File

@@ -0,0 +1,3 @@
package dev.inmo.tgbotapi.webapps
typealias HEXColor = String

View File

@@ -23,6 +23,7 @@ external class MainButton {
fun hideProgress(): MainButton
internal fun onClick(eventHandler: () -> Unit): MainButton
internal fun offClick(eventHandler: () -> Unit): MainButton
internal fun setParams(params: Json): MainButton
}

View File

@@ -2,15 +2,32 @@ package dev.inmo.tgbotapi.webapps
external interface ThemeParams {
@JsName("bg_color")
val backgroundColor: String?
val backgroundColor: HEXColor?
@JsName("secondary_bg_color")
val secondaryBackgroundColor: HEXColor?
@JsName("text_color")
val textColor: String?
val textColor: HEXColor?
@JsName("hint_color")
val hintColor: String?
val hintColor: HEXColor?
@JsName("link_color")
val linkColor: String?
val linkColor: HEXColor?
@JsName("button_color")
val buttonColor: String?
val buttonColor: HEXColor?
@JsName("button_text_color")
val buttonTextColor: String?
val buttonTextColor: HEXColor?
@JsName("bg_color")
val backgroundColorHex: Color.Hex?
@JsName("secondary_bg_color")
val secondaryBackgroundColorHex: Color.Hex?
@JsName("text_color")
val textColorHex: Color.Hex?
@JsName("hint_color")
val hintColorHex: Color.Hex?
@JsName("link_color")
val linkColorHex: Color.Hex?
@JsName("button_color")
val buttonColorHex: Color.Hex?
@JsName("button_text_color")
val buttonTextColorHex: Color.Hex?
}

View File

@@ -1,11 +1,21 @@
package dev.inmo.tgbotapi.webapps
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.webapps.haptic.HapticFeedback
import dev.inmo.tgbotapi.webapps.invoice.InvoiceClosedInfo
external class WebApp {
val version: String
val initData: String
val initDataUnsafe: WebAppInitData
val headerColor: HEXColor?
fun setHeaderColor(color: Color.BackgroundColor)
val backgroundColor: HEXColor?
fun setBackgroundColor(color: Color.Hex)
fun setBackgroundColor(color: Color.BackgroundColor)
@JsName("colorScheme")
val colorSchemeRaw: String
val themeParams: ThemeParams
@@ -17,19 +27,34 @@ external class WebApp {
@JsName("MainButton")
val mainButton: MainButton
@JsName("BackButton")
val backButton: BackButton
@JsName("HapticFeedback")
val hapticFeedback: HapticFeedback
internal fun onEvent(type: String, callback: () -> Unit)
@JsName("onEvent")
internal fun onEventWithBoolean(type: String, callback: (ViewportChangedData) -> Unit)
internal fun onEventWithViewportChangedData(type: String, callback: (ViewportChangedData) -> Unit)
@JsName("onEvent")
internal fun onEventWithInvoiceClosedInfo(type: String, callback: (InvoiceClosedInfo) -> Unit)
fun offEvent(type: String, callback: () -> Unit)
@JsName("offEvent")
fun offEventWithBoolean(type: String, callback: (ViewportChangedData) -> Unit)
fun offEventWithViewportChangedData(type: String, callback: (ViewportChangedData) -> Unit)
@JsName("offEvent")
fun offEventWithInvoiceClosedInfo(type: String, callback: (InvoiceClosedInfo) -> Unit)
fun sendData(data: String)
fun ready()
fun expand()
fun close()
fun isVersionAtLeast(version: String): Boolean
fun openLink(url: String)
fun openTelegramLink(url: String)
fun openInvoice(url: String, callback: (InvoiceClosedInfo) -> Unit = definedExternally)
}
val WebApp.colorScheme: ColorScheme
@@ -57,7 +82,19 @@ fun WebApp.onEvent(type: EventType, eventHandler: EventHandler) = {
fun WebApp.onEvent(type: EventType.ViewportChanged, eventHandler: ViewportChangedEventHandler) = { it: ViewportChangedData ->
eventHandler(js("this").unsafeCast<WebApp>(), it)
}.also {
onEventWithBoolean(
onEventWithViewportChangedData(
type.typeName,
callback = it
)
}
/**
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onEvent(type: EventType.InvoiceClosed, eventHandler: InvoiceClosedEventHandler) = { it: InvoiceClosedInfo ->
eventHandler(js("this").unsafeCast<WebApp>(), it)
}.also {
onEventWithInvoiceClosedInfo(
type.typeName,
callback = it
)
@@ -75,6 +112,18 @@ fun WebApp.onMainButtonClicked(eventHandler: EventHandler) = onEvent(EventType.M
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onViewportChanged(eventHandler: ViewportChangedEventHandler) = onEvent(EventType.ViewportChanged, eventHandler)
/**
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onBackButtonClicked(eventHandler: EventHandler) = onEvent(EventType.BackButtonClicked, eventHandler)
/**
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onSettingsButtonClicked(eventHandler: EventHandler) = onEvent(EventType.SettingsButtonClicked, eventHandler)
/**
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onInvoiceClosed(eventHandler: InvoiceClosedEventHandler) = onEvent(EventType.InvoiceClosed, eventHandler)
fun WebApp.isInitDataSafe(botToken: String) = TelegramAPIUrlsKeeper(botToken).checkWebAppData(
initData,

View File

@@ -0,0 +1,14 @@
package dev.inmo.tgbotapi.webapps
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.Username
import dev.inmo.tgbotapi.types.chat.PublicChat
external interface WebAppChat {
val id: ChatIdentifier
val type: String
val title: String
val username: Username?
@JsName("photo_url")
val photoUrl: String?
}

View File

@@ -15,5 +15,10 @@ external interface WebAppInitData {
@JsName("auth_date")
val authDate: MilliSeconds
@JsName("can_send_after")
val canSendAfter: MilliSeconds
val chat: WebAppChat
val hash: String
}

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.webapps.haptic
external interface HapticFeedback {
fun impactOccurred(style: HapticFeedbackStyle)
fun notificationOccurred(type: HapticFeedbackType)
fun selectionChanged()
}

View File

@@ -0,0 +1,17 @@
package dev.inmo.tgbotapi.webapps.haptic
import dev.inmo.micro_utils.common.Warning
import kotlinx.serialization.Serializable
@Serializable
value class HapticFeedbackStyle @Warning("Do not use this constructor if available objects from companion cover your needs") constructor(
val name: String
) {
companion object {
val Light = HapticFeedbackStyle("light")
val Medium = HapticFeedbackStyle("medium")
val Heavy = HapticFeedbackStyle("heavy")
val Rigid = HapticFeedbackStyle("rigid")
val Soft = HapticFeedbackStyle("soft")
}
}

View File

@@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.webapps.haptic
import dev.inmo.micro_utils.common.Warning
import kotlinx.serialization.Serializable
@Serializable
value class HapticFeedbackType @Warning("Do not use this constructor if available objects from companion cover your needs") constructor(
val name: String
) {
companion object {
val Error = HapticFeedbackType("error")
val Success = HapticFeedbackType("success")
val Warning = HapticFeedbackType("warning")
}
}

View File

@@ -0,0 +1,16 @@
package dev.inmo.tgbotapi.webapps.invoice
external interface InvoiceClosedInfo {
val url: String
val status: String
}
val InvoiceClosedInfo.statusTyped
get() = when (status) {
InvoiceStatus.Paid.name -> InvoiceStatus.Paid
InvoiceStatus.Cancelled.name -> InvoiceStatus.Cancelled
InvoiceStatus.Failed.name -> InvoiceStatus.Failed
InvoiceStatus.Pending.name -> InvoiceStatus.Pending
else -> InvoiceStatus.Unknown(status)
}

View File

@@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.webapps.invoice
sealed interface InvoiceStatus {
val name: String
object Paid : InvoiceStatus { override val name: String = "paid" }
object Cancelled : InvoiceStatus { override val name: String = "cancelled" }
object Failed : InvoiceStatus { override val name: String = "failed" }
object Pending : InvoiceStatus { override val name: String = "pending" }
value class Unknown(override val name: String) : InvoiceStatus
}