mirror of
https://github.com/InsanusMokrassar/BooruGrabberTelegramBot.git
synced 2026-05-10 09:20:03 +00:00
Compare commits
2 Commits
f33aaa9eb5
...
0.0.6
| Author | SHA1 | Date | |
|---|---|---|---|
| 348f17127f | |||
| f546c4791f |
93
README.md
93
README.md
@@ -13,6 +13,99 @@ Bot for booru-boards grabbing. It uses [imageboard-api](https://github.com/Kodeh
|
||||
|
||||
Sample bot presented here: [@booru_grabber_bot](https://t.me/booru_grabber_bot)
|
||||
|
||||
## Fast how to start
|
||||
|
||||
1. Create a `config.json`. Minimal required config:
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "your bot token",
|
||||
"database": {
|
||||
"url": "jdbc:postgresql://booru_grabber_postgres:5432/test",
|
||||
"username": "test",
|
||||
"password": "test"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
All available properties:
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "your bot token",
|
||||
"database": {
|
||||
"url": "jdbc:postgresql://booru_grabber_postgres:5432/test",
|
||||
"driver": "org.postgresql.Driver",
|
||||
"username": "test",
|
||||
"password": "test",
|
||||
"reconnectOptions": {
|
||||
"attempts": 3,
|
||||
"delay": 1000
|
||||
}
|
||||
},
|
||||
"client": {
|
||||
"connectionTimeoutMillis": null,
|
||||
"requestTimeoutMillis": null,
|
||||
"responseTimeoutMillis": null,
|
||||
"proxy": {
|
||||
"hostname": "proxy.example.com",
|
||||
"type": "socks",
|
||||
"port": 1080,
|
||||
"username": null,
|
||||
"password": null
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Property reference:
|
||||
|
||||
**`token`** *(required)* — Telegram bot token from [@BotFather](https://t.me/BotFather).
|
||||
|
||||
**`database`** *(required)*:
|
||||
|
||||
- `url` — JDBC connection URL (default: `jdbc:pgsql://localhost:12346/test`)
|
||||
- `driver` — JDBC driver class (default: `org.postgresql.Driver`)
|
||||
- `username` — database user (default: empty)
|
||||
- `password` — database password (default: empty)
|
||||
- `reconnectOptions.attempts` — how many times to retry connecting on startup (default: `3`)
|
||||
- `reconnectOptions.delay` — delay in milliseconds between retries (default: `1000`)
|
||||
|
||||
**`client`** *(optional)* — HTTP client settings for Telegram API requests:
|
||||
|
||||
- `connectionTimeoutMillis` — connection timeout in ms
|
||||
- `requestTimeoutMillis` — write/request timeout in ms
|
||||
- `responseTimeoutMillis` — read/response timeout in ms
|
||||
- `proxy.hostname` *(required if proxy set)* — proxy host
|
||||
- `proxy.type` — `socks` (default) or `http`
|
||||
- `proxy.port` — proxy port (default: `1080` for socks, `3128` for http)
|
||||
- `proxy.username` — proxy username (optional; for socks, password is required when username is set)
|
||||
- `proxy.password` — proxy password (optional)
|
||||
|
||||
2. In `docker-compose.yml`, uncomment the `booru_grabber_bot` service and set the path to your config file:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
booru_grabber_postgres:
|
||||
image: postgres
|
||||
container_name: "booru_grabber_postgres"
|
||||
environment:
|
||||
POSTGRES_USER: "test"
|
||||
POSTGRES_PASSWORD: "test"
|
||||
POSTGRES_DB: "test"
|
||||
booru_grabber_bot:
|
||||
image: insanusmokrassar/booru_grabber_bot
|
||||
container_name: "booru_grabber_bot"
|
||||
volumes:
|
||||
- "/absolute/path/to/config.json:/booru_grabber_bot/config.json:ro"
|
||||
```
|
||||
|
||||
3. Start the services:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Available commands
|
||||
|
||||
Bot have two helping commands: `/start` and `/help`. These commands will return help for bot `/request`/`/enable` commands:
|
||||
|
||||
@@ -4,4 +4,4 @@ org.gradle.parallel=true
|
||||
kotlin.js.generate.externals=true
|
||||
kotlin.incremental=true
|
||||
|
||||
docker_version=0.0.5
|
||||
docker_version=0.0.6
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
[versions]
|
||||
|
||||
kotlin = "2.0.21"
|
||||
tgbotapi = "20.0.1"
|
||||
microutils = "0.23.0"
|
||||
imageboard = "2.7.0"
|
||||
krontab = "2.6.1"
|
||||
kslog = "1.3.6"
|
||||
ktor = "3.0.1"
|
||||
exposed = "0.55.0"
|
||||
psql = "42.7.4"
|
||||
clikt = "5.0.1"
|
||||
kotlin = "2.3.21"
|
||||
tgbotapi = "33.1.0"
|
||||
microutils = "0.29.2"
|
||||
imageboard = "2.6.1.1"
|
||||
krontab = "2.9.0"
|
||||
kslog = "1.6.1"
|
||||
ktor = "3.4.3"
|
||||
exposed = "1.2.0"
|
||||
psql = "42.7.11"
|
||||
clikt = "5.1.0"
|
||||
|
||||
[libraries]
|
||||
|
||||
|
||||
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-8.10.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -106,12 +106,12 @@ suspend fun main(args: Array<String>) {
|
||||
}
|
||||
result.take(settings.count)
|
||||
}.takeIf { it.isNotEmpty() } ?: return
|
||||
runCatchingSafely {
|
||||
runCatchingLogging {
|
||||
val urls = result.map { it.url }
|
||||
chatsUrlsSeenRepo.add(chatId, urls)
|
||||
seenUrls.addAll(urls)
|
||||
when {
|
||||
urls.isEmpty() -> return@runCatchingSafely
|
||||
urls.isEmpty() -> return@runCatchingLogging
|
||||
urls.size == 1 -> sendPhoto(
|
||||
chatId,
|
||||
FileUrl(urls.first()),
|
||||
@@ -143,24 +143,24 @@ suspend fun main(args: Array<String>) {
|
||||
chatsChangingMutex.withLock {
|
||||
chatsSendingJobs[chatId] ?.cancel()
|
||||
settings ?.scheduler ?.let {
|
||||
chatsSendingJobs[chatId] = it.asFlowWithDelays().subscribeSafelyWithoutExceptions(scope) {
|
||||
chatsSendingJobs[chatId] = it.asFlowWithDelays().subscribeLoggingDropExceptions(scope) {
|
||||
triggerSendForChat(chatId, settings)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repo.onNewValue.subscribeSafelyWithoutExceptions(this) {
|
||||
repo.onNewValue.subscribeLoggingDropExceptions(this) {
|
||||
refreshChatJob(it.first, it.second)
|
||||
}
|
||||
repo.onValueRemoved.subscribeSafelyWithoutExceptions(this) {
|
||||
repo.onValueRemoved.subscribeLoggingDropExceptions(this) {
|
||||
refreshChatJob(it, null)
|
||||
}
|
||||
|
||||
doForAllWithNextPaging {
|
||||
repo.keys(it).also {
|
||||
it.results.forEach {
|
||||
runCatchingSafely {
|
||||
runCatchingLogging {
|
||||
refreshChatJob(it, null)
|
||||
}
|
||||
}
|
||||
@@ -173,16 +173,16 @@ suspend fun main(args: Array<String>) {
|
||||
onCommand("enable", requireOnlyCommandInMessage = false) {
|
||||
val args = it.content.textSources.drop(1).joinToString("") { it.source }.split(" ")
|
||||
val parser = EnableArgsParser()
|
||||
runCatchingSafely {
|
||||
runCatchingLogging {
|
||||
parser.parse(args)
|
||||
repo.set(ChatId(it.chat.id.chatId), parser.resultSettings ?: return@runCatchingSafely)
|
||||
repo.set(ChatId(it.chat.id.chatId), parser.resultSettings ?: return@runCatchingLogging)
|
||||
}.onFailure { e ->
|
||||
e.printStackTrace()
|
||||
if (it.chat is PrivateChat) {
|
||||
reply(it, parser.getFormattedHelp()!!)
|
||||
}
|
||||
}
|
||||
runCatchingSafely {
|
||||
runCatchingLogging {
|
||||
if (it.chat is ChannelChat) {
|
||||
delete(it)
|
||||
}
|
||||
@@ -200,7 +200,7 @@ suspend fun main(args: Array<String>) {
|
||||
}
|
||||
} else {
|
||||
val parser = EnableArgsParser(repo.get(ChatId(it.chat.id.chatId)) ?: ChatSettings.DEFAULT)
|
||||
runCatchingSafely {
|
||||
runCatchingLogging {
|
||||
parser.parse(args)
|
||||
parser.resultSettings
|
||||
}.onFailure { e ->
|
||||
@@ -214,18 +214,18 @@ suspend fun main(args: Array<String>) {
|
||||
triggerSendForChat(ChatId(it.chat.id.chatId), chatSettings ?: return@onCommand)
|
||||
}
|
||||
onCommand("disable", requireOnlyCommandInMessage = true) {
|
||||
runCatchingSafely {
|
||||
runCatchingLogging {
|
||||
repo.unset(ChatId(it.chat.id.chatId))
|
||||
}
|
||||
runCatchingSafely {
|
||||
runCatchingLogging {
|
||||
delete(it)
|
||||
}
|
||||
}
|
||||
onCommand("take_settings", requireOnlyCommandInMessage = true) {
|
||||
val settings = runCatchingSafely {
|
||||
val settings = runCatchingLogging {
|
||||
repo.get(ChatId(it.chat.id.chatId))
|
||||
}.getOrNull()
|
||||
runCatchingSafely {
|
||||
runCatchingLogging {
|
||||
if (settings == null) {
|
||||
reply(it, "You didn't enable requesting")
|
||||
} else {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:OptIn(ExperimentalSerializationApi::class)
|
||||
|
||||
import dev.inmo.krontab.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -44,6 +46,8 @@ data class ChatSettings(
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalSerializationApi
|
||||
@Suppress("EXTERNAL_SERIALIZER_USELESS")
|
||||
@Serializer(DefaultBoards::class)
|
||||
object BoardSerializer : KSerializer<DefaultBoards> {
|
||||
override val descriptor: SerialDescriptor = String.serializer().descriptor
|
||||
|
||||
@@ -4,8 +4,8 @@ import dev.inmo.kslog.common.e
|
||||
import dev.inmo.kslog.common.logger
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.transactions.transactionManager
|
||||
import org.jetbrains.exposed.v1.jdbc.Database
|
||||
import org.jetbrains.exposed.v1.jdbc.transactions.transactionManager
|
||||
import org.postgresql.Driver
|
||||
import java.sql.Connection
|
||||
|
||||
|
||||
Reference in New Issue
Block a user