1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-22 08:13:47 +00:00

update webapps support

This commit is contained in:
InsanusMokrassar 2022-06-21 16:27:53 +06:00
parent cde8fdeffd
commit f2e9bf6bd8
19 changed files with 217 additions and 14 deletions

View File

@ -2,6 +2,8 @@
## 2.1.0 ## 2.1.0
* Add support of functionality for `WebApp`s from [Bot API 6.1](https://core.telegram.org/bots/api-changelog#june-20-2022)
## 2.0.3 ## 2.0.3
* `Core`: * `Core`:

View File

@ -65,7 +65,8 @@ object PreviewChatSerializer : KSerializer<Chat> {
ChatType.ChannelChatType -> formatter.decodeFromJsonElement(ChannelChatImpl.serializer(), decodedJson) ChatType.ChannelChatType -> formatter.decodeFromJsonElement(ChannelChatImpl.serializer(), decodedJson)
is ChatType.UnknownChatType -> UnknownChatType( is ChatType.UnknownChatType -> UnknownChatType(
formatter.decodeFromJsonElement(Long.serializer(), decodedJson[chatIdField] ?: JsonPrimitive(-1)).toChatId(), 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 GroupChatImpl -> GroupChatImpl.serializer().serialize(encoder, value)
is SupergroupChatImpl -> SupergroupChatImpl.serializer().serialize(encoder, value) is SupergroupChatImpl -> SupergroupChatImpl.serializer().serialize(encoder, value)
is ChannelChatImpl -> ChannelChatImpl.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) ChatType.ChannelChatType -> formatter.decodeFromJsonElement(ExtendedChannelChatImpl.serializer(), decodedJson)
is ChatType.UnknownChatType -> UnknownExtendedChat( is ChatType.UnknownChatType -> UnknownExtendedChat(
formatter.decodeFromJsonElement(Long.serializer(), decodedJson[chatIdField] ?: JsonPrimitive(-1)).toChatId(), 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 ExtendedGroupChatImpl -> ExtendedGroupChatImpl.serializer().serialize(encoder, value)
is ExtendedSupergroupChatImpl -> ExtendedSupergroupChatImpl.serializer().serialize(encoder, value) is ExtendedSupergroupChatImpl -> ExtendedSupergroupChatImpl.serializer().serialize(encoder, value)
is ExtendedChannelChatImpl -> ExtendedChannelChatImpl.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 dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
@Serializable @Serializable
data class ExtendedChannelChatImpl( data class ExtendedChannelChatImpl(
@ -119,7 +120,8 @@ data class ExtendedBot(
data class UnknownExtendedChat( data class UnknownExtendedChat(
override val id: ChatId, override val id: ChatId,
val raw: String val raw: String,
val rawJson: JsonObject
) : ExtendedChat { ) : ExtendedChat {
override val chatPhoto: ChatPhoto? = null override val chatPhoto: ChatPhoto? = null
} }

View File

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

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 package dev.inmo.tgbotapi.webapps
import dev.inmo.tgbotapi.webapps.invoice.InvoiceClosedInfo
typealias EventHandler = WebApp.() -> Unit typealias EventHandler = WebApp.() -> Unit
typealias ViewportChangedEventHandler = WebApp.(ViewportChangedData) -> 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 ThemeChanged : EventType("themeChanged")
object ViewportChanged : EventType("viewportChanged") object ViewportChanged : EventType("viewportChanged")
object MainButtonClicked : EventType("mainButtonClicked") 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 fun hideProgress(): MainButton
internal fun onClick(eventHandler: () -> Unit): MainButton internal fun onClick(eventHandler: () -> Unit): MainButton
internal fun offClick(eventHandler: () -> Unit): MainButton
internal fun setParams(params: Json): MainButton internal fun setParams(params: Json): MainButton
} }

View File

@ -2,15 +2,32 @@ package dev.inmo.tgbotapi.webapps
external interface ThemeParams { external interface ThemeParams {
@JsName("bg_color") @JsName("bg_color")
val backgroundColor: String? val backgroundColor: HEXColor?
@JsName("secondary_bg_color")
val secondaryBackgroundColor: HEXColor?
@JsName("text_color") @JsName("text_color")
val textColor: String? val textColor: HEXColor?
@JsName("hint_color") @JsName("hint_color")
val hintColor: String? val hintColor: HEXColor?
@JsName("link_color") @JsName("link_color")
val linkColor: String? val linkColor: HEXColor?
@JsName("button_color") @JsName("button_color")
val buttonColor: String? val buttonColor: HEXColor?
@JsName("button_text_color") @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 package dev.inmo.tgbotapi.webapps
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.webapps.haptic.HapticFeedback
import dev.inmo.tgbotapi.webapps.invoice.InvoiceClosedInfo
external class WebApp { external class WebApp {
val version: String
val initData: String val initData: String
val initDataUnsafe: WebAppInitData 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") @JsName("colorScheme")
val colorSchemeRaw: String val colorSchemeRaw: String
val themeParams: ThemeParams val themeParams: ThemeParams
@ -17,19 +27,34 @@ external class WebApp {
@JsName("MainButton") @JsName("MainButton")
val mainButton: MainButton val mainButton: MainButton
@JsName("BackButton")
val backButton: BackButton
@JsName("HapticFeedback")
val hapticFeedback: HapticFeedback
internal fun onEvent(type: String, callback: () -> Unit) internal fun onEvent(type: String, callback: () -> Unit)
@JsName("onEvent") @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) fun offEvent(type: String, callback: () -> Unit)
@JsName("offEvent") @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 sendData(data: String)
fun ready() fun ready()
fun expand() fun expand()
fun close() 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 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 -> fun WebApp.onEvent(type: EventType.ViewportChanged, eventHandler: ViewportChangedEventHandler) = { it: ViewportChangedData ->
eventHandler(js("this").unsafeCast<WebApp>(), it) eventHandler(js("this").unsafeCast<WebApp>(), it)
}.also { }.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, type.typeName,
callback = it 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 * @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) 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( fun WebApp.isInitDataSafe(botToken: String) = TelegramAPIUrlsKeeper(botToken).checkWebAppData(
initData, 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") @JsName("auth_date")
val authDate: MilliSeconds val authDate: MilliSeconds
@JsName("can_send_after")
val canSendAfter: MilliSeconds
val chat: WebAppChat
val hash: String 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
}