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

eu.vendeli.tgbot.interfaces.MediaAction.kt Maven / Gradle / Ivy

There is a newer version: 6.6.0
Show newest version
package eu.vendeli.tgbot.interfaces

import eu.vendeli.tgbot.TelegramBot
import eu.vendeli.tgbot.types.User
import eu.vendeli.tgbot.types.internal.ImplicitFile
import eu.vendeli.tgbot.types.internal.MediaContentType
import eu.vendeli.tgbot.types.internal.Recipient
import eu.vendeli.tgbot.types.internal.Response
import eu.vendeli.tgbot.types.internal.toContentType
import eu.vendeli.tgbot.utils.makeRequestAsync
import eu.vendeli.tgbot.utils.makeSilentRequest
import io.ktor.http.ContentType
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.nio.file.Files
import kotlin.collections.set

/**
 * Media action, see [Actions article](https://github.com/vendelieu/telegram-bot/wiki/Actions)
 *
 * @param ReturnType response type.
 */
interface MediaAction : Action, TgAction {
    /**
     * The name of the field that will store the data.
     */
    val MediaAction.dataField: String

    /**
     * Content type of media.
     */
    val MediaAction.defaultType: MediaContentType

    /**
     * Media itself.
     */
    val MediaAction.media: ImplicitFile<*>

    /**
     * Make a request for action.
     *
     * @param to Recipient
     * @param via Instance of the bot through which the request will be made.
     */
    override suspend fun send(to: String, via: TelegramBot) {
        internalSend(Recipient.String(to), via)
    }

    /**
     * Make a request for action.
     *
     * @param to Recipient
     * @param via Instance of the bot through which the request will be made.
     */
    override suspend fun send(to: Long, via: TelegramBot) {
        internalSend(Recipient.Long(to), via)
    }

    /**
     * Make a request for action.
     *
     * @param to Recipient
     * @param via Instance of the bot through which the request will be made.
     */
    override suspend fun send(to: User, via: TelegramBot) {
        internalSend(Recipient.Long(to.id), via)
    }

    /**
     * The internal method used to send the data.
     *
     * @param to Recipient
     * @param via Instance of the bot through which the request will be made.
     */
    suspend fun MediaAction.internalSend(to: Recipient, via: TelegramBot) {
        parameters["chat_id"] = to.get
        val filename = parameters["file_name"]?.toString()?.also {
            parameters.remove("file_name")
        } ?: media.name ?: "$dataField.$defaultType"

        when (media) {
            is ImplicitFile.FromString -> {
                parameters[dataField] = media.file
                via.makeSilentRequest(method, parameters)
            }

            is ImplicitFile.FromByteArray -> via.makeSilentRequest {
                method = [email protected]
                dataField = [email protected]
                name = filename
                data = media.bytes
                parameters = [email protected]
                contentType = defaultType.toContentType()
            }

            is ImplicitFile.FromFile -> via.makeSilentRequest {
                method = [email protected]
                dataField = [email protected]
                name = filename
                data = media.bytes
                parameters = [email protected]
                contentType = withContext(Dispatchers.IO) {
                    ContentType.parse(
                        Files.probeContentType((media.file as File).toPath())
                            ?: return@withContext defaultType.toContentType(),
                    )
                }
            }
        }
    }

    /**
     * Make request with ability operating over response.
     *
     * @param to Recipient
     * @param via Instance of the bot through which the request will be made.
     */
    override suspend fun sendAsync(
        to: String,
        via: TelegramBot,
    ): Deferred> = internalSendAsync(returnType, Recipient.String(to), via)

    /**
     * Make request with ability operating over response.
     *
     * @param to Recipient
     * @param via Instance of the bot through which the request will be made.
     */
    override suspend fun sendAsync(
        to: Long,
        via: TelegramBot,
    ): Deferred> = internalSendAsync(returnType, Recipient.Long(to), via)

    /**
     * Make request with ability operating over response.
     *
     * @param to Recipient
     * @param via Instance of the bot through which the request will be made.
     */
    override suspend fun sendAsync(
        to: User,
        via: TelegramBot,
    ): Deferred> = internalSendAsync(returnType, Recipient.Long(to.id), via)
}

/**
 * The internal method used to send the data with ability operating over response.
 *
 * @param returnType response type
 * @param to Recipient
 * @param via Instance of the bot through which the request will be made.
 * @return [Deferred]<[Response]<[R]>>
 */
internal suspend inline fun  MediaAction.internalSendAsync(
    returnType: Class,
    to: Recipient,
    via: TelegramBot,
): Deferred> {
    parameters["chat_id"] = to.get
    val filename = parameters["file_name"]?.toString()?.also {
        parameters.remove("file_name")
    } ?: media.name ?: "$dataField.$defaultType"

    return when (media) {
        is ImplicitFile.FromString -> {
            parameters[dataField] = media.file
            via.makeRequestAsync(method, parameters, returnType, wrappedDataType)
        }

        is ImplicitFile.FromByteArray -> via.makeRequestAsync(returnType, wrappedDataType) {
            method = [email protected]
            dataField = [email protected]
            name = filename
            data = media.bytes
            parameters = [email protected]
            contentType = defaultType.toContentType()
        }

        is ImplicitFile.FromFile -> via.makeRequestAsync(returnType, wrappedDataType) {
            method = [email protected]
            dataField = [email protected]
            name = filename
            data = media.bytes
            parameters = [email protected]
            contentType = withContext(Dispatchers.IO) {
                ContentType.parse(
                    Files.probeContentType((media.file as File).toPath())
                        ?: return@withContext defaultType.toContentType(),
                )
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy