mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-12-22 16:47:13 +00:00
preparations for events generating
This commit is contained in:
parent
9cde4927ce
commit
6824f2c992
@ -101,15 +101,23 @@ fun readEnvs(content: String, presets: Map<String, String>?): Map<String, String
|
|||||||
return (presets ?: emptyMap()) + readEnvs
|
return (presets ?: emptyMap()) + readEnvs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val realArgs = args.map { sourceArg ->
|
||||||
|
if (sourceArg.startsWith("\"") && sourceArg.endsWith("\"")) {
|
||||||
|
sourceArg.removePrefix("\"").removeSuffix("\"")
|
||||||
|
} else {
|
||||||
|
sourceArg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun readParameters() {
|
fun readParameters() {
|
||||||
var i = 0
|
var i = 0
|
||||||
while (i < args.size) {
|
while (i < realArgs.size) {
|
||||||
val arg = args[i]
|
val arg = realArgs[i]
|
||||||
when (arg) {
|
when (arg) {
|
||||||
"--env",
|
"--env",
|
||||||
"-e" -> {
|
"-e" -> {
|
||||||
i++
|
i++
|
||||||
envFile = File(args[i])
|
envFile = File(realArgs[i])
|
||||||
}
|
}
|
||||||
"--skip",
|
"--skip",
|
||||||
"-s" -> {
|
"-s" -> {
|
||||||
@ -118,17 +126,17 @@ fun readParameters() {
|
|||||||
"--extensions",
|
"--extensions",
|
||||||
"-ex" -> {
|
"-ex" -> {
|
||||||
i++
|
i++
|
||||||
extensions = args[i].split(",")
|
extensions = realArgs[i].split(",")
|
||||||
}
|
}
|
||||||
"--outputFolder",
|
"--outputFolder",
|
||||||
"-o" -> {
|
"-o" -> {
|
||||||
i++
|
i++
|
||||||
outputFolder = File(args[i])
|
outputFolder = File(realArgs[i])
|
||||||
}
|
}
|
||||||
"--args",
|
"--args",
|
||||||
"-a" -> {
|
"-a" -> {
|
||||||
i++
|
i++
|
||||||
val subarg = args[i]
|
val subarg = realArgs[i]
|
||||||
val key = subarg.takeWhile { it != '=' }
|
val key = subarg.takeWhile { it != '=' }
|
||||||
val value = subarg.dropWhile { it != '=' }.removePrefix("=")
|
val value = subarg.dropWhile { it != '=' }.removePrefix("=")
|
||||||
commandLineArgs[key] = value
|
commandLineArgs[key] = value
|
||||||
@ -164,6 +172,7 @@ fun readParameters() {
|
|||||||
Runtime.getRuntime().exit(0)
|
Runtime.getRuntime().exit(0)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
println(arg)
|
||||||
val potentialFile = File(arg)
|
val potentialFile = File(arg)
|
||||||
println("Potential file/folder as template: ${potentialFile.absolutePath}")
|
println("Potential file/folder as template: ${potentialFile.absolutePath}")
|
||||||
runCatching {
|
runCatching {
|
||||||
|
@ -12,3 +12,12 @@ inline val RequestStatus.isAllowed: Boolean
|
|||||||
|
|
||||||
inline val RequestStatus.isSent: Boolean
|
inline val RequestStatus.isSent: Boolean
|
||||||
get() = status == "sent"
|
get() = status == "sent"
|
||||||
|
|
||||||
|
inline val dev.inmo.tgbotapi.webapps.args.ArgStatusObject.isCancelled: Boolean
|
||||||
|
get() = status == "cancelled"
|
||||||
|
|
||||||
|
inline val dev.inmo.tgbotapi.webapps.args.ArgStatusObject.isAllowed: Boolean
|
||||||
|
get() = status == "allowed"
|
||||||
|
|
||||||
|
inline val dev.inmo.tgbotapi.webapps.args.ArgStatusObject.isSent: Boolean
|
||||||
|
get() = status == "sent"
|
@ -0,0 +1,4 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
interface ArgBiometricAuthRequested : ArgBiometricTokenNullableObject, ArgIsAuthenticatedObject {
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
external interface ArgBiometricTokenNullableObject {
|
||||||
|
val biometricToken: String?
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
external interface ArgDataNullableObject {
|
||||||
|
val data: String?
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
external interface ArgDataObject : ArgDataNullableObject {
|
||||||
|
override val data: String
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
interface ArgErrorObject {
|
||||||
|
val error: String
|
||||||
|
}
|
||||||
|
|
||||||
|
val ArgErrorObject.isUnsupported
|
||||||
|
get() = error.uppercase() == "UNSUPPORTED"
|
||||||
|
|
||||||
|
val ArgErrorObject.isAlreadyFullscreen
|
||||||
|
get() = error.uppercase() == "ALREADY_FULLSCREEN"
|
||||||
|
|
||||||
|
val ArgErrorObject.isAMessageExpired
|
||||||
|
get() = error.uppercase() == "MESSAGE_EXPIRED"
|
||||||
|
|
||||||
|
val ArgErrorObject.isMessageSendFailed
|
||||||
|
get() = error.uppercase() == "MESSAGE_SEND_FAILED"
|
||||||
|
|
||||||
|
val ArgErrorObject.isUserDeclined
|
||||||
|
get() = error.uppercase() == "USER_DECLINED"
|
||||||
|
|
||||||
|
val ArgErrorObject.isSuggestedEmojiInvalid
|
||||||
|
get() = error.uppercase() == "SUGGESTED_EMOJI_INVALID"
|
||||||
|
|
||||||
|
val ArgErrorObject.isDurationInvalid
|
||||||
|
get() = error.uppercase() == "DURATION_INVALID"
|
||||||
|
|
||||||
|
val ArgErrorObject.isServerError
|
||||||
|
get() = error.uppercase() == "SERVER_ERROR"
|
||||||
|
|
||||||
|
val ArgErrorObject.isUnknownError
|
||||||
|
get() = error.uppercase() == "UNKNOWN_ERROR"
|
@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
interface ArgIsAuthenticatedObject {
|
||||||
|
val isAuthenticated: Boolean
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
interface ArgIsUpdatedObject {
|
||||||
|
val isUpdated: Boolean
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.webapps.location.LocationData
|
||||||
|
|
||||||
|
interface ArgLocationDataObject {
|
||||||
|
val locationData: LocationData
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.args
|
||||||
|
|
||||||
|
external interface ArgStatusObject {
|
||||||
|
val status: String
|
||||||
|
}
|
||||||
|
|
||||||
|
val ArgStatusObject.isUnsupported
|
||||||
|
get() = status.lowercase() == "unsupported"
|
||||||
|
|
||||||
|
val ArgStatusObject.isUnknown
|
||||||
|
get() = status.lowercase() == "unknown"
|
||||||
|
|
||||||
|
val ArgStatusObject.isAdded
|
||||||
|
get() = status.lowercase() == "added"
|
||||||
|
|
||||||
|
val ArgStatusObject.isMissed
|
||||||
|
get() = status.lowercase() == "missed"
|
||||||
|
|
||||||
|
val ArgStatusObject.isAllowed
|
||||||
|
get() = status.lowercase() == "allowed"
|
||||||
|
|
||||||
|
val ArgStatusObject.isDownloading
|
||||||
|
get() = status.lowercase() == "downloading"
|
||||||
|
|
||||||
|
val ArgStatusObject.isCancelled
|
||||||
|
get() = status.lowercase() == "cancelled"
|
@ -2,5 +2,177 @@
|
|||||||
{
|
{
|
||||||
"event_name": "activated",
|
"event_name": "activated",
|
||||||
"callback_args": ""
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "deactivated",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "themeChanged",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "viewportChanged",
|
||||||
|
"callback_args": "Boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "safeAreaChanged",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "contentSafeAreaChanged",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "mainButtonClicked",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "secondaryButtonClicked",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "backButtonClicked",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "settingsButtonClicked",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "invoiceClosed",
|
||||||
|
"callback_args": "String, dev.inmo.tgbotapi.webapps.invoice.InvoiceStatus"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "popupClosed",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.popup.PopupClosedEventArg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "qrTextReceived",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgDataObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "scanQrPopupClosed",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "clipboardTextReceived",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgDataNullableObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "writeAccessRequested",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgStatusObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "contactRequested",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgStatusObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "biometricManagerUpdated",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "biometricAuthRequested",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgBiometricAuthRequested"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "biometricTokenUpdated",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgIsUpdatedObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "fullscreenChanged",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "fullscreenFailed",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgErrorObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "homeScreenAdded",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "homeScreenChecked",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgStatusObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "accelerometerStarted",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "accelerometerStopped",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "accelerometerChanged",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "accelerometerFailed",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgErrorObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "deviceOrientationStarted",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "deviceOrientationStopped",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "deviceOrientationChanged",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "deviceOrientationFailed",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgErrorObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "gyroscopeStarted",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "gyroscopeStopped",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "gyroscopeChanged",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "gyroscopeFailed",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgErrorObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "locationManagerUpdated",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "locationRequested",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgLocationDataObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "shareMessageSent",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "shareMessageFailed",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgErrorObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "emojiStatusSet",
|
||||||
|
"callback_args": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "emojiStatusFailed",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgErrorObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "emojiStatusAccessRequested",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgStatusObject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"event_name": "fileDownloadRequested",
|
||||||
|
"callback_args": "dev.inmo.tgbotapi.webapps.args.ArgStatusObject"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -3,18 +3,64 @@
|
|||||||
|
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
import java.lang.Runtime
|
import java.lang.Runtime
|
||||||
|
import java.lang.System
|
||||||
|
|
||||||
val rootFolder = File("../../../../../../../../")
|
val rootFolder = File("../../../../../../../../")
|
||||||
val rfAbsolutePath = rootFolder.absolutePath
|
val rfAbsolutePath = rootFolder.absolutePath
|
||||||
|
val currentFolder = File("./")
|
||||||
|
val cfAbsolutePath = currentFolder.absolutePath
|
||||||
|
|
||||||
|
val realArgs = args.map { sourceArg ->
|
||||||
|
if (sourceArg.startsWith("\"") && sourceArg.endsWith("\"")) {
|
||||||
|
sourceArg.removePrefix("\"").removeSuffix("\"")
|
||||||
|
} else {
|
||||||
|
sourceArg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var verboseMode: Boolean = false
|
||||||
|
|
||||||
|
fun readParameters() {
|
||||||
|
var i = 0
|
||||||
|
while (i < realArgs.size) {
|
||||||
|
val arg = realArgs[i]
|
||||||
|
|
||||||
|
when (arg) {
|
||||||
|
"-v", "--verbose" -> {
|
||||||
|
verboseMode = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun generateEvent(eventName: String, callbacks: String) {
|
fun generateEvent(eventName: String, callbacks: String) {
|
||||||
val uppercaseEventName = eventName.take(1).uppercase() + eventName.drop(1)
|
val uppercaseEventName = eventName.take(1).uppercase() + eventName.drop(1)
|
||||||
val subpackage = eventName.map { if (it.isUpperCase()) "_${it.lowercase()}" else it }.joinToString("")
|
val subpackage = eventName.map { if (it.isUpperCase()) "_${it.lowercase()}" else it }.joinToString("")
|
||||||
val command = "${rfAbsolutePath}/.templates/generator.kts -s -a \"subpackage=$subpackage\" -a \"event_name=$eventName\" -a \"event_name_uppercase=$uppercaseEventName\" -a \"callback_args=$callbacks\" -o \"./\" -ex \"kt\" \"${rfAbsolutePath}/.templates/{{\$subpackage}}\""
|
val command = "${rfAbsolutePath}/.templates/generator.kts -s -a \"subpackage=$subpackage\" -a \"event_name=$eventName\" -a \"event_name_uppercase=$uppercaseEventName\" -a \"callback_args=$callbacks\" -a \"callback_typealias_name=${uppercaseEventName}EventHandler\" -o \"$cfAbsolutePath\" -ex \"kt\" \"${rfAbsolutePath}/.templates/{{\$subpackage}}\""
|
||||||
|
|
||||||
println(command)
|
val process = Runtime.getRuntime().exec(command)
|
||||||
println(Runtime.getRuntime().exec(command).waitFor())
|
val inputStream: InputStream = process.getInputStream()
|
||||||
|
val errorStream: InputStream = process.getErrorStream()
|
||||||
|
|
||||||
|
val exitCode by lazy { process.waitFor() }
|
||||||
|
|
||||||
|
if (verboseMode) {
|
||||||
|
inputStream.use {
|
||||||
|
it.copyTo(System.out)
|
||||||
|
}
|
||||||
|
println(exitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exitCode != 0) {
|
||||||
|
errorStream.use {
|
||||||
|
it.copyTo(System.out)
|
||||||
|
}
|
||||||
|
Runtime.getRuntime().exit(exitCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val eventsList: JsonArray = Json.parseToJsonElement(File("EventsList.json").readText()).jsonArray
|
val eventsList: JsonArray = Json.parseToJsonElement(File("EventsList.json").readText()).jsonArray
|
||||||
@ -25,3 +71,62 @@ eventsList.forEach {
|
|||||||
it.jsonObject["callback"] ?.jsonPrimitive ?.content ?: ""
|
it.jsonObject["callback"] ?.jsonPrimitive ?.content ?: ""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val eventTypeParts = mutableListOf<String>()
|
||||||
|
val webAppParts = mutableListOf<String>()
|
||||||
|
val extensionsParts = mutableListOf<String>()
|
||||||
|
|
||||||
|
currentFolder.listFiles() ?.forEach { generatedFolder: File ->
|
||||||
|
if (generatedFolder.isDirectory) {
|
||||||
|
generatedFolder.listFiles() ?.forEach { generatedFile: File ->
|
||||||
|
when {
|
||||||
|
generatedFile.name.startsWith("EventType") -> {
|
||||||
|
eventTypeParts
|
||||||
|
}
|
||||||
|
generatedFile.name.startsWith("WebApp") -> {
|
||||||
|
webAppParts
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
extensionsParts
|
||||||
|
}
|
||||||
|
}.add(generatedFile.readText())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val eventTypePartsString = eventTypeParts.joinToString("\n") { " $it" }
|
||||||
|
eventTypeParts.clear()
|
||||||
|
val eventTypeFileContent = "package dev.inmo.tgbotapi.webapps\n\nsealed class EventType(val typeName: String) {\n${eventTypePartsString}\n}\n"
|
||||||
|
println(eventTypeFileContent)
|
||||||
|
|
||||||
|
val eventTypeOutputFile = File(currentFolder, "../EventType.kt")
|
||||||
|
eventTypeOutputFile.writeText(
|
||||||
|
eventTypeFileContent
|
||||||
|
)
|
||||||
|
|
||||||
|
val webAppPartsString = webAppParts.joinToString("\n")
|
||||||
|
webAppParts.clear()
|
||||||
|
val eventTypeFileContent = webAppPartsString
|
||||||
|
println(eventTypeFileContent)
|
||||||
|
|
||||||
|
val webAppOutputFile = File(currentFolder, "ToPutInWebApp!!!!!.kt")
|
||||||
|
webAppOutputFile.writeText(
|
||||||
|
webAppPartsString
|
||||||
|
)
|
||||||
|
|
||||||
|
val extensionsPartsString = extensionsParts.joinToString("\n")
|
||||||
|
extensionsParts.clear()
|
||||||
|
val extensionsPartsFileContent = "package dev.inmo.tgbotapi.webapps.events\n\n${extensionsPartsString}\n"
|
||||||
|
println(extensionsPartsFileContent)
|
||||||
|
|
||||||
|
val extensionsPartsOutputFile = File(currentFolder, "Extensions.kt")
|
||||||
|
extensionsPartsOutputFile.writeText(
|
||||||
|
extensionsPartsFileContent
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
currentFolder.listFiles() ?.toList() ?.forEach { generatedFolder: File ->
|
||||||
|
if (it.isDirectory) {
|
||||||
|
it.deleteRecursively()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps.popup
|
||||||
|
|
||||||
|
external interface PopupClosedEventArg {
|
||||||
|
@JsName("button_id")
|
||||||
|
val buttonId: String?
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user