mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-09-05 16:19:26 +00:00
init
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
abstract class BaseRequestsExecutor(
|
||||
token: String,
|
||||
hostUrl: String = "https://api.telegram.org"
|
||||
) : RequestsExecutor {
|
||||
protected val baseUrl: String = "$hostUrl/bot$token"
|
||||
|
||||
protected val scope: CoroutineScope = CoroutineScope(
|
||||
Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||
)
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor
|
||||
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.HttpClientCall
|
||||
|
||||
interface KtorCallFactory {
|
||||
suspend fun <T: Any> prepareCall(
|
||||
client: HttpClient,
|
||||
baseUrl: String,
|
||||
request: Request<T>
|
||||
) : HttpClientCall?
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor
|
||||
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.BaseRequestsExecutor
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base.MultipartRequestCallFactory
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base.SimpleRequestCallFactory
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestException
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ResponseParameters
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.HttpClientCall
|
||||
import io.ktor.client.engine.HttpClientEngine
|
||||
import io.ktor.client.engine.okhttp.OkHttp
|
||||
import io.ktor.util.cio.toByteArray
|
||||
import kotlinx.io.charsets.Charset
|
||||
import kotlinx.serialization.json.JSON
|
||||
|
||||
class KtorRequestsExecutor(
|
||||
token: String,
|
||||
private val client: HttpClient = HttpClient(OkHttp),
|
||||
hostUrl: String = "https://api.telegram.org",
|
||||
callsFactories: List<KtorCallFactory> = emptyList(),
|
||||
excludeDefaultFactories: Boolean = false
|
||||
) : BaseRequestsExecutor(token, hostUrl) {
|
||||
constructor(
|
||||
token: String,
|
||||
engine: HttpClientEngine = OkHttp.create(),
|
||||
hostUrl: String = "https://api.telegram.org"
|
||||
) : this(
|
||||
token,
|
||||
HttpClient(engine),
|
||||
hostUrl
|
||||
)
|
||||
|
||||
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
|
||||
if (!excludeDefaultFactories) {
|
||||
asSequence().plus(SimpleRequestCallFactory()).plus(MultipartRequestCallFactory()).toList()
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> execute(request: Request<T>): T {
|
||||
var call: HttpClientCall? = null
|
||||
for (factory in callsFactories) {
|
||||
call = factory.prepareCall(
|
||||
client,
|
||||
baseUrl,
|
||||
request
|
||||
)
|
||||
if (call != null) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (call == null) {
|
||||
throw IllegalArgumentException("Can't execute request: $request")
|
||||
}
|
||||
val content = call.response.content.toByteArray().toString(Charset.defaultCharset())
|
||||
val responseObject = JSON.parse(
|
||||
ResponseParameters.serializer(request.resultSerializer()),
|
||||
content
|
||||
)
|
||||
return responseObject.result ?: call.let {
|
||||
throw RequestException(
|
||||
responseObject,
|
||||
"Can't get result object"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base
|
||||
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorCallFactory
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.*
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapWithCommonValues
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.HttpClientCall
|
||||
import io.ktor.client.call.call
|
||||
import io.ktor.client.request.accept
|
||||
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||
import io.ktor.client.request.forms.formData
|
||||
import io.ktor.client.request.url
|
||||
import io.ktor.http.*
|
||||
import kotlinx.io.streams.asInput
|
||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||
|
||||
class MultipartRequestCallFactory : KtorCallFactory {
|
||||
@ImplicitReflectionSerializer
|
||||
override suspend fun <T: Any> prepareCall(
|
||||
client: HttpClient,
|
||||
baseUrl: String,
|
||||
request: Request<T>
|
||||
): HttpClientCall? = (request as? MultipartRequest) ?.let {
|
||||
castedRequest ->
|
||||
client.call {
|
||||
url("$baseUrl/${castedRequest.method()}")
|
||||
method = HttpMethod.Post
|
||||
accept(ContentType.Application.Json)
|
||||
body = MultiPartFormDataContent(
|
||||
formData {
|
||||
val params = castedRequest.paramsJson.mapWithCommonValues()
|
||||
for ((key, value) in castedRequest.mediaMap + params) {
|
||||
when (value) {
|
||||
is MultipartFile -> append(
|
||||
key,
|
||||
value.file.inputStream().asInput(),
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, value.mimeType)
|
||||
append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
|
||||
}
|
||||
)
|
||||
is FileId -> append(key, value.fileId)
|
||||
else -> append(key, value.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
build()
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.base
|
||||
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorCallFactory
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.SimpleRequest
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.HttpClientCall
|
||||
import io.ktor.client.call.call
|
||||
import io.ktor.client.request.accept
|
||||
import io.ktor.client.request.url
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.content.TextContent
|
||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||
|
||||
class SimpleRequestCallFactory : KtorCallFactory {
|
||||
@ImplicitReflectionSerializer
|
||||
override suspend fun <T: Any> prepareCall(
|
||||
client: HttpClient,
|
||||
baseUrl: String,
|
||||
request: Request<T>
|
||||
): HttpClientCall? = (request as? SimpleRequest<T>) ?.let {
|
||||
castedRequest ->
|
||||
client.call {
|
||||
url("$baseUrl/${castedRequest.method()}")
|
||||
method = HttpMethod.Post
|
||||
accept(ContentType.Application.Json)
|
||||
|
||||
val content = request.toJsonWithoutNulls().toString()
|
||||
|
||||
body = TextContent(
|
||||
content,
|
||||
ContentType.Application.Json
|
||||
)
|
||||
build()
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot
|
||||
|
||||
import okhttp3.Credentials
|
||||
import okhttp3.OkHttpClient
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Proxy
|
||||
|
||||
data class ProxySettings(
|
||||
val host: String = "localhost",
|
||||
val port: Int = 1080,
|
||||
val username: String? = null,
|
||||
val password: String? = null
|
||||
)
|
||||
|
||||
fun OkHttpClient.Builder.useWith(proxySettings: ProxySettings) {
|
||||
proxy(
|
||||
Proxy(
|
||||
Proxy.Type.SOCKS,
|
||||
InetSocketAddress(
|
||||
proxySettings.host,
|
||||
proxySettings.port
|
||||
)
|
||||
)
|
||||
)
|
||||
proxySettings.password ?.let {
|
||||
password ->
|
||||
proxyAuthenticator {
|
||||
_, response ->
|
||||
response.request().newBuilder().apply {
|
||||
addHeader(
|
||||
"Proxy-Authorization",
|
||||
Credentials.basic(proxySettings.username ?: "", password)
|
||||
)
|
||||
}.build()
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot
|
||||
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ResponseParameters
|
||||
import java.io.IOException
|
||||
|
||||
class RequestException(
|
||||
val response: ResponseParameters<*>,
|
||||
message: String? = null,
|
||||
cause: Throwable? = null
|
||||
) : IOException(
|
||||
message,
|
||||
cause
|
||||
)
|
@@ -0,0 +1,8 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot
|
||||
|
||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
|
||||
|
||||
interface RequestsExecutor {
|
||||
@Throws(RequestException::class)
|
||||
suspend fun <T : Any> execute(request: Request<T>): T
|
||||
}
|
Reference in New Issue
Block a user