All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ski.gagar.vxutil.vertigram.verticles.TelegramVerticle.kt Maven / Gradle / Ivy

The newest version!
package ski.gagar.vxutil.vertigram.verticles

import ski.gagar.vxutil.jackson.mapTo
import ski.gagar.vxutil.jackson.suspendJsonConsumer
import ski.gagar.vxutil.use
import ski.gagar.vxutil.verticles.ErrorLoggingCoroutineVerticle
import ski.gagar.vxutil.vertigram.client.DirectTelegram
import ski.gagar.vxutil.vertigram.client.Telegram
import ski.gagar.vxutil.vertigram.methods.JsonTgCallable
import ski.gagar.vxutil.vertigram.methods.MultipartTgCallable
import ski.gagar.vxutil.vertigram.methods.TgCallable
import ski.gagar.vxutil.vertigram.throttling.ThrottlingOptions
import ski.gagar.vxutil.vertigram.throttling.ThrottlingTelegram
import ski.gagar.vxutil.vertigram.types.UpdateList
import ski.gagar.vxutil.vertigram.types.UpdateType
import ski.gagar.vxutil.vertigram.util.TypeHints
import ski.gagar.vxutil.vertigram.util.getOrAssert

@Suppress("DEPRECATION")
private typealias RawGetUpdates = ski.gagar.vxutil.vertigram.methods.GetUpdates

class TelegramVerticle : ErrorLoggingCoroutineVerticle() {
    private val typedConfig by lazy {
        config.mapTo()
    }
    private lateinit var tg: Telegram

    override suspend fun start() {
        val directTg = DirectTelegram(
            typedConfig.token,
            vertx,
            typedConfig.tgOptions
        )
        val throttling = typedConfig.throttling
        tg = if (null == throttling) {
            directTg
        } else {
            ThrottlingTelegram(vertx, directTg, throttling)
        }

        @Suppress("TYPEALIAS_EXPANSION_DEPRECATION")
        suspendJsonConsumer(
            typedConfig.callAddress(RawGetUpdates::class.java), function = ::handleGetUpdates)

        for ((methodName, requestType) in TypeHints.Json.requestTypesByMethodName) {
            if (methodName in TypeHints.doNotGenerateInTgVerticleMethodNames)
                continue
            val responseType = TypeHints.Json.returnTypesByMethodName.getOrAssert(methodName)
            suspendJsonConsumer(
                typedConfig.callAddress(methodName,
                    RequestType.Json
                ),
                requestJavaType = requestType
            ) { msg: TgCallable<*> ->
                tg.call(responseType, msg)
            }
        }

        for ((methodName, requestType) in TypeHints.Multipart.requestTypesByMethodName) {
            if (methodName in TypeHints.doNotGenerateInTgVerticleMethodNames)
                continue
            val responseType = TypeHints.Multipart.returnTypesByMethodName.getOrAssert(methodName)
            suspendJsonConsumer(
                typedConfig.callAddress(methodName,
                    RequestType.Multipart
                ),
                requestJavaType = requestType
            ) { msg: TgCallable<*> ->
                tg.call(responseType, msg)
            }
        }

        suspendJsonConsumer(typedConfig.longPollTimeoutAddress(), function = ::handleLongPollTimeout)
        suspendJsonConsumer(typedConfig.downloadFileAddress(), function = ::handleDownloadFile)
    }

    override suspend fun stop() {
        val tg = this.tg
        if (tg is AutoCloseable) {
            tg.close()
        }
    }

    private suspend fun handleGetUpdates(msg: GetUpdates) =
        UpdateList(tg.getUpdates(limit = msg.limit, offset = msg.offset, allowedUpdates = msg.allowedUpdates))

    private fun handleLongPollTimeout(msg: GetLongPollTimeout) = typedConfig.tgOptions.longPollTimeout.also { use(msg) }

    private suspend fun handleDownloadFile(msg: DownloadFile) = tg.downloadFile(msg.path, msg.outputPath)

    enum class RequestType(val postfix: String) {
        Json("json"),
        Multipart("multipart");

        companion object {
            fun > byClass(clazz: Class) =
                when {
                    JsonTgCallable::class.java.isAssignableFrom(clazz) -> Json
                    MultipartTgCallable::class.java.isAssignableFrom(clazz) -> Multipart
                    else -> throw AssertionError("oops")
                }

            fun byCallable(tgc: TgCallable<*>) =
                when (tgc) {
                    is JsonTgCallable<*> -> Json
                    is MultipartTgCallable<*> -> Multipart
                }
        }
    }

    data class Config(
        val token: String,
        val baseAddress: String = DEFAULT_BASE_ADDRESS,
        val tgOptions: DirectTelegram.Options = DirectTelegram.Options(),
        val throttling: ThrottlingOptions? = ThrottlingOptions()
    ) {

        internal fun callAddress(methodName: String, requestType: RequestType) =
            callAddress(
                methodName,
                baseAddress,
                requestType
            )

        fun > callAddress(clazz: Class) =
            callAddress(
                clazz,
                baseAddress
            )

        inline fun > callAddress(obj: T) =
            callAddress(
                obj,
                baseAddress
            )

        fun longPollTimeoutAddress() =
            longPollTimeoutAddress(
                baseAddress
            )

        fun downloadFileAddress() =
            downloadFileAddress(baseAddress)

        companion object {
            const val DEFAULT_BASE_ADDRESS = "ski.gagar.vertigram.telegram"

            private fun callAddress(methodName: String,
                                    baseAddress: String = DEFAULT_BASE_ADDRESS,
                                    requestType: RequestType
            ) =
                "$baseAddress.$methodName.${requestType.postfix}"

            fun > callAddress(clazz: Class, baseAddress: String = DEFAULT_BASE_ADDRESS) =
                callAddress(
                    TypeHints.methodNames.getOrAssert(
                        clazz
                    ),
                    baseAddress,
                    RequestType.byClass(
                        clazz
                    )
                )

            fun > callAddress(obj: T, baseAddress: String = DEFAULT_BASE_ADDRESS) =
                callAddress(
                    TypeHints.methodNames.getOrAssert(
                        obj.javaClass
                    ),
                    baseAddress,
                    RequestType.byCallable(
                        obj
                    )
                )

            fun longPollTimeoutAddress(baseAddress: String = DEFAULT_BASE_ADDRESS) =
                "$baseAddress.conf.longPollTimeout"

            fun downloadFileAddress(baseAddress: String = DEFAULT_BASE_ADDRESS) =
                "$baseAddress.conf.downloadFile"

        }
    }

    data class GetUpdates(val offset: Long?, val limit: Int?, val allowedUpdates: List? = null)
    object GetLongPollTimeout
    data class DownloadFile(val path: String, val outputPath: String)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy