mirror of
				https://github.com/InsanusMokrassar/BooruGrabberTelegramBot.git
				synced 2025-11-03 21:52:33 +00:00 
			
		
		
		
	Compare commits
	
		
			21 Commits
		
	
	
		
			5f3991e58e
			...
			renovate/g
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					5d55fe1c34 | ||
| f546c4791f | |||
| ecffb1dd07 | |||
| 34a8267568 | |||
| a8c317af44 | |||
| 3e2b6e67e9 | |||
| b81be8404c | |||
| d60898f4f1 | |||
| 115eb8bf3a | |||
| ebc4b80ef3 | |||
| 16e85b0878 | |||
| 
						 | 
					b7c33ded79 | ||
| 8863afa5a7 | |||
| 
						 | 
					9ff5ffa9c8 | ||
| 41549fbef1 | |||
| 4e2c5ea31e | |||
| 046a8bede4 | |||
| 8983eff109 | |||
| 4c7e4f375a | |||
| 8f2c98026b | |||
| 132349e1ea | 
							
								
								
									
										4
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							@@ -8,9 +8,9 @@ jobs:
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v2
 | 
			
		||||
      - name: Set up JDK 11
 | 
			
		||||
      - name: Set up JDK 17
 | 
			
		||||
        uses: actions/setup-java@v1
 | 
			
		||||
        with:
 | 
			
		||||
          java-version: 11
 | 
			
		||||
          java-version: 17
 | 
			
		||||
      - name: Build with Gradle
 | 
			
		||||
        run: ./gradlew build
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								.github/workflows/docker-publish.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.github/workflows/docker-publish.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
name: Docker
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches:
 | 
			
		||||
      - master
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  publishing:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    permissions:
 | 
			
		||||
      contents: read
 | 
			
		||||
      packages: write
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout repository
 | 
			
		||||
        uses: actions/checkout@v2
 | 
			
		||||
      - name: Set up JDK 17
 | 
			
		||||
        uses: actions/setup-java@v1
 | 
			
		||||
        with:
 | 
			
		||||
          java-version: 17
 | 
			
		||||
      - name: Log into registry
 | 
			
		||||
        uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
 | 
			
		||||
        with:
 | 
			
		||||
          username: ${{ secrets.DOCKER_LOGIN }}
 | 
			
		||||
          password: ${{ secrets.DOCKER_PASSWORD }}
 | 
			
		||||
      - name: Deploy
 | 
			
		||||
        run: ./gradlew build && ./nonsudo_deploy
 | 
			
		||||
							
								
								
									
										8
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
FROM bellsoft/liberica-openjdk-alpine:19
 | 
			
		||||
 | 
			
		||||
ADD ./build/distributions/booru_grabber_bot.tar /
 | 
			
		||||
RUN chown -R 1000:1000 "/booru_grabber_bot"
 | 
			
		||||
 | 
			
		||||
USER 1000
 | 
			
		||||
 | 
			
		||||
ENTRYPOINT ["/booru_grabber_bot/bin/booru_grabber_bot", "/booru_grabber_bot/config.json"]
 | 
			
		||||
