mirror of
				https://github.com/InsanusMokrassar/BooruGrabberTelegramBot.git
				synced 2025-10-25 09:10:13 +00:00 
			
		
		
		
	Compare commits
	
		
			25 Commits
		
	
	
		
			ea801e6e0d
			...
			renovate/p
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | e952749084 | ||
| f546c4791f | |||
| ecffb1dd07 | |||
| 34a8267568 | |||
| a8c317af44 | |||
| 3e2b6e67e9 | |||
| b81be8404c | |||
| d60898f4f1 | |||
| 115eb8bf3a | |||
| ebc4b80ef3 | |||
| 16e85b0878 | |||
|  | b7c33ded79 | ||
| 8863afa5a7 | |||
|  | 9ff5ffa9c8 | ||
| 41549fbef1 | |||
| 4e2c5ea31e | |||
| 046a8bede4 | |||
| 8983eff109 | |||
| 4c7e4f375a | |||
| 8f2c98026b | |||
| 132349e1ea | |||
| 5f3991e58e | |||
| 3cb74bd587 | |||
| 4a90e0f427 | |||
| edf6c9717b | 
							
								
								
									
										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.7.22" | ||||
| tgbotapi = "4.2.1" | ||||
| microutils = "0.16.1" | ||||
| imageboard = "2.5.2" | ||||
| krontab = "0.8.4" | ||||
| kslog = "0.5.4" | ||||
| exposed = "0.41.1" | ||||
| psql = "42.5.0" | ||||
| clikt = "3.5.0" | ||||
| 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.8" | ||||
| 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-bin.zip | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-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" | ||||
|   ] | ||||
| } | ||||
| @@ -2,6 +2,6 @@ FROM adoptopenjdk/openjdk11 | ||||
|  | ||||
| USER 1000 | ||||
|  | ||||
| ENTRYPOINT ["/booru_grabber_bot/bin/booru_grabber_bot", "/booru_grabber_bot/local.config.json"] | ||||
| ENTRYPOINT ["/booru_grabber_bot/bin/booru_grabber_bot", "/booru_grabber_bot/config.json"] | ||||
|  | ||||
| ADD ./build/distributions/booru_grabber_bot.tar / | ||||
|   | ||||
| @@ -17,7 +17,7 @@ app=booru_grabber_bot | ||||
| version=0.0.1 | ||||
| server=hub.docker.com | ||||
|  | ||||
| assert_success ../gradlew build | ||||
| assert_success ./gradlew build | ||||
| # scp ./build/distributions/AutoPostTestTelegramBot-1.0.0.zip ./config.json developer@insanusmokrassar.dev:/tmp/ | ||||
| assert_success sudo docker build -t $app:"$version" . | ||||
| assert_success sudo docker tag $app:"$version" $server/$app:$version | ||||
|   | ||||
| @@ -1,3 +1 @@ | ||||
| rootProject.name = 'booru_grabber_bot' | ||||
|  | ||||
| enableFeaturePreview("VERSION_CATALOGS") | ||||
|   | ||||
| @@ -1,19 +1,18 @@ | ||||
| import dev.inmo.krontab.utils.asFlow | ||||
| 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 | ||||
| import dev.inmo.micro_utils.repos.* | ||||
| import dev.inmo.micro_utils.repos.cache.cache.FullKVCache | ||||
| import dev.inmo.micro_utils.repos.cache.cache.KVCache | ||||
| import dev.inmo.micro_utils.repos.cache.cached | ||||
| 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 | ||||
| @@ -22,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 | ||||
| @@ -31,7 +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 kotlin.reflect.full.memberProperties | ||||
| import okhttp3.OkHttpClient | ||||
|  | ||||
| internal lateinit var InternalBoards: Boards | ||||
|  | ||||
| /** | ||||
|  * This method by default expects one argument in [args] field: telegram bot configuration | ||||
| @@ -42,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?") | ||||
|  | ||||
| @@ -55,23 +64,23 @@ 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) }, | ||||
|     ).cached(FullKVCache(), scope = scope) | ||||
|     ).fullyCached(scope = scope) | ||||
|  | ||||
|     val chatsUrlsSeen = ExposedKeyValuesRepo( | ||||
|     val chatsUrlsSeenRepo = ExposedKeyValuesRepo( | ||||
|         config.database.database, | ||||
|         { long("chat_id") }, | ||||
|         { text("url") }, | ||||
|         "chatsUrlsSeen" | ||||
|     ).withMapper( | ||||
|         { chatId }, | ||||
|         { chatId.long }, | ||||
|         { this }, | ||||
|         { ChatId(this) }, | ||||
|         { ChatId(RawChatId(this)) }, | ||||
|         { this }, | ||||
|     ).cached(KVCache(128), scope = scope) | ||||
|     ) | ||||
|  | ||||
|     val chatsChangingMutex = Mutex() | ||||
|     val chatsSendingJobs = mutableMapOf<ChatId, Job>() | ||||
| @@ -82,6 +91,7 @@ suspend fun main(args: Array<String>) { | ||||
|         val me = getMe() | ||||
|  | ||||
|         suspend fun triggerSendForChat(chatId: ChatId, settings: ChatSettings) { | ||||
|             val seenUrls = chatsUrlsSeenRepo.getAll(chatId).toMutableSet() | ||||
|             val result = let { | ||||
|                 val result = mutableListOf<BoardImage>() | ||||
|                 var i = 0 | ||||
| @@ -89,17 +99,17 @@ suspend fun main(args: Array<String>) { | ||||
|                     val images = settings.makeRequest(i).takeIf { it.isNotEmpty() } ?: break | ||||
|                     result.addAll( | ||||
|                         images.filterNot { | ||||
|                             chatsUrlsSeen.contains(chatId, it.url) | ||||
|                             seenUrls.contains(it.url ?: return@filterNot true) | ||||
|                         } | ||||
|                     ) | ||||
|                     i++ | ||||
|                 } | ||||
|                 val toDrop = (result.size - settings.count).takeIf { it > 0 } ?: return@let result | ||||
|                 result.dropLast(toDrop) | ||||
|                 result.take(settings.count) | ||||
|             }.takeIf { it.isNotEmpty() } ?: return | ||||
|             runCatchingSafely { | ||||
|                 val urls = result.map { it.url } | ||||
|                 chatsUrlsSeen.add(chatId, urls) | ||||
|                 chatsUrlsSeenRepo.add(chatId, urls) | ||||
|                 seenUrls.addAll(urls) | ||||
|                 when { | ||||
|                     urls.isEmpty() -> return@runCatchingSafely | ||||
|                     urls.size == 1 -> sendPhoto( | ||||
| @@ -133,23 +143,13 @@ suspend fun main(args: Array<String>) { | ||||
|             chatsChangingMutex.withLock { | ||||
|                 chatsSendingJobs[chatId] ?.cancel() | ||||
|                 settings ?.scheduler ?.let { | ||||
|                     chatsSendingJobs[chatId] = it.asFlow().subscribeSafelyWithoutExceptions(scope) { | ||||
|                     chatsSendingJobs[chatId] = it.asFlowWithDelays().subscribeSafelyWithoutExceptions(scope) { | ||||
|                         triggerSendForChat(chatId, settings) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         doForAllWithNextPaging { | ||||
|             repo.keys(it).also { | ||||
|                 it.results.forEach { | ||||
|                     runCatchingSafely { | ||||
|                         refreshChatJob(it, null) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         repo.onNewValue.subscribeSafelyWithoutExceptions(this) { | ||||
|             refreshChatJob(it.first, it.second) | ||||
|         } | ||||
| @@ -157,19 +157,29 @@ suspend fun main(args: Array<String>) { | ||||
|             refreshChatJob(it, null) | ||||
|         } | ||||
|  | ||||
|         doForAllWithNextPaging { | ||||
|             repo.keys(it).also { | ||||
|                 it.results.forEach { | ||||
|                     runCatchingSafely { | ||||
|                         refreshChatJob(it, null) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         onCommand(Regex("(help|start)"), requireOnlyCommandInMessage = true) { | ||||
|             reply(it, EnableArgsParser(onlyQueryIsRequired = false).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(" ") | ||||
|             val parser = EnableArgsParser(onlyQueryIsRequired = false) | ||||
|             val parser = EnableArgsParser() | ||||
|             runCatchingSafely { | ||||
|                 parser.parse(args) | ||||
|                 repo.set(ChatId(it.chat.id.chatId), parser.resultSettings ?: return@runCatchingSafely) | ||||
|             }.onFailure { e -> | ||||
|                 e.printStackTrace() | ||||
|                 if (it.chat is PrivateChat) { | ||||
|                     reply(it, parser.getFormattedHelp()) | ||||
|                     reply(it, parser.getFormattedHelp()!!) | ||||
|                 } | ||||
|             } | ||||
|             runCatchingSafely { | ||||
| @@ -189,14 +199,14 @@ suspend fun main(args: Array<String>) { | ||||
|                     return@onCommand | ||||
|                 } | ||||
|             } else { | ||||
|                 val parser = EnableArgsParser(onlyQueryIsRequired = true, repo.get(ChatId(it.chat.id.chatId)) ?: ChatSettings.DEFAULT) | ||||
|                 val parser = EnableArgsParser(repo.get(ChatId(it.chat.id.chatId)) ?: ChatSettings.DEFAULT) | ||||
|                 runCatchingSafely { | ||||
|                     parser.parse(args) | ||||
|                     parser.resultSettings | ||||
|                 }.onFailure { e -> | ||||
|                     e.printStackTrace() | ||||
|                     if (it.chat is PrivateChat) { | ||||
|                         reply(it, parser.getFormattedHelp()) | ||||
|                         reply(it, parser.getFormattedHelp()!!) | ||||
|                     } | ||||
|                 }.getOrNull() | ||||
|             } | ||||
| @@ -226,7 +236,18 @@ suspend fun main(args: Array<String>) { | ||||
|                         +"Count: " + code(settings.count.toString()) + "\n" | ||||
|                         +"Gallery: " + code(settings.gallery.toString()) + "\n" | ||||
|                         +"Rating: " + code(settings.rating ?.name ?: "unset") + "\n" | ||||
|                         +"Attach urls: " + code(settings.attachUrls.toString()) | ||||
|                         +"Attach urls: " + code(settings.attachUrls.toString()) + "\n" | ||||
|                         +"Command: " + code( | ||||
|                             "/request " + | ||||
|                                 "${settings.query} " + | ||||
|                                 (settings.krontabTemplate ?.let { "-k $it " } ?: "") + | ||||
|                                 "-b ${DefaultBoards.values().first { it == settings.board.boardType }.name.lowercase()} " + | ||||
|                                 "-n ${settings.count} " + | ||||
|                                 (if (settings.gallery) "-g " else "") + | ||||
|                                 (settings.rating ?.let { "-r ${it.name} " } ?: "") + | ||||
|                                 (if (settings.attachUrls) "-a " else "") | ||||
|  | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|   | ||||
							
								
								
									
										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,19 +28,19 @@ 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> { | ||||
|         return withContext(Dispatchers.IO) { | ||||
|             board.search(page, count, query, rating).blocking() | ||||
|             board.search(page, count, query, rating).blocking() ?: emptyList() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -7,8 +7,7 @@ import net.kodehawa.lib.imageboards.boards.DefaultBoards | ||||
| import net.kodehawa.lib.imageboards.entities.Rating | ||||
|  | ||||
| class EnableArgsParser( | ||||
|     onlyQueryIsRequired: Boolean, | ||||
|     private val base: ChatSettings = ChatSettings("", null, DefaultBoards.SAFEBOORU) | ||||
|     private val base: ChatSettings = ChatSettings.DEFAULT | ||||
| ) : CliktCommand(name = "enable") { | ||||
|     private fun <EachT : Any, ValueT> NullableOption<EachT, ValueT>.default( | ||||
|         value: EachT?, | ||||
| @@ -26,6 +25,7 @@ class EnableArgsParser( | ||||
|         .check("Count should be in range 1-10") { it in 1 .. 10 } | ||||
|     val query by argument() | ||||
|         .multiple(required = true) | ||||
|         .optional() | ||||
|         .help("Your query to booru. Use syntax \"-- -sometag\" to add excluding of some tag in query") | ||||
|     val krontab by option("-k", "--krontab") | ||||
|         .transformValues(5) { it.joinToString(" ") } | ||||
| @@ -47,7 +47,7 @@ class EnableArgsParser( | ||||
|  | ||||
|     override fun run() { | ||||
|         resultSettings = ChatSettings( | ||||
|             query.filterNot { it.isEmpty() }.joinToString(" ").trim(), | ||||
|             query ?.filterNot { it.isEmpty() } ?.joinToString(" ") ?.trim() ?: base.query, | ||||
|             krontab, | ||||
|             board ?: base.board.boardType as DefaultBoards, | ||||
|             count ?: base.count, | ||||
|   | ||||
| @@ -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