1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-09-05 16:19:26 +00:00
This commit is contained in:
2018-12-26 16:07:24 +08:00
parent 120db4c445
commit 89eda29965
330 changed files with 6934 additions and 3 deletions

View File

@@ -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()
)
}

View File

@@ -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?
}

View File

@@ -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"
)
}
}
}

View File

@@ -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()
}
}
}

View File

@@ -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()
}
}
}

View File

@@ -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()
}
}
}

View File

@@ -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
)

View File

@@ -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
}