@@ -33,6 +33,7 @@ dependencies {
 | 
			
		||||
    implementation libs.krontab
 | 
			
		||||
    implementation libs.psql
 | 
			
		||||
    implementation libs.imageboard
 | 
			
		||||
    implementation libs.ktor.client.okhttp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
application {
 | 
			
		||||
@@ -40,6 +41,6 @@ application {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
java {
 | 
			
		||||
    sourceCompatibility = JavaVersion.VERSION_11
 | 
			
		||||
    targetCompatibility = JavaVersion.VERSION_11
 | 
			
		||||
    sourceCompatibility = JavaVersion.VERSION_17
 | 
			
		||||
    targetCompatibility = JavaVersion.VERSION_17
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,3 +10,8 @@ services:
 | 
			
		||||
      POSTGRES_DB: "test"
 | 
			
		||||
    ports:
 | 
			
		||||
      - "8092:5432"
 | 
			
		||||
#  booru_grabber_bot:
 | 
			
		||||
#    image: insanusmokrassar/booru_grabber_bot
 | 
			
		||||
#    container_name: "booru_grabber_bot"
 | 
			
		||||
#    volumes:
 | 
			
		||||
#      - "path_to_file:/booru_grabber_bot/config.json:ro"
 | 
			
		||||
 
 | 
			
		||||
@@ -3,3 +3,5 @@ kotlin.code.style=official
 | 
			
		||||
org.gradle.parallel=true
 | 
			
		||||
kotlin.js.generate.externals=true
 | 
			
		||||
kotlin.incremental=true
 | 
			
		||||
 | 
			
		||||
docker_version=0.0.5
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,15 @@
 | 
			
		||||
[versions]
 | 
			
		||||
 | 
			
		||||
kotlin = "1.8.22"
 | 
			
		||||
tgbotapi = "9.1.0"
 | 
			
		||||
microutils = "0.19.9"
 | 
			
		||||
imageboard = "2.6.0"
 | 
			
		||||
krontab = "2.1.2"
 | 
			
		||||
kslog = "1.1.2"
 | 
			
		||||
exposed = "0.42.1"
 | 
			
		||||
psql = "42.6.0"
 | 
			
		||||
clikt = "3.5.2"
 | 
			
		||||
kotlin = "2.2.10"
 | 
			
		||||
tgbotapi = "28.0.2"
 | 
			
		||||
microutils = "0.26.3"
 | 
			
		||||
imageboard = "2.7.0"
 | 
			
		||||
krontab = "2.7.2"
 | 
			
		||||
kslog = "1.5.0"
 | 
			
		||||
ktor = "3.2.3"
 | 
			
		||||
exposed = "0.61.0"
 | 
			
		||||
psql = "42.7.4"
 | 
			
		||||
clikt = "5.0.1"
 | 
			
		||||
 | 
			
		||||
[libraries]
 | 
			
		||||
 | 
			
		||||
@@ -23,6 +24,8 @@ kslog = { module = "dev.inmo:kslog", version.ref = "kslog" }
 | 
			
		||||
exposed = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
 | 
			
		||||
psql = { module = "org.postgresql:postgresql", version.ref = "psql" }
 | 
			
		||||
 | 
			
		||||
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
 | 
			
		||||
 | 
			
		||||
imageboard = { module = "com.github.Kodehawa:imageboard-api", version.ref = "imageboard" }
 | 
			
		||||
 | 
			
		||||
clikt = { module = "com.github.ajalt.clikt:clikt", version.ref = "clikt" }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
distributionBase=GRADLE_USER_HOME
 | 
			
		||||
distributionPath=wrapper/dists
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
 | 
			
		||||
zipStoreBase=GRADLE_USER_HOME
 | 
			
		||||
zipStorePath=wrapper/dists
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								nonsudo_deploy
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								nonsudo_deploy
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
function send_notification() {
 | 
			
		||||
    echo "$1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function assert_success() {
 | 
			
		||||
    "${@}"
 | 
			
		||||
    local status=${?}
 | 
			
		||||
    if [ ${status} -ne 0 ]; then
 | 
			
		||||
        send_notification "### Error ${status} at: ${BASH_LINENO[*]} ###"
 | 
			
		||||
        exit ${status}
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
app=booru_grabber_bot
 | 
			
		||||
version="`grep ./gradle.properties -e "^docker_version=" | sed -e "s/docker_version=\(.*\)/\1/"`"
 | 
			
		||||
server=insanusmokrassar
 | 
			
		||||
 | 
			
		||||
assert_success docker build -t $app:"$version" .
 | 
			
		||||
assert_success docker tag $app:"$version" $server/$app:$version
 | 
			
		||||
assert_success docker tag $app:"$version" $server/$app:latest
 | 
			
		||||
assert_success docker push $server/$app:$version
 | 
			
		||||
assert_success docker push $server/$app:latest
 | 
			
		||||
							
								
								
									
										6
									
								
								renovate.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								renovate.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
 | 
			
		||||
  "extends": [
 | 
			
		||||
    "config:recommended"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1 @@
 | 
			
		||||
rootProject.name = 'booru_grabber_bot'
 | 
			
		||||
 | 
			
		||||
enableFeaturePreview("VERSION_CATALOGS")
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
import com.github.ajalt.clikt.core.parse
 | 
			
		||||
import dev.inmo.krontab.utils.asFlowWithDelays
 | 
			
		||||
import dev.inmo.micro_utils.coroutines.*
 | 
			
		||||
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
 | 
			
		||||
@@ -6,12 +7,12 @@ import dev.inmo.micro_utils.repos.cache.full.fullyCached
 | 
			
		||||
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
 | 
			
		||||
import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedKeyValuesRepo
 | 
			
		||||
import dev.inmo.micro_utils.repos.mappers.withMapper
 | 
			
		||||
import dev.inmo.tgbotapi.bot.ktor.telegramBot
 | 
			
		||||
import dev.inmo.tgbotapi.extensions.api.bot.getMe
 | 
			
		||||
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
 | 
			
		||||
import dev.inmo.tgbotapi.extensions.api.delete
 | 
			
		||||
import dev.inmo.tgbotapi.extensions.api.send.media.*
 | 
			
		||||
import dev.inmo.tgbotapi.extensions.api.send.reply
 | 
			
		||||
import dev.inmo.tgbotapi.extensions.api.telegramBot
 | 
			
		||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
 | 
			
		||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
 | 
			
		||||
import dev.inmo.tgbotapi.requests.abstracts.FileUrl
 | 
			
		||||
@@ -20,6 +21,7 @@ import dev.inmo.tgbotapi.types.chat.ChannelChat
 | 
			
		||||
import dev.inmo.tgbotapi.types.chat.PrivateChat
 | 
			
		||||
import dev.inmo.tgbotapi.types.media.TelegramMediaPhoto
 | 
			
		||||
import dev.inmo.tgbotapi.utils.code
 | 
			
		||||
import io.ktor.client.engine.okhttp.*
 | 
			
		||||
import java.io.File
 | 
			
		||||
import kotlinx.coroutines.*
 | 
			
		||||
import kotlinx.coroutines.sync.Mutex
 | 
			
		||||
@@ -29,6 +31,9 @@ import models.Config
 | 
			
		||||
import net.kodehawa.lib.imageboards.ImageBoard
 | 
			
		||||
import net.kodehawa.lib.imageboards.boards.DefaultBoards
 | 
			
		||||
import net.kodehawa.lib.imageboards.entities.BoardImage
 | 
			
		||||
import okhttp3.OkHttpClient
 | 
			
		||||
 | 
			
		||||
internal lateinit var InternalBoards: Boards
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This method by default expects one argument in [args] field: telegram bot configuration
 | 
			
		||||
@@ -39,7 +44,14 @@ suspend fun main(args: Array<String>) {
 | 
			
		||||
    // decode config
 | 
			
		||||
    val config: Config = json.decodeFromString(Config.serializer(), File(args.first()).readText())
 | 
			
		||||
    // that is your bot
 | 
			
		||||
    val bot = telegramBot(config.token)
 | 
			
		||||
    val bot = telegramBot(config.token, OkHttp) {
 | 
			
		||||
        config.client ?.apply { setupConfig() }
 | 
			
		||||
    }
 | 
			
		||||
    InternalBoards = Boards(
 | 
			
		||||
        OkHttpClient.Builder().apply {
 | 
			
		||||
            config.client ?.apply { setupConfig() }
 | 
			
		||||
        }.build()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    ImageBoard.setUserAgent("WhoAmI?")
 | 
			
		||||
 | 
			
		||||
@@ -52,9 +64,9 @@ suspend fun main(args: Array<String>) {
 | 
			
		||||
        { text("config") },
 | 
			
		||||
        "configs"
 | 
			
		||||
    ).withMapper(
 | 
			
		||||
        { chatId },
 | 
			
		||||
        { chatId.long },
 | 
			
		||||
        { json.encodeToString(ChatSettings.serializer(), this) },
 | 
			
		||||
        { ChatId(this) },
 | 
			
		||||
        { ChatId(RawChatId(this)) },
 | 
			
		||||
        { json.decodeFromString(ChatSettings.serializer(), this) },
 | 
			
		||||
    ).fullyCached(scope = scope)
 | 
			
		||||
 | 
			
		||||
@@ -64,9 +76,9 @@ suspend fun main(args: Array<String>) {
 | 
			
		||||
        { text("url") },
 | 
			
		||||
        "chatsUrlsSeen"
 | 
			
		||||
    ).withMapper(
 | 
			
		||||
        { chatId },
 | 
			
		||||
        { chatId.long },
 | 
			
		||||
        { this },
 | 
			
		||||
        { ChatId(this) },
 | 
			
		||||
        { ChatId(RawChatId(this)) },
 | 
			
		||||
        { this },
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
@@ -156,7 +168,7 @@ suspend fun main(args: Array<String>) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        onCommand(Regex("(help|start)"), requireOnlyCommandInMessage = true) {
 | 
			
		||||
            reply(it, EnableArgsParser().getFormattedHelp().takeIf { it.isNotBlank() } ?: return@onCommand)
 | 
			
		||||
            reply(it, EnableArgsParser().getFormattedHelp() ?.takeIf { it.isNotBlank() } ?: return@onCommand)
 | 
			
		||||
        }
 | 
			
		||||
        onCommand("enable", requireOnlyCommandInMessage = false) {
 | 
			
		||||
            val args = it.content.textSources.drop(1).joinToString("") { it.source }.split(" ")
 | 
			
		||||
@@ -167,7 +179,7 @@ suspend fun main(args: Array<String>) {
 | 
			
		||||
            }.onFailure { e ->
 | 
			
		||||
                e.printStackTrace()
 | 
			
		||||
                if (it.chat is PrivateChat) {
 | 
			
		||||
                    reply(it, parser.getFormattedHelp())
 | 
			
		||||
                    reply(it, parser.getFormattedHelp()!!)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            runCatchingSafely {
 | 
			
		||||
@@ -194,7 +206,7 @@ suspend fun main(args: Array<String>) {
 | 
			
		||||
                }.onFailure { e ->
 | 
			
		||||
                    e.printStackTrace()
 | 
			
		||||
                    if (it.chat is PrivateChat) {
 | 
			
		||||
                        reply(it, parser.getFormattedHelp())
 | 
			
		||||
                        reply(it, parser.getFormattedHelp()!!)
 | 
			
		||||
                    }
 | 
			
		||||
                }.getOrNull()
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								src/main/kotlin/Boards.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/kotlin/Boards.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
import net.kodehawa.lib.imageboards.ImageBoard
 | 
			
		||||
import net.kodehawa.lib.imageboards.boards.DefaultBoards
 | 
			
		||||
import net.kodehawa.lib.imageboards.entities.impl.*
 | 
			
		||||
import okhttp3.OkHttpClient
 | 
			
		||||
import java.util.concurrent.TimeUnit
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Boards(
 | 
			
		||||
    private val client: OkHttpClient = OkHttpClient.Builder()
 | 
			
		||||
        .connectTimeout(3, TimeUnit.SECONDS)
 | 
			
		||||
        .readTimeout(3, TimeUnit.SECONDS)
 | 
			
		||||
        .build()
 | 
			
		||||
) {
 | 
			
		||||
    val E621 = ImageBoard(client, DefaultBoards.E621, FurryImage::class.java)
 | 
			
		||||
    val KONACHAN = ImageBoard(client, DefaultBoards.KONACHAN, KonachanImage::class.java)
 | 
			
		||||
    val RULE34 = ImageBoard(client, DefaultBoards.R34, Rule34Image::class.java)
 | 
			
		||||
    val YANDERE = ImageBoard(client, DefaultBoards.YANDERE, YandereImage::class.java)
 | 
			
		||||
    val DANBOORU = ImageBoard(client, DefaultBoards.DANBOORU, DanbooruImage::class.java)
 | 
			
		||||
    val SAFEBOORU = ImageBoard(
 | 
			
		||||
        client, DefaultBoards.SAFEBOORU,
 | 
			
		||||
        SafebooruImage::class.java
 | 
			
		||||
    )
 | 
			
		||||
    val E926 = ImageBoard(client, DefaultBoards.E926, SafeFurryImage::class.java)
 | 
			
		||||
    val GELBOORU = ImageBoard(client, DefaultBoards.GELBOORU, GelbooruImage::class.java)
 | 
			
		||||
}
 | 
			
		||||
@@ -6,7 +6,6 @@ import kotlinx.serialization.builtins.serializer
 | 
			
		||||
import kotlinx.serialization.descriptors.SerialDescriptor
 | 
			
		||||
import kotlinx.serialization.encoding.Decoder
 | 
			
		||||
import kotlinx.serialization.encoding.Encoder
 | 
			
		||||
import net.kodehawa.lib.imageboards.DefaultImageBoards
 | 
			
		||||
import net.kodehawa.lib.imageboards.ImageBoard
 | 
			
		||||
import net.kodehawa.lib.imageboards.boards.DefaultBoards
 | 
			
		||||
import net.kodehawa.lib.imageboards.entities.BoardImage
 | 
			
		||||
@@ -29,14 +28,14 @@ data class ChatSettings(
 | 
			
		||||
 | 
			
		||||
    val board: ImageBoard<*>
 | 
			
		||||
        get() = when (boardBase) {
 | 
			
		||||
            DefaultBoards.R34 -> DefaultImageBoards.RULE34
 | 
			
		||||
            DefaultBoards.E621 -> DefaultImageBoards.E621
 | 
			
		||||
            DefaultBoards.KONACHAN -> DefaultImageBoards.KONACHAN
 | 
			
		||||
            DefaultBoards.YANDERE -> DefaultImageBoards.YANDERE
 | 
			
		||||
            DefaultBoards.DANBOORU -> DefaultImageBoards.DANBOORU
 | 
			
		||||
            DefaultBoards.SAFEBOORU -> DefaultImageBoards.SAFEBOORU
 | 
			
		||||
            DefaultBoards.GELBOORU -> DefaultImageBoards.GELBOORU
 | 
			
		||||
            DefaultBoards.E926 -> DefaultImageBoards.E926
 | 
			
		||||
            DefaultBoards.R34 -> InternalBoards.RULE34
 | 
			
		||||
            DefaultBoards.E621 -> InternalBoards.E621
 | 
			
		||||
            DefaultBoards.KONACHAN -> InternalBoards.KONACHAN
 | 
			
		||||
            DefaultBoards.YANDERE -> InternalBoards.YANDERE
 | 
			
		||||
            DefaultBoards.DANBOORU -> InternalBoards.DANBOORU
 | 
			
		||||
            DefaultBoards.SAFEBOORU -> InternalBoards.SAFEBOORU
 | 
			
		||||
            DefaultBoards.GELBOORU -> InternalBoards.GELBOORU
 | 
			
		||||
            DefaultBoards.E926 -> InternalBoards.E926
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    suspend fun makeRequest(page: Int): List<BoardImage> {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,5 +5,6 @@ import kotlinx.serialization.Serializable
 | 
			
		||||
@Serializable
 | 
			
		||||
data class Config(
 | 
			
		||||
    val token: String,
 | 
			
		||||
    val database: DatabaseConfig
 | 
			
		||||
    val database: DatabaseConfig,
 | 
			
		||||
    val client: HttpClientConfig? = null
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										96
									
								
								src/main/kotlin/models/HttpClientConfig.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/main/kotlin/models/HttpClientConfig.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
import dev.inmo.tgbotapi.types.MilliSeconds
 | 
			
		||||
import io.ktor.client.HttpClientConfig
 | 
			
		||||
import io.ktor.client.engine.okhttp.*
 | 
			
		||||
import io.ktor.client.plugins.*
 | 
			
		||||
import io.ktor.client.request.*
 | 
			
		||||
import io.ktor.http.*
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import okhttp3.OkHttpClient
 | 
			
		||||
import java.net.*
 | 
			
		||||
import java.util.*
 | 
			
		||||
import java.util.concurrent.TimeUnit
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
data class HttpClientConfig(
 | 
			
		||||
    val connectionTimeoutMillis: MilliSeconds? = null,
 | 
			
		||||
    val requestTimeoutMillis: MilliSeconds? = null,
 | 
			
		||||
    val responseTimeoutMillis: MilliSeconds? = null,
 | 
			
		||||
    val proxy: ProxyConfig? = null
 | 
			
		||||
) {
 | 
			
		||||
    @Serializable
 | 
			
		||||
    data class ProxyConfig(
 | 
			
		||||
        val hostname: String,
 | 
			
		||||
        val type: ProxyType = ProxyType.socks,
 | 
			
		||||
        val port: Int = type.defaultPort,
 | 
			
		||||
        val username: String? = null,
 | 
			
		||||
        val password: String? = null
 | 
			
		||||
    ) {
 | 
			
		||||
        @Serializable
 | 
			
		||||
        enum class ProxyType(val defaultPort: Int, val proxyType: Proxy.Type) {
 | 
			
		||||
            socks(1080, Proxy.Type.SOCKS),
 | 
			
		||||
            http(3128, Proxy.Type.HTTP),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val socketAddress
 | 
			
		||||
            get() = InetSocketAddress(hostname, port)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun OkHttpClient.Builder.setupConfig() {
 | 
			
		||||
        // setting up connection timeout millis
 | 
			
		||||
        connectionTimeoutMillis ?.let { connectTimeout(it, TimeUnit.MILLISECONDS) }
 | 
			
		||||
        // setting up write timeout millis
 | 
			
		||||
        requestTimeoutMillis ?.let { writeTimeout(it, TimeUnit.MILLISECONDS) }
 | 
			
		||||
        // setting up read timeout millis
 | 
			
		||||
        responseTimeoutMillis ?.let { readTimeout(it, TimeUnit.MILLISECONDS) }
 | 
			
		||||
 | 
			
		||||
        // Start setup bot client engine proxy
 | 
			
		||||
        this@HttpClientConfig.proxy ?.let { proxyConfig ->
 | 
			
		||||
            proxy(
 | 
			
		||||
                Proxy(
 | 
			
		||||
                    proxyConfig.type.proxyType,
 | 
			
		||||
                    proxyConfig.socketAddress
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            proxyConfig.username ?.let { username ->
 | 
			
		||||
                if (proxyConfig.type == ProxyConfig.ProxyType.socks) {
 | 
			
		||||
                    val passwordAuthentication = PasswordAuthentication(
 | 
			
		||||
                        username,
 | 
			
		||||
                        proxyConfig.password ?.toCharArray() ?: error("For Socks proxy you should use both username and password or do not use authentication at all")
 | 
			
		||||
                    )
 | 
			
		||||
                    Authenticator.setDefault(object : Authenticator() {
 | 
			
		||||
                        override fun getPasswordAuthentication(): PasswordAuthentication? {
 | 
			
		||||
                            return if (requestingHost.lowercase() == proxyConfig.hostname.lowercase()) {
 | 
			
		||||
                                passwordAuthentication
 | 
			
		||||
                            } else {
 | 
			
		||||
                                null
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun HttpClientConfig<OkHttpConfig>.setupConfig() {
 | 
			
		||||
        // setting up telegram bot client
 | 
			
		||||
        engine {
 | 
			
		||||
            // Start setup bot client engine configuration
 | 
			
		||||
            config {
 | 
			
		||||
                setupConfig()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        proxy ?.username ?.let { username ->
 | 
			
		||||
            if (proxy.type == ProxyConfig.ProxyType.http) {
 | 
			
		||||
                val passwordSuffix = proxy.password ?.let { ":$it" }
 | 
			
		||||
                val credentials = Base64.getEncoder().encodeToString("${username}${passwordSuffix}".toByteArray())
 | 
			
		||||
                this@setupConfig.defaultRequest {
 | 
			
		||||
                    header(HttpHeaders.ProxyAuthorization, "Basic $credentials")
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user