mirror of
https://github.com/dalbodeule/chibot-chzzk-bot.git
synced 2025-08-07 12:51:13 +00:00
Compare commits
83 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1d23ac5121 | ||
|
8f8d2f895a | ||
|
47b4b8252f | ||
|
64880318e8 | ||
|
cec07f9859 | ||
|
18ee27e567 | ||
|
34ec0f29ff | ||
|
2b999c5acb | ||
|
c669943f87 | ||
|
efaaf5ae9f | ||
|
c8fca6995c | ||
|
903f1f7f38 | ||
|
e4b6f819ca | ||
|
2c1f42e4af | ||
|
ff90e5fe7f | ||
|
a227dda930 | ||
|
3e09989202 | ||
|
eddca6dbab | ||
|
9c48dd676e | ||
|
779604d21e | ||
|
83791fe59b | ||
|
fe63a4af15 | ||
|
7522ec6f9e | ||
|
c35b3082cc | ||
|
19d3f23cd7 | ||
|
80d777dad5 | ||
|
d2071b323e | ||
|
f2b30c8b00 | ||
|
947e6d4bb3 | ||
|
43b6869100 | ||
|
ba12fd655b | ||
|
b1d69e90ef | ||
|
a9aa5188f9 | ||
|
e9a2e6b918 | ||
|
035a6dc6cd | ||
|
a774418259 | ||
|
e31efc0212 | ||
|
eae675eaf6 | ||
|
be84a73828 | ||
|
fbb0e50379 | ||
|
3f60348ace | ||
|
09bb485a13 | ||
|
c22c70398f | ||
|
8af0c3ac33 | ||
|
557600f812 | ||
|
e85561dd74 | ||
|
1a1b02506f | ||
|
5a3cdbd45a | ||
|
ceb730a933 | ||
|
f795e51845 | ||
|
9edf2d44ee | ||
|
0cd8a274e0 | ||
|
a98758532f | ||
|
22f47737df | ||
|
f5a97348be | ||
|
152752218b | ||
|
618a31c121 | ||
|
d85abcbe43 | ||
|
8675d0bd85 | ||
|
1c52466024 | ||
|
87f8cb0248 | ||
|
ea05474deb | ||
|
3c5ce73734 | ||
|
a65772f575 | ||
|
0481681dd4 | ||
|
d717b297f3 | ||
|
74645ee5da | ||
|
77545c3b74 | ||
|
9a2e14ad21 | ||
|
d9c7636ec0 | ||
|
be4b9ff3ec | ||
|
d4497b5a13 | ||
|
20f6d84040 | ||
|
4da72f194e | ||
|
acfa2b4b02 | ||
|
3e398ba840 | ||
|
54edd46f71 | ||
|
7ad3013d47 | ||
|
94fa1eff61 | ||
|
907b8e8d2a | ||
|
086e7f9392 | ||
|
5cc376f22f | ||
|
639ed5faed |
9
.idea/dataSources.xml
generated
9
.idea/dataSources.xml
generated
@@ -1,14 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
<data-source source="LOCAL" name="@localhost" uuid="90f8ee11-600e-4155-a316-e8062c7c828b">
|
<data-source source="LOCAL" name="@prod" uuid="90f8ee11-600e-4155-a316-e8062c7c828b">
|
||||||
<driver-ref>mysql.8</driver-ref>
|
<driver-ref>mariadb</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
|
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
|
||||||
<jdbc-url>jdbc:mysql://localhost:3306</jdbc-url>
|
<jdbc-url>jdbc:mariadb://localhost:3306</jdbc-url>
|
||||||
<jdbc-additional-properties>
|
<jdbc-additional-properties>
|
||||||
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.resource.type" value="Deployment" />
|
||||||
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||||
</jdbc-additional-properties>
|
</jdbc-additional-properties>
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Use a base image with JDK 21 for the final image
|
||||||
|
FROM openjdk:21-jdk
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy the JAR file from the TeamCity build artifacts
|
||||||
|
COPY build/libs/chzzk_bot-*.jar app.jar
|
||||||
|
|
||||||
|
# Set the entry point
|
||||||
|
ENTRYPOINT ["java", "-jar", "app.jar"]
|
73
README.md
73
README.md
@@ -1,3 +1,72 @@
|
|||||||
# maybe_chzzk_bot_kotlin
|
# nabot_chzzk_bot
|
||||||
|
|
||||||
[discord](https://discord.gg/up8ANZegmy)
|
[](https://discord.gg/up8ANZegmy) [](https://teamcity.mori.space/project/NabotChzzkBot) [](https://hub.docker.com/repository/docker/dalbodeule/chzzkbot/general)
|
||||||
|
|
||||||
|
## Chzzk Chatbot with [JDA5](https://github.com/discord-jda/JDA), [chzzk4j](https://github.com/R2turnTrue/chzzk4j)
|
||||||
|
|
||||||
|
네이버 게임스트리밍 플랫폼 치지직의 챗봇입니다.
|
||||||
|
|
||||||
|
## 지원 기능
|
||||||
|
|
||||||
|
### Placeholders
|
||||||
|
|
||||||
|
- [x] \<name>
|
||||||
|
- [x] \<following>
|
||||||
|
- [x] \<counter:counter_name>
|
||||||
|
- [x] \<personal_counter:counter_name>
|
||||||
|
- [x] \<daily_counter:counter_name>
|
||||||
|
- [x] \<days:yyyy-mm-dd>
|
||||||
|
|
||||||
|
### 관리 명령어 (on Discord)
|
||||||
|
- [x] /register chzzk_id: \[치지직 고유ID]
|
||||||
|
- [x] /alert channel: \[디스코드 Channel ID] content: \[알림 내용]
|
||||||
|
- [x] /add label: \[명령어] content: \[내용]
|
||||||
|
- [ ] /list
|
||||||
|
- [x] /update label: \[명령어] content: \[내용]
|
||||||
|
- [x] /delete label: \[명령어]
|
||||||
|
### 매니저 명령어 (on Discord)
|
||||||
|
- [x] /addmanager user: \[Discord user]
|
||||||
|
- [x] /listmanager
|
||||||
|
- [x] /removemanager user: \[Discord user]
|
||||||
|
### 관리 명령어 (on Chzzk chat)
|
||||||
|
- [x] !명령어추가 \[명령어] \[내용]
|
||||||
|
- [x] !명령어수정 \[명령어] \[내용]
|
||||||
|
- [x] !명령어삭제 \[명령어]
|
||||||
|
|
||||||
|
### Envs
|
||||||
|
- DISCORD_TOKEN
|
||||||
|
- DB_URL
|
||||||
|
- DB_USER
|
||||||
|
- DB_PASS
|
||||||
|
- RUN_AGENT = `false`
|
||||||
|
- NID_AUT
|
||||||
|
- NID_SES
|
||||||
|
|
||||||
|
### 사용 예시
|
||||||
|
- 팔로우
|
||||||
|
- `/add label: !팔로우 content: <name>님은 오늘로 <following>일째 팔로우네요!`
|
||||||
|
- 출첵
|
||||||
|
- `/add label: !출첵 content: <name>님의 <daily_counter:attendance>번째 출석! fail_content: <name>님은 오늘 이미 출석했어요! <daily_counter:attendance>번 했네요?`
|
||||||
|
- `/add label: ? content: <name>님이 <counter:hook>개째 갈고리 수집`
|
||||||
|
- ㄱㅇㅇ
|
||||||
|
- `/add label: ㄱㅇㅇ content: <counter:cute>번째 ㄱㅇㅇ`
|
||||||
|
- `/add label: ㄱㅇㅇ content: 나누 귀여움 +<counter:cute>`
|
||||||
|
- 풉
|
||||||
|
- `/add label: 풉 content: <counter:poop>번째 비웃음?`
|
||||||
|
- `/add label: 풉키풉키 content: <counter:poop>번째 비웃음?`
|
||||||
|
- 바보
|
||||||
|
- `/add label: 바보 content: 나 바보 아니다?`
|
||||||
|
- `/add label: 바보 content: <counter:fool> 번째 바보? 나 바보 아니다?`
|
||||||
|
- 첫방송
|
||||||
|
- `/add label: 첫방송 content: 24년 7월 23일부터 <days:2024-07-23>일 째 방송중!`
|
||||||
|
|
||||||
|
## 사용 기술스택
|
||||||
|
- [Exposed](https://github.com/JetBrains/Exposed)
|
||||||
|
- [Kotlin](https://github.com/JetBrains/kotlin)
|
||||||
|
- [JDA5](https://github.com/discord-jda/JDA)
|
||||||
|
- [chzzk4j](https://github.com/R2turnTrue/chzzk4j)
|
||||||
|
- [HikariCP](https://github.com/brettwooldridge/HikariCP)
|
||||||
|
- [gson](https://github.com/google/gson)
|
||||||
|
- [mariadb](https://mariadb.org/)
|
||||||
|
- [docker](https://www.docker.com/)
|
||||||
|
- [Teamcity](https://www.jetbrains.com/teamcity/)
|
||||||
|
@@ -23,52 +23,29 @@ application {
|
|||||||
mainClass.set("${"${project.group}.${project.name}".lowercase()}.MainKt")
|
mainClass.set("${"${project.group}.${project.name}".lowercase()}.MainKt")
|
||||||
}
|
}
|
||||||
|
|
||||||
graalvmNative {
|
|
||||||
agent {
|
|
||||||
trackReflectionMetadata.set(true)
|
|
||||||
|
|
||||||
metadataCopy {
|
|
||||||
outputDirectories.add("src/main/resources/META-INF/native-image")
|
|
||||||
mergeWithExisting.set(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binaries {
|
|
||||||
binaries.all {
|
|
||||||
resources.autodetect()
|
|
||||||
}
|
|
||||||
named("main") {
|
|
||||||
useFatJar.set(true)
|
|
||||||
sharedLibrary.set(false)
|
|
||||||
buildArgs.add("--initialize-at-build-time=org.hibernate.*")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
metadataRepository {
|
|
||||||
enabled.set(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// https://mvnrepository.com/artifact/net.dv8tion/JDA
|
// https://mvnrepository.com/artifact/net.dv8tion/JDA
|
||||||
implementation("net.dv8tion:JDA:5.0.0-beta.24") {
|
implementation("net.dv8tion:JDA:5.0.1") {
|
||||||
exclude(module = "opus-java")
|
exclude(module = "opus-java")
|
||||||
}
|
}
|
||||||
// https://mvnrepository.com/artifact/io.github.R2turnTrue/chzzk4j
|
// https://mvnrepository.com/artifact/io.github.R2turnTrue/chzzk4j
|
||||||
implementation("io.github.R2turnTrue:chzzk4j:0.0.7")
|
implementation("io.github.R2turnTrue:chzzk4j:0.0.9")
|
||||||
|
|
||||||
implementation("ch.qos.logback:logback-classic:1.4.14")
|
// https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
|
||||||
|
implementation("ch.qos.logback:logback-classic:1.5.6")
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-core
|
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-core
|
||||||
implementation("org.jetbrains.exposed:exposed-core:0.51.1")
|
implementation("org.jetbrains.exposed:exposed-core:0.52.0")
|
||||||
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-dao
|
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-dao
|
||||||
implementation("org.jetbrains.exposed:exposed-dao:0.51.1")
|
implementation("org.jetbrains.exposed:exposed-dao:0.52.0")
|
||||||
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-jdbc
|
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-jdbc
|
||||||
runtimeOnly("org.jetbrains.exposed:exposed-jdbc:0.51.1")
|
implementation("org.jetbrains.exposed:exposed-jdbc:0.52.0")
|
||||||
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-kotlin-datetime
|
// https://mvnrepository.com/artifact/org.jetbrains.exposed/exposed-kotlin-datetime
|
||||||
runtimeOnly("org.jetbrains.exposed:exposed-kotlin-datetime:0.51.1")
|
implementation("org.jetbrains.exposed:exposed-java-time:0.52.0")
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
|
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
|
||||||
implementation("com.zaxxer:HikariCP:5.1.0")
|
implementation("com.zaxxer:HikariCP:5.1.0")
|
||||||
@@ -77,12 +54,14 @@ dependencies {
|
|||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0-RC")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0-RC")
|
||||||
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-reflect
|
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-reflect
|
||||||
implementation("org.jetbrains.kotlin:kotlin-reflect:2.0.0")
|
implementation("org.jetbrains.kotlin:kotlin-reflect:2.0.0")
|
||||||
// https://mvnrepository.com/artifact/org.reflections/reflections
|
|
||||||
implementation("org.reflections:reflections:0.10.2")
|
// https://mvnrepository.com/artifact/com.google.code.gson/gson
|
||||||
|
implementation("com.google.code.gson:gson:2.11.0")
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client
|
// https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client
|
||||||
implementation("org.mariadb.jdbc:mariadb-java-client:3.4.0")
|
implementation("org.mariadb.jdbc:mariadb-java-client:3.4.1")
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/io.github.cdimascio/dotenv-kotlin
|
||||||
implementation("io.github.cdimascio:dotenv-kotlin:6.4.1")
|
implementation("io.github.cdimascio:dotenv-kotlin:6.4.1")
|
||||||
|
|
||||||
kotlin("stdlib")
|
kotlin("stdlib")
|
||||||
@@ -102,3 +81,7 @@ tasks.withType<Jar> {
|
|||||||
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.named<JavaExec>("run") {
|
||||||
|
systemProperty("logback.configurationFile", "logback-debug.xml")
|
||||||
|
}
|
4
docker-build.sh
Executable file
4
docker-build.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
current_time=$(date +"%Y%m%d%H%M")
|
||||||
|
docker build -t dalbodeule/chzzkbot:latest -t dalbodeule/chzzkbot:$current_time --push .
|
@@ -1,6 +1,6 @@
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
group = space.mori
|
group = space.mori
|
||||||
version = 1.0.0
|
version = 1.0.3
|
||||||
|
|
||||||
org.gradle.jvmargs=-Dfile.encoding=UTF-8
|
org.gradle.jvmargs=-Dfile.encoding=UTF-8
|
||||||
org.gradle.console=plain
|
org.gradle.console=plain
|
||||||
|
@@ -2,18 +2,13 @@ package space.mori.chzzk_bot
|
|||||||
|
|
||||||
import com.zaxxer.hikari.HikariConfig
|
import com.zaxxer.hikari.HikariConfig
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
import io.github.cdimascio.dotenv.dotenv
|
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
import org.jetbrains.exposed.sql.SchemaUtils
|
import org.jetbrains.exposed.sql.SchemaUtils
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
import org.slf4j.LoggerFactory
|
import space.mori.chzzk_bot.models.*
|
||||||
import space.mori.chzzk_bot.models.Commands
|
|
||||||
import space.mori.chzzk_bot.models.Users
|
|
||||||
|
|
||||||
object Connector {
|
object Connector {
|
||||||
private val dotenv = dotenv()
|
private val hikariConfig = HikariConfig().apply {
|
||||||
|
|
||||||
val hikariConfig = HikariConfig().apply {
|
|
||||||
jdbcUrl = dotenv["DB_URL"]
|
jdbcUrl = dotenv["DB_URL"]
|
||||||
driverClassName = "org.mariadb.jdbc.Driver"
|
driverClassName = "org.mariadb.jdbc.Driver"
|
||||||
username = dotenv["DB_USER"]
|
username = dotenv["DB_USER"]
|
||||||
@@ -24,12 +19,10 @@ object Connector {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
Database.connect(dataSource)
|
Database.connect(dataSource)
|
||||||
val tables = listOf(Users, Commands)
|
val tables = listOf(Users, Commands, Counters, DailyCounters, PersonalCounters, Managers)
|
||||||
|
|
||||||
transaction {
|
transaction {
|
||||||
tables.forEach { table ->
|
SchemaUtils.createMissingTablesAndColumns(* tables.toTypedArray())
|
||||||
SchemaUtils.createMissingTablesAndColumns(table)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -9,29 +9,34 @@ import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
|||||||
import space.mori.chzzk_bot.discord.Discord
|
import space.mori.chzzk_bot.discord.Discord
|
||||||
import space.mori.chzzk_bot.chzzk.Connector as ChzzkConnector
|
import space.mori.chzzk_bot.chzzk.Connector as ChzzkConnector
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
val dotenv = dotenv()
|
val dotenv = dotenv {
|
||||||
|
ignoreIfMissing = true
|
||||||
|
}
|
||||||
val logger: Logger = LoggerFactory.getLogger("main")
|
val logger: Logger = LoggerFactory.getLogger("main")
|
||||||
|
|
||||||
|
val discord = Discord()
|
||||||
|
|
||||||
|
val connector = Connector
|
||||||
|
val chzzkConnector = ChzzkConnector
|
||||||
|
val chzzkHandler = ChzzkHandler
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val discord = Discord()
|
|
||||||
|
|
||||||
val connector = Connector
|
|
||||||
val chzzkConnector = ChzzkConnector
|
|
||||||
val chzzkHandler = ChzzkHandler
|
|
||||||
|
|
||||||
discord.enable()
|
discord.enable()
|
||||||
chzzkHandler.enable()
|
chzzkHandler.enable()
|
||||||
|
chzzkHandler.runStreamInfo()
|
||||||
|
|
||||||
if(dotenv.get("RUN_AGENT", "false").toBoolean()) {
|
if(dotenv.get("RUN_AGENT", "false").toBoolean()) {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
delay(TimeUnit.MINUTES.toMillis(1))
|
delay(TimeUnit.MINUTES.toMillis(1))
|
||||||
discord.disable()
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(Thread {
|
Runtime.getRuntime().addShutdownHook(Thread {
|
||||||
logger.info("Shutting down...")
|
logger.info("Shutting down...")
|
||||||
|
chzzkHandler.stopStreamInfo()
|
||||||
chzzkHandler.disable()
|
chzzkHandler.disable()
|
||||||
discord.disable()
|
discord.disable()
|
||||||
connector.dataSource.close()
|
connector.dataSource.close()
|
||||||
|
148
src/main/kotlin/space/mori/chzzk_bot/chzzk/ChzzkApis.kt
Normal file
148
src/main/kotlin/space/mori/chzzk_bot/chzzk/ChzzkApis.kt
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package space.mori.chzzk_bot.chzzk
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
data class IData<T>(
|
||||||
|
val code: Int = 200,
|
||||||
|
val message: String? = null,
|
||||||
|
val content: T
|
||||||
|
)
|
||||||
|
|
||||||
|
// Follows
|
||||||
|
data class IFollowContent(
|
||||||
|
val userIdHash: String = "",
|
||||||
|
val nickname: String = "",
|
||||||
|
val profileImageUrl: String = "",
|
||||||
|
val userRoleCode: String = "",
|
||||||
|
val badge: Badge? = null,
|
||||||
|
val title: Title? = null,
|
||||||
|
val verifiedMark: Boolean = false,
|
||||||
|
val activityBadges: List<Badge> = emptyList(),
|
||||||
|
val streamingProperty: StreamingProperty = StreamingProperty()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Badge(
|
||||||
|
val badgeNo: Int?,
|
||||||
|
val badgeId: String?,
|
||||||
|
val imageUrl: String?,
|
||||||
|
val title: String?,
|
||||||
|
val description: String?,
|
||||||
|
val activated: Boolean?
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Title(
|
||||||
|
val name: String = "",
|
||||||
|
val color: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
data class StreamingProperty(
|
||||||
|
val following: Following? = Following(),
|
||||||
|
val nicknameColor: NicknameColor = NicknameColor()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Following(
|
||||||
|
val followDate: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class NicknameColor(
|
||||||
|
val colorCode: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
// Stream info
|
||||||
|
data class IStreamInfo(
|
||||||
|
val liveId: Int = 0,
|
||||||
|
val liveTitle: String = "",
|
||||||
|
val status: String = "",
|
||||||
|
val liveImageUrl: String = "",
|
||||||
|
val defaultThumbnailImageUrl: String? = null,
|
||||||
|
val concurrentUserCount: Int = 0,
|
||||||
|
val accumulateCount: Int = 0,
|
||||||
|
val openDate: String = "",
|
||||||
|
val closeDate: String = "",
|
||||||
|
val adult: Boolean = false,
|
||||||
|
val clipActive: Boolean = false,
|
||||||
|
val tags: List<String> = emptyList(),
|
||||||
|
val chatChannelId: String = "",
|
||||||
|
val categoryType: String = "",
|
||||||
|
val liveCategory: String = "",
|
||||||
|
val liveCategoryValue: String = "",
|
||||||
|
val chatActive: Boolean = true,
|
||||||
|
val chatAvailableGroup: String = "",
|
||||||
|
val paidPromotion: Boolean = false,
|
||||||
|
val chatAvailableCondition: String = "",
|
||||||
|
val minFollowerMinute: Int = 0,
|
||||||
|
val livePlaybackJson: String = "",
|
||||||
|
val p2pQuality: List<Any> = emptyList(),
|
||||||
|
val channel: Channel = Channel(),
|
||||||
|
val livePollingStatusJson: String = "",
|
||||||
|
val userAdultStatus: String? = null,
|
||||||
|
val chatDonationRankingExposure: Boolean = true,
|
||||||
|
val adParameter: AdParameter = AdParameter()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Channel(
|
||||||
|
val channelId: String = "",
|
||||||
|
val channelName: String = "",
|
||||||
|
val channelImageUrl: String = "",
|
||||||
|
val verifiedMark: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AdParameter(
|
||||||
|
val tag: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
// OkHttpClient에 Interceptor 추가
|
||||||
|
val client = OkHttpClient.Builder()
|
||||||
|
.addNetworkInterceptor { chain ->
|
||||||
|
chain.proceed(
|
||||||
|
chain.request()
|
||||||
|
.newBuilder()
|
||||||
|
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
val gson = Gson()
|
||||||
|
|
||||||
|
fun getFollowDate(chatID: String, userId: String) : IData<IFollowContent> {
|
||||||
|
val url = "https://comm-api.game.naver.com/nng_main/v1/chats/$chatID/users/$userId/profile-card?chatType=STREAMING"
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
client.newCall(request).execute().use { response ->
|
||||||
|
try {
|
||||||
|
if(!response.isSuccessful) throw IOException("Unexpected code ${response.code}")
|
||||||
|
val body = response.body?.string()
|
||||||
|
val follow = gson.fromJson(body, object: TypeToken<IData<IFollowContent>>() {})
|
||||||
|
|
||||||
|
return follow
|
||||||
|
} catch(e: Exception) {
|
||||||
|
println(e.stackTrace)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getStreamInfo(userId: String) : IData<IStreamInfo> {
|
||||||
|
val url = "https://api.chzzk.naver.com/service/v2/channels/${userId}/live-detail"
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
client.newCall(request).execute().use { response ->
|
||||||
|
try {
|
||||||
|
if(!response.isSuccessful) throw IOException("Unexpected code ${response.code}")
|
||||||
|
val body = response.body?.string()
|
||||||
|
val follow = gson.fromJson(body, object: TypeToken<IData<IStreamInfo>>() {})
|
||||||
|
|
||||||
|
return follow
|
||||||
|
} catch(e: Exception) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,26 +1,33 @@
|
|||||||
package space.mori.chzzk_bot.chzzk
|
package space.mori.chzzk_bot.chzzk
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder
|
||||||
|
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.mori.chzzk_bot.chzzk.Connector.chzzk
|
import space.mori.chzzk_bot.chzzk.Connector.chzzk
|
||||||
|
import space.mori.chzzk_bot.discord
|
||||||
|
import space.mori.chzzk_bot.models.User
|
||||||
import space.mori.chzzk_bot.services.UserService
|
import space.mori.chzzk_bot.services.UserService
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChatEventListener
|
import xyz.r2turntrue.chzzk4j.chat.ChatEventListener
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
|
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
|
||||||
import xyz.r2turntrue.chzzk4j.types.channel.ChzzkChannel
|
import xyz.r2turntrue.chzzk4j.types.channel.ChzzkChannel
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
import java.net.SocketTimeoutException
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
object ChzzkHandler {
|
object ChzzkHandler {
|
||||||
private val handlers = mutableListOf<UserHandler>()
|
private val handlers = mutableListOf<UserHandler>()
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
@Volatile private var running: Boolean = false
|
||||||
|
|
||||||
internal fun addUser(chzzkChannel: ChzzkChannel) {
|
internal fun addUser(chzzkChannel: ChzzkChannel, user: User) {
|
||||||
handlers.add(UserHandler(chzzkChannel, logger))
|
handlers.add(UserHandler(chzzkChannel, logger, user))
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun enable() {
|
internal fun enable() {
|
||||||
UserService.getAllUsers().map {
|
UserService.getAllUsers().map {
|
||||||
chzzk.getChannel(it.token)?.let { token -> addUser(token)}
|
chzzk.getChannel(it.token)?.let { token -> addUser(token, it)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,15 +38,57 @@ object ChzzkHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun reloadCommand(chzzkChannel: ChzzkChannel) {
|
internal fun reloadCommand(chzzkChannel: ChzzkChannel) {
|
||||||
val handler = handlers.firstOrNull { it.channel == chzzkChannel }
|
val handler = handlers.firstOrNull { it.channel.channelId == chzzkChannel.channelId }
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
handler.reloadCommand()
|
handler.reloadCommand()
|
||||||
else
|
else
|
||||||
throw RuntimeException("${chzzkChannel.channelName} doesn't have handler")
|
throw RuntimeException("${chzzkChannel.channelName} doesn't have handler")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun reloadUser(chzzkChannel: ChzzkChannel, user: User) {
|
||||||
|
val handler = handlers.firstOrNull { it.channel.channelId == chzzkChannel.channelId }
|
||||||
|
if (handler != null)
|
||||||
|
handler.reloadUser(user)
|
||||||
|
else
|
||||||
|
throw RuntimeException("${chzzkChannel.channelName} doesn't have handler")
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun runStreamInfo() {
|
||||||
|
running = true
|
||||||
|
val thread = Thread({
|
||||||
|
while(running) {
|
||||||
|
handlers.forEach {
|
||||||
|
if (!running) return@forEach
|
||||||
|
try {
|
||||||
|
val streamInfo = getStreamInfo(it.channel.channelId)
|
||||||
|
if (streamInfo.content.status == "OPEN" && !it.isActive) it.isActive(true, streamInfo)
|
||||||
|
if (streamInfo.content.status == "CLOSE" && it.isActive) it.isActive(false, streamInfo)
|
||||||
|
} catch(e: SocketTimeoutException) {
|
||||||
|
logger.info("Timeout: ${it.channel.channelName} / ${e.stackTraceToString()}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.info("Exception: ${it.channel.channelName} / ${e.stackTraceToString()}")
|
||||||
|
} finally {
|
||||||
|
Thread.sleep(5000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Thread.sleep(60000)
|
||||||
|
}
|
||||||
|
}, "Chzzk-StreamInfo")
|
||||||
|
|
||||||
|
thread.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun stopStreamInfo() {
|
||||||
|
running = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserHandler(val channel: ChzzkChannel, private val logger: Logger) {
|
class UserHandler(
|
||||||
|
val channel: ChzzkChannel,
|
||||||
|
private val logger: Logger,
|
||||||
|
private var user: User,
|
||||||
|
private var _isActive: Boolean = false
|
||||||
|
) {
|
||||||
private lateinit var messageHandler: MessageHandler
|
private lateinit var messageHandler: MessageHandler
|
||||||
|
|
||||||
private var listener: ChzzkChat = chzzk.chat(channel.channelId)
|
private var listener: ChzzkChat = chzzk.chat(channel.channelId)
|
||||||
@@ -56,7 +105,8 @@ class UserHandler(val channel: ChzzkChannel, private val logger: Logger) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onChat(msg: ChatMessage) {
|
override fun onChat(msg: ChatMessage) {
|
||||||
messageHandler.handle(msg)
|
if(!_isActive) return
|
||||||
|
messageHandler.handle(msg, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConnectionClosed(code: Int, reason: String?, remote: Boolean, tryingToReconnect: Boolean) {
|
override fun onConnectionClosed(code: Int, reason: String?, remote: Boolean, tryingToReconnect: Boolean) {
|
||||||
@@ -66,16 +116,54 @@ class UserHandler(val channel: ChzzkChannel, private val logger: Logger) {
|
|||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
init {
|
|
||||||
logger.info("ChzzkChat connecting... ${channel.channelName} - ${channel.channelId}")
|
|
||||||
listener.connectBlocking()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun disable() {
|
internal fun disable() {
|
||||||
listener.closeBlocking()
|
listener.closeAsync()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun reloadCommand() {
|
internal fun reloadCommand() {
|
||||||
messageHandler.reloadCommand()
|
messageHandler.reloadCommand()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun reloadUser(user: User) {
|
||||||
|
this.user = user
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val isActive: Boolean
|
||||||
|
get() = _isActive
|
||||||
|
|
||||||
|
internal fun isActive(value: Boolean, status: IData<IStreamInfo>) {
|
||||||
|
_isActive = value
|
||||||
|
if(value) {
|
||||||
|
logger.info("${user.username} is live.")
|
||||||
|
|
||||||
|
logger.info("ChzzkChat connecting... ${channel.channelName} - ${channel.channelId}")
|
||||||
|
listener.connectAsync()
|
||||||
|
|
||||||
|
if(user.liveAlertMessage != "" && user.liveAlertGuild != null && user.liveAlertChannel != null) {
|
||||||
|
val channel = discord.getChannel(user.liveAlertGuild!!, user.liveAlertChannel!!) ?: throw RuntimeException("${user.liveAlertChannel} is not valid.")
|
||||||
|
|
||||||
|
val embed = EmbedBuilder()
|
||||||
|
embed.setTitle(status.content.liveTitle, "https://chzzk.naver.com/live/${user.token}")
|
||||||
|
embed.setDescription("${user.username} 님이 방송을 시작했습니다.")
|
||||||
|
embed.setUrl(status.content.channel.channelImageUrl)
|
||||||
|
embed.setTimestamp(Instant.now())
|
||||||
|
embed.setAuthor(user.username, "https://chzzk.naver.com/live/${user.token}", status.content.channel.channelImageUrl)
|
||||||
|
embed.addField("카테고리", status.content.liveCategoryValue, true)
|
||||||
|
embed.addField("태그", status.content.tags.joinToString(", "), true)
|
||||||
|
embed.setImage(status.content.liveImageUrl.replace("{type}", "1080"))
|
||||||
|
|
||||||
|
channel.sendMessage(
|
||||||
|
MessageCreateBuilder()
|
||||||
|
.setContent(user.liveAlertMessage)
|
||||||
|
.setEmbeds(embed.build())
|
||||||
|
.build()
|
||||||
|
).queue()
|
||||||
|
|
||||||
|
listener.sendChat("${user.username} 님의 방송이 감지되었습니다.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.info("${user.username} is offline.")
|
||||||
|
listener.closeAsync()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,13 +1,12 @@
|
|||||||
package space.mori.chzzk_bot.chzzk
|
package space.mori.chzzk_bot.chzzk
|
||||||
|
|
||||||
import io.github.cdimascio.dotenv.dotenv
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import xyz.r2turntrue.chzzk4j.Chzzk
|
import xyz.r2turntrue.chzzk4j.Chzzk
|
||||||
import xyz.r2turntrue.chzzk4j.ChzzkBuilder
|
import xyz.r2turntrue.chzzk4j.ChzzkBuilder
|
||||||
import xyz.r2turntrue.chzzk4j.types.channel.ChzzkChannel
|
import xyz.r2turntrue.chzzk4j.types.channel.ChzzkChannel
|
||||||
|
import space.mori.chzzk_bot.dotenv
|
||||||
|
|
||||||
object Connector {
|
object Connector {
|
||||||
private val dotenv = dotenv()
|
|
||||||
val chzzk: Chzzk = ChzzkBuilder()
|
val chzzk: Chzzk = ChzzkBuilder()
|
||||||
.withAuthorization(dotenv["NID_AUT"], dotenv["NID_SES"])
|
.withAuthorization(dotenv["NID_AUT"], dotenv["NID_SES"])
|
||||||
.build()
|
.build()
|
||||||
|
@@ -1,18 +1,31 @@
|
|||||||
package space.mori.chzzk_bot.chzzk
|
package space.mori.chzzk_bot.chzzk
|
||||||
|
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
|
import space.mori.chzzk_bot.models.User
|
||||||
import space.mori.chzzk_bot.services.CommandService
|
import space.mori.chzzk_bot.services.CommandService
|
||||||
|
import space.mori.chzzk_bot.services.CounterService
|
||||||
import space.mori.chzzk_bot.services.UserService
|
import space.mori.chzzk_bot.services.UserService
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
import xyz.r2turntrue.chzzk4j.chat.ChatMessage
|
||||||
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
|
import xyz.r2turntrue.chzzk4j.chat.ChzzkChat
|
||||||
import xyz.r2turntrue.chzzk4j.types.channel.ChzzkChannel
|
import xyz.r2turntrue.chzzk4j.types.channel.ChzzkChannel
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
|
||||||
|
|
||||||
class MessageHandler(
|
class MessageHandler(
|
||||||
private val channel: ChzzkChannel,
|
private val channel: ChzzkChannel,
|
||||||
private val logger: Logger,
|
private val logger: Logger,
|
||||||
private val listener: ChzzkChat
|
private val listener: ChzzkChat
|
||||||
) {
|
) {
|
||||||
private val commands = mutableMapOf<String, () -> Unit>()
|
private val commands = mutableMapOf<String, (msg: ChatMessage, user: User) -> Unit>()
|
||||||
|
|
||||||
|
private val counterPattern = Regex("<counter:([^>]+)>")
|
||||||
|
private val personalCounterPattern = Regex("<counter_personal:([^>]+)>")
|
||||||
|
private val dailyCounterPattern = Regex("<daily_counter:([^>]+)>")
|
||||||
|
private val namePattern = Regex("<name>")
|
||||||
|
private val followPattern = Regex("<following>")
|
||||||
|
private val daysPattern = """<days:(\d{4})-(\d{2})-(\d{2})>""".toRegex()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
reloadCommand()
|
reloadCommand()
|
||||||
@@ -22,18 +35,159 @@ class MessageHandler(
|
|||||||
val user = UserService.getUser(channel.channelId)
|
val user = UserService.getUser(channel.channelId)
|
||||||
?: throw RuntimeException("User not found. it's bug? ${channel.channelName} - ${channel.channelId}")
|
?: throw RuntimeException("User not found. it's bug? ${channel.channelName} - ${channel.channelId}")
|
||||||
val commands = CommandService.getCommands(user)
|
val commands = CommandService.getCommands(user)
|
||||||
|
val manageCommands = mapOf("!명령어추가" to this::manageAddCommand, "!명령어삭제" to this::manageRemoveCommand, "!명령어수정" to this::manageUpdateCommand)
|
||||||
|
|
||||||
|
manageCommands.forEach { (commandName, command) ->
|
||||||
|
this.commands[commandName] = command
|
||||||
|
}
|
||||||
|
|
||||||
commands.map {
|
commands.map {
|
||||||
this.commands.put(it.command.lowercase()) {
|
this.commands.put(it.command.lowercase()) { msg, user ->
|
||||||
logger.debug("${channel.channelName} - ${it.command} - ${it.content}")
|
logger.debug("${channel.channelName} - ${it.command} - ${it.content}/${it.failContent}")
|
||||||
listener.sendChat(it.content)
|
|
||||||
|
val result = replaceCounters(Pair(it.content, it.failContent), user, msg, listener, msg.profile?.nickname ?: "")
|
||||||
|
listener.sendChat(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun handle(msg: ChatMessage) {
|
private fun manageAddCommand(msg: ChatMessage, user: User) {
|
||||||
|
if (msg.profile?.userRoleCode == "common_user") {
|
||||||
|
listener.sendChat("매니저만 명령어를 추가할 수 있습니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val parts = msg.content.split(" ", limit = 3)
|
||||||
|
if (parts.size < 3) {
|
||||||
|
listener.sendChat("명령어 추가 형식은 '!명령어추가 명령어 내용'입니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (commands.containsKey(parts[1])) {
|
||||||
|
listener.sendChat("${parts[1]} 명령어는 이미 있는 명령어입니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val command = parts[1]
|
||||||
|
val content = parts[2]
|
||||||
|
CommandService.saveCommand(user, command, content, "")
|
||||||
|
listener.sendChat("명령어 '$command' 추가되었습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun manageUpdateCommand(msg: ChatMessage, user: User) {
|
||||||
|
if (msg.profile?.userRoleCode == "common_user") {
|
||||||
|
listener.sendChat("매니저만 명령어를 추가할 수 있습니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val parts = msg.content.split(" ", limit = 3)
|
||||||
|
if (parts.size < 3) {
|
||||||
|
listener.sendChat("명령어 수정 형식은 '!명령어수정 명령어 내용'입니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!commands.containsKey(parts[1])) {
|
||||||
|
listener.sendChat("${parts[1]} 명령어는 없는 명령어입니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val command = parts[1]
|
||||||
|
val content = parts[2]
|
||||||
|
CommandService.updateCommand(user, command, content, "")
|
||||||
|
listener.sendChat("명령어 '$command' 수정되었습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun manageRemoveCommand(msg: ChatMessage, user: User) {
|
||||||
|
if (msg.profile?.userRoleCode == "common_user") {
|
||||||
|
listener.sendChat("매니저만 명령어를 삭제할 수 있습니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val parts = msg.content.split(" ", limit = 2)
|
||||||
|
if (parts.size < 2) {
|
||||||
|
listener.sendChat("명령어 삭제 형식은 '!명령어삭제 명령어'입니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val command = parts[1]
|
||||||
|
CommandService.removeCommand(user, command)
|
||||||
|
listener.sendChat("명령어 '$command' 삭제되었습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun handle(msg: ChatMessage, user: User) {
|
||||||
val commandKey = msg.content.split(' ')[0]
|
val commandKey = msg.content.split(' ')[0]
|
||||||
|
|
||||||
commands[commandKey.lowercase()]?.let { it() }
|
commands[commandKey.lowercase()]?.let { it(msg, user) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun replaceCounters(chat: Pair<String, String>, user: User, msg: ChatMessage, listener: ChzzkChat, userName: String): String {
|
||||||
|
var result = chat.first
|
||||||
|
var isFail = false
|
||||||
|
|
||||||
|
// Replace dailyCounterPattern
|
||||||
|
result = dailyCounterPattern.replace(result) { matchResult ->
|
||||||
|
val name = matchResult.groupValues[1]
|
||||||
|
val dailyCounter = CounterService.getDailyCounterValue(name, msg.userId, user)
|
||||||
|
|
||||||
|
if (dailyCounter.second) {
|
||||||
|
CounterService.updateDailyCounterValue(name, msg.userId, 1, user).first.toString()
|
||||||
|
} else {
|
||||||
|
isFail = true
|
||||||
|
dailyCounter.first.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle fail case
|
||||||
|
if (isFail && chat.second.isNotEmpty()) {
|
||||||
|
result = chat.second
|
||||||
|
result = dailyCounterPattern.replace(result) { matchResult ->
|
||||||
|
val name = matchResult.groupValues[1]
|
||||||
|
val dailyCounter = CounterService.getDailyCounterValue(name, msg.userId, user)
|
||||||
|
dailyCounter.first.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace followPattern
|
||||||
|
result = followPattern.replace(result) { matchResult ->
|
||||||
|
try {
|
||||||
|
val followingDate = getFollowDate(listener.chatId, msg.userId)
|
||||||
|
.content.streamingProperty.following?.followDate
|
||||||
|
|
||||||
|
val period = followingDate?.let {
|
||||||
|
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||||
|
val pastDate = LocalDateTime.parse(it, formatter)
|
||||||
|
val today = LocalDateTime.now()
|
||||||
|
ChronoUnit.DAYS.between(pastDate, today)
|
||||||
|
} ?: 0
|
||||||
|
|
||||||
|
period.toString()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error(e.message)
|
||||||
|
"0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace daysPattern
|
||||||
|
result = daysPattern.replace(result) { matchResult ->
|
||||||
|
val (year, month, day) = matchResult.destructured
|
||||||
|
val pastDate = LocalDateTime.of(year.toInt(), month.toInt(), day.toInt(), 0, 0, 0)
|
||||||
|
val today = LocalDateTime.now()
|
||||||
|
|
||||||
|
val daysBetween = ChronoUnit.DAYS.between(pastDate, today)
|
||||||
|
daysBetween.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace counterPattern
|
||||||
|
result = counterPattern.replace(result) { matchResult ->
|
||||||
|
val name = matchResult.groupValues[1]
|
||||||
|
CounterService.updateCounterValue(name, 1, user).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace personalCounterPattern
|
||||||
|
result = personalCounterPattern.replace(result) { matchResult ->
|
||||||
|
val name = matchResult.groupValues[1]
|
||||||
|
CounterService.updatePersonalCounterValue(name, msg.userId, 1, user).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace namePattern
|
||||||
|
result = namePattern.replace(result, userName)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -3,33 +3,9 @@ package space.mori.chzzk_bot.discord
|
|||||||
import net.dv8tion.jda.api.JDA
|
import net.dv8tion.jda.api.JDA
|
||||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData
|
import net.dv8tion.jda.api.interactions.commands.build.CommandData
|
||||||
import org.reflections.Reflections
|
|
||||||
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
annotation class Command
|
|
||||||
|
|
||||||
interface CommandInterface {
|
interface CommandInterface {
|
||||||
val name: String
|
val name: String
|
||||||
fun run(event: SlashCommandInteractionEvent, bot: JDA): Unit
|
fun run(event: SlashCommandInteractionEvent, bot: JDA): Unit
|
||||||
val command: CommandData
|
val command: CommandData
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCommands(): List<CommandInterface> {
|
|
||||||
val commandList = mutableListOf<CommandInterface>()
|
|
||||||
|
|
||||||
val packageName = "space.mori.chzzk_bot.discord.commands"
|
|
||||||
val reflections = Reflections(packageName)
|
|
||||||
val annotatedClasses = reflections.getTypesAnnotatedWith(Command::class.java)
|
|
||||||
|
|
||||||
for(clazz in annotatedClasses) {
|
|
||||||
val obj = clazz.kotlin.objectInstance
|
|
||||||
if(obj is CommandInterface) {
|
|
||||||
commandList.add(obj)
|
|
||||||
} else {
|
|
||||||
throw IllegalStateException("${clazz.name} is not a CommandInterface")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return commandList.toList()
|
|
||||||
}
|
|
@@ -4,21 +4,61 @@ import net.dv8tion.jda.api.JDA
|
|||||||
import net.dv8tion.jda.api.JDABuilder
|
import net.dv8tion.jda.api.JDABuilder
|
||||||
import net.dv8tion.jda.api.entities.Activity
|
import net.dv8tion.jda.api.entities.Activity
|
||||||
import net.dv8tion.jda.api.entities.Guild
|
import net.dv8tion.jda.api.entities.Guild
|
||||||
|
import net.dv8tion.jda.api.events.guild.GuildJoinEvent
|
||||||
|
import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent
|
||||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
||||||
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import space.mori.chzzk_bot.dotenv
|
import space.mori.chzzk_bot.dotenv
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import space.mori.chzzk_bot.discord.commands.*
|
||||||
|
import space.mori.chzzk_bot.services.ManagerService
|
||||||
|
|
||||||
class Discord: ListenerAdapter() {
|
class Discord: ListenerAdapter() {
|
||||||
private lateinit var bot: JDA
|
private lateinit var bot: JDA
|
||||||
private var guild: Guild? = null
|
private var guild: Guild? = null
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
|
||||||
private val commands = getCommands()
|
private val commands = listOf(
|
||||||
|
AddCommand,
|
||||||
|
AlertCommand,
|
||||||
|
PingCommand,
|
||||||
|
RegisterCommand,
|
||||||
|
RemoveCommand,
|
||||||
|
UpdateCommand,
|
||||||
|
AddManagerCommand,
|
||||||
|
ListManagerCommand,
|
||||||
|
RemoveManagerCommand,
|
||||||
|
)
|
||||||
|
|
||||||
override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) {
|
override fun onSlashCommandInteraction(event: SlashCommandInteractionEvent) {
|
||||||
event.deferReply().queue()
|
event.deferReply().queue()
|
||||||
commands.find { it.name == event.name }?.run(event, bot)
|
val handler = commands.find { it.name == event.name }
|
||||||
|
logger.debug("Handler: ${handler?.name ?: "undefined"} command")
|
||||||
|
handler?.run(event, bot)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onGuildMemberRemove(event: GuildMemberRemoveEvent) {
|
||||||
|
event.member?.let { ManagerService.deleteManager(event.guild.idLong, it.idLong) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onGuildJoin(event: GuildJoinEvent) {
|
||||||
|
commandUpdate(event.guild)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun commandUpdate(guild: Guild) {
|
||||||
|
guild.updateCommands().addCommands(* commands.map { it.command}.toTypedArray())
|
||||||
|
.onSuccess {
|
||||||
|
logger.info("Command update on guild success!")
|
||||||
|
}
|
||||||
|
.queue()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun commandUpdate(bot: JDA) {
|
||||||
|
bot.updateCommands().addCommands(* commands.map { it.command}.toTypedArray())
|
||||||
|
.onSuccess {
|
||||||
|
logger.info("Command update bot boot success!")
|
||||||
|
}
|
||||||
|
.queue()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun enable() {
|
internal fun enable() {
|
||||||
@@ -31,15 +71,9 @@ class Discord: ListenerAdapter() {
|
|||||||
|
|
||||||
guild = bot.getGuildById(dotenv["GUILD_ID"])
|
guild = bot.getGuildById(dotenv["GUILD_ID"])
|
||||||
|
|
||||||
bot.updateCommands()
|
commandUpdate(bot)
|
||||||
.addCommands(* commands.map { it.command }.toTypedArray())
|
bot.guilds.forEach {
|
||||||
.onSuccess { logger.info("Command update success!") }
|
commandUpdate(it)
|
||||||
.queue()
|
|
||||||
|
|
||||||
|
|
||||||
if (guild == null) {
|
|
||||||
logger.info("No guild found!")
|
|
||||||
this.disable()
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.info("Could not enable Discord!")
|
logger.info("Could not enable Discord!")
|
||||||
@@ -57,4 +91,7 @@ class Discord: ListenerAdapter() {
|
|||||||
logger.debug(e.stackTraceToString())
|
logger.debug(e.stackTraceToString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
internal fun getChannel(guildId: Long, channelId: Long) =
|
||||||
|
bot.getGuildById(guildId)?.getTextChannelById(channelId)
|
||||||
|
}
|
||||||
|
@@ -8,41 +8,55 @@ import net.dv8tion.jda.api.interactions.commands.build.OptionData
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
||||||
import space.mori.chzzk_bot.chzzk.Connector
|
import space.mori.chzzk_bot.chzzk.Connector
|
||||||
import space.mori.chzzk_bot.discord.Command
|
|
||||||
import space.mori.chzzk_bot.discord.CommandInterface
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
import space.mori.chzzk_bot.services.CommandService
|
import space.mori.chzzk_bot.services.CommandService
|
||||||
|
import space.mori.chzzk_bot.services.ManagerService
|
||||||
import space.mori.chzzk_bot.services.UserService
|
import space.mori.chzzk_bot.services.UserService
|
||||||
|
|
||||||
@Command
|
|
||||||
object AddCommand : CommandInterface {
|
object AddCommand : CommandInterface {
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
override val name: String = "add"
|
override val name: String = "add"
|
||||||
override val command = Commands.slash(name, "명령어를 추가합니다.")
|
override val command = Commands.slash(name, "명령어를 추가합니다.")
|
||||||
.addOptions(OptionData(OptionType.STRING, "label", "작동할 명령어를 입력하세요.", true))
|
.addOptions(OptionData(OptionType.STRING, "label", "작동할 명령어를 입력하세요.", true))
|
||||||
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요.", true))
|
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요.", true))
|
||||||
|
.addOptions(OptionData(OptionType.STRING, "fail_content", "카운터 업데이트 실패시 표시될 텍스트를 입력하세요.", false))
|
||||||
|
|
||||||
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
||||||
val label = event.getOption("label")?.asString
|
val label = event.getOption("label")?.asString
|
||||||
val content = event.getOption("content")?.asString
|
val content = event.getOption("content")?.asString
|
||||||
|
val failContent = event.getOption("fail_content")?.asString
|
||||||
|
|
||||||
if(label == null || content == null) {
|
if(label == null || content == null) {
|
||||||
event.hook.sendMessage("명령어와 텍스트는 필수 입력입니다.").queue()
|
event.hook.sendMessage("명령어와 텍스트는 필수 입력입니다.").queue()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val user = UserService.getUser(event.user.idLong)
|
var user = UserService.getUser(event.user.idLong)
|
||||||
if(user == null) {
|
val manager = event.guild?.idLong?.let { ManagerService.getUser(it, event.user.idLong) }
|
||||||
event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue()
|
if(user == null && manager == null) {
|
||||||
|
event.hook.sendMessage("당신은 이 명령어를 사용할 수 없습니다.").queue()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (manager != null) {
|
||||||
|
user = manager.user
|
||||||
|
ManagerService.updateManager(user, event.user.idLong, event.user.effectiveName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val commands = CommandService.getCommands(user!!)
|
||||||
|
if (commands.any { it.command == label }) {
|
||||||
|
event.hook.sendMessage("$label 명령어는 이미 있습니다! 업데이트 명령어를 써주세요.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val chzzkChannel = Connector.getChannel(user.token)
|
val chzzkChannel = Connector.getChannel(user.token)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommandService.saveCommand(user, label, content)
|
CommandService.saveCommand(user, label, content, failContent ?: "")
|
||||||
try {
|
try {
|
||||||
ChzzkHandler.reloadCommand(chzzkChannel!!)
|
ChzzkHandler.reloadCommand(chzzkChannel!!)
|
||||||
} catch (_: Exception) {}
|
} catch (_: Exception) {}
|
||||||
event.hook.sendMessage("등록이 완료되었습니다. $label = $content").queue()
|
event.hook.sendMessage("등록이 완료되었습니다. $label = $content/$failContent").queue()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
logger.debug(e.stackTraceToString())
|
logger.debug(e.stackTraceToString())
|
||||||
|
@@ -0,0 +1,47 @@
|
|||||||
|
package space.mori.chzzk_bot.discord.commands
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.JDA
|
||||||
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionType
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.Commands
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
|
import space.mori.chzzk_bot.services.ManagerService
|
||||||
|
import space.mori.chzzk_bot.services.UserService
|
||||||
|
|
||||||
|
object AddManagerCommand : CommandInterface {
|
||||||
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
override val name: String = "addmanager"
|
||||||
|
override val command = Commands.slash(name, "매니저를 추가합니다.")
|
||||||
|
.addOptions(OptionData(OptionType.USER, "user", "추가할 유저를 선택하세요.", true))
|
||||||
|
|
||||||
|
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
||||||
|
val manager = event.getOption("user")?.asUser
|
||||||
|
|
||||||
|
if(manager == null) {
|
||||||
|
event.hook.sendMessage("유저는 필수사항입니다.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(manager.idLong == event.user.idLong) {
|
||||||
|
event.hook.sendMessage("자신은 매니저로 설정할 수 없습니다.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val user = UserService.getUser(event.user.idLong)
|
||||||
|
if(user == null) {
|
||||||
|
event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ManagerService.saveManager(user, manager.idLong, manager.effectiveName)
|
||||||
|
if(user.liveAlertGuild == null)
|
||||||
|
UserService.updateLiveAlert(user.id.value, event.guild!!.idLong, event.channelIdLong, "")
|
||||||
|
event.hook.sendMessage("등록이 완료되었습니다. ${manager.effectiveName}").queue()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
|
logger.debug(e.stackTraceToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,51 @@
|
|||||||
|
package space.mori.chzzk_bot.discord.commands
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.JDA
|
||||||
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionType
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.Commands
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
||||||
|
import space.mori.chzzk_bot.chzzk.Connector
|
||||||
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
|
import space.mori.chzzk_bot.services.ManagerService
|
||||||
|
import space.mori.chzzk_bot.services.UserService
|
||||||
|
|
||||||
|
object AlertCommand : CommandInterface {
|
||||||
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
override val name: String = "alert"
|
||||||
|
override val command = Commands.slash(name, "명령어를 추가합니다.")
|
||||||
|
.addOptions(OptionData(OptionType.CHANNEL, "channel", "알림을 보낼 채널을 입력하세요."))
|
||||||
|
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요. 비워두면 알람이 취소됩니다."))
|
||||||
|
|
||||||
|
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
||||||
|
val channel = event.getOption("channel")?.asChannel
|
||||||
|
val content = event.getOption("content")?.asString
|
||||||
|
|
||||||
|
var user = UserService.getUser(event.user.idLong)
|
||||||
|
val manager = event.guild?.idLong?.let { ManagerService.getUser(it, event.user.idLong) }
|
||||||
|
if(user == null && manager == null) {
|
||||||
|
event.hook.sendMessage("당신은 이 명령어를 사용할 수 없습니다.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager != null) {
|
||||||
|
user = manager.user
|
||||||
|
ManagerService.updateManager(user, event.user.idLong, event.user.effectiveName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val chzzkChannel = Connector.getChannel(user!!.token)
|
||||||
|
|
||||||
|
try {
|
||||||
|
val newUser = UserService.updateLiveAlert(user.id.value, channel?.guild?.idLong ?: 0L, channel?.idLong ?: 0L, content ?: "")
|
||||||
|
try {
|
||||||
|
ChzzkHandler.reloadUser(chzzkChannel!!, newUser)
|
||||||
|
} catch (_: Exception) {}
|
||||||
|
event.hook.sendMessage("업데이트가 완료되었습니다.").queue()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
|
logger.debug(e.stackTraceToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
package space.mori.chzzk_bot.discord.commands
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder
|
||||||
|
import net.dv8tion.jda.api.JDA
|
||||||
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.Commands
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
|
import space.mori.chzzk_bot.services.ManagerService
|
||||||
|
import space.mori.chzzk_bot.services.UserService
|
||||||
|
|
||||||
|
object ListManagerCommand : CommandInterface {
|
||||||
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
override val name: String = "listmanager"
|
||||||
|
override val command = Commands.slash(name, "매니저 목록을 확인합니다.")
|
||||||
|
|
||||||
|
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
||||||
|
try {
|
||||||
|
val managers = event.guild?.idLong?.let { ManagerService.getAllUsers(it) }
|
||||||
|
|
||||||
|
if(managers == null) {
|
||||||
|
event.channel.sendMessage("여기에서는 사용할 수 없습니다.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val user = UserService.getUserWithGuildId(event.guild!!.idLong)
|
||||||
|
|
||||||
|
val embed = EmbedBuilder()
|
||||||
|
embed.setTitle("${user!!.username} 매니저 목록")
|
||||||
|
embed.setDescription("매니저 목록입니다.")
|
||||||
|
|
||||||
|
var idx = 1
|
||||||
|
|
||||||
|
managers.forEach {
|
||||||
|
embed.addField("${idx++}", it.lastUserName ?: it.managerId.toString(), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
event.channel.sendMessageEmbeds(embed.build()).queue()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
|
logger.debug(e.stackTraceToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -4,11 +4,9 @@ import net.dv8tion.jda.api.JDA
|
|||||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.Commands
|
import net.dv8tion.jda.api.interactions.commands.build.Commands
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.mori.chzzk_bot.discord.Command
|
|
||||||
import space.mori.chzzk_bot.discord.CommandInterface
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
|
|
||||||
@Command()
|
object PingCommand: CommandInterface {
|
||||||
object Ping: CommandInterface {
|
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
override val name = "ping"
|
override val name = "ping"
|
||||||
override val command = Commands.slash(name, "봇이 살아있을까요?")
|
override val command = Commands.slash(name, "봇이 살아있을까요?")
|
@@ -8,12 +8,10 @@ import net.dv8tion.jda.api.interactions.commands.build.OptionData
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
||||||
import space.mori.chzzk_bot.chzzk.Connector
|
import space.mori.chzzk_bot.chzzk.Connector
|
||||||
import space.mori.chzzk_bot.discord.Command
|
|
||||||
import space.mori.chzzk_bot.discord.CommandInterface
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
import space.mori.chzzk_bot.services.UserService
|
import space.mori.chzzk_bot.services.UserService
|
||||||
|
|
||||||
@Command
|
object RegisterCommand: CommandInterface {
|
||||||
object Register: CommandInterface {
|
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
override val name = "register"
|
override val name = "register"
|
||||||
override val command = Commands.slash(name, "치지직 계정을 등록합니다.")
|
override val command = Commands.slash(name, "치지직 계정을 등록합니다.")
|
||||||
@@ -40,9 +38,9 @@ object Register: CommandInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
UserService.saveUser(chzzkChannel.channelName, chzzkChannel.channelId, event.user.idLong)
|
val user = UserService.saveUser(chzzkChannel.channelName, chzzkChannel.channelId, event.user.idLong)
|
||||||
ChzzkHandler.addUser(chzzkChannel)
|
|
||||||
event.hook.sendMessage("등록이 완료되었습니다. `${chzzkChannel.channelId}` - `${chzzkChannel.channelName}`")
|
event.hook.sendMessage("등록이 완료되었습니다. `${chzzkChannel.channelId}` - `${chzzkChannel.channelName}`")
|
||||||
|
ChzzkHandler.addUser(chzzkChannel, user)
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
logger.debug(e.stackTraceToString())
|
logger.debug(e.stackTraceToString())
|
@@ -8,12 +8,11 @@ import net.dv8tion.jda.api.interactions.commands.build.OptionData
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
||||||
import space.mori.chzzk_bot.chzzk.Connector
|
import space.mori.chzzk_bot.chzzk.Connector
|
||||||
import space.mori.chzzk_bot.discord.Command
|
|
||||||
import space.mori.chzzk_bot.discord.CommandInterface
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
import space.mori.chzzk_bot.services.CommandService
|
import space.mori.chzzk_bot.services.CommandService
|
||||||
|
import space.mori.chzzk_bot.services.ManagerService
|
||||||
import space.mori.chzzk_bot.services.UserService
|
import space.mori.chzzk_bot.services.UserService
|
||||||
|
|
||||||
@Command
|
|
||||||
object RemoveCommand : CommandInterface {
|
object RemoveCommand : CommandInterface {
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
override val name: String = "remove"
|
override val name: String = "remove"
|
||||||
@@ -28,12 +27,19 @@ object RemoveCommand : CommandInterface {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val user = UserService.getUser(event.user.idLong)
|
var user = UserService.getUser(event.user.idLong)
|
||||||
if(user == null) {
|
val manager = event.guild?.idLong?.let { ManagerService.getUser(it, event.user.idLong) }
|
||||||
event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue()
|
if(user == null && manager == null) {
|
||||||
|
event.hook.sendMessage("당신은 이 명령어를 사용할 수 없습니다.").queue()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val chzzkChannel = Connector.getChannel(user.token)
|
|
||||||
|
if (manager != null) {
|
||||||
|
user = manager.user
|
||||||
|
ManagerService.updateManager(user, event.user.idLong, event.user.effectiveName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val chzzkChannel = Connector.getChannel(user!!.token)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommandService.removeCommand(user, label)
|
CommandService.removeCommand(user, label)
|
||||||
|
@@ -0,0 +1,49 @@
|
|||||||
|
package space.mori.chzzk_bot.discord.commands
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.JDA
|
||||||
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionType
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.Commands
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
|
import space.mori.chzzk_bot.services.ManagerService
|
||||||
|
import space.mori.chzzk_bot.services.UserService
|
||||||
|
|
||||||
|
object RemoveManagerCommand : CommandInterface {
|
||||||
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
override val name: String = "removemanager"
|
||||||
|
override val command = Commands.slash(name, "매니저를 삭제합니다.")
|
||||||
|
.addOptions(OptionData(OptionType.USER, "user", "삭제할 유저를 선택하세요.", true))
|
||||||
|
|
||||||
|
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
||||||
|
val manager = event.getOption("user")?.asUser
|
||||||
|
|
||||||
|
if(manager == null) {
|
||||||
|
event.hook.sendMessage("유저는 필수사항입니다.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(manager.idLong == event.user.idLong) {
|
||||||
|
event.hook.sendMessage("자신은 매니저로 설정할 수 없습니다.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val user = UserService.getUser(event.user.idLong)
|
||||||
|
if(user == null) {
|
||||||
|
event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ManagerService.getUser(user.liveAlertGuild ?: 0L, manager.idLong) == null) {
|
||||||
|
event.hook.sendMessage("${manager.name}은 매니저가 아닙니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ManagerService.deleteManager(user, manager.idLong)
|
||||||
|
event.hook.sendMessage("삭제가 완료되었습니다. ${manager.effectiveName}").queue()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
|
logger.debug(e.stackTraceToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -8,41 +8,46 @@ import net.dv8tion.jda.api.interactions.commands.build.OptionData
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
import space.mori.chzzk_bot.chzzk.ChzzkHandler
|
||||||
import space.mori.chzzk_bot.chzzk.Connector
|
import space.mori.chzzk_bot.chzzk.Connector
|
||||||
import space.mori.chzzk_bot.discord.Command
|
|
||||||
import space.mori.chzzk_bot.discord.CommandInterface
|
import space.mori.chzzk_bot.discord.CommandInterface
|
||||||
import space.mori.chzzk_bot.services.CommandService
|
import space.mori.chzzk_bot.services.CommandService
|
||||||
|
import space.mori.chzzk_bot.services.ManagerService
|
||||||
import space.mori.chzzk_bot.services.UserService
|
import space.mori.chzzk_bot.services.UserService
|
||||||
import xyz.r2turntrue.chzzk4j.types.channel.ChzzkChannel
|
|
||||||
|
|
||||||
@Command
|
|
||||||
object UpdateCommand : CommandInterface {
|
object UpdateCommand : CommandInterface {
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
override val name: String = "update"
|
override val name: String = "update"
|
||||||
override val command = Commands.slash(name, "명령어를 수정합니다.")
|
override val command = Commands.slash(name, "명령어를 수정합니다.")
|
||||||
.addOptions(OptionData(OptionType.STRING, "label", "수정할 명령어를 입력하세요.", true))
|
.addOptions(OptionData(OptionType.STRING, "label", "수정할 명령어를 입력하세요.", true))
|
||||||
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요.", true))
|
.addOptions(OptionData(OptionType.STRING, "content", "표시될 텍스트를 입력하세요.", true))
|
||||||
|
.addOptions(OptionData(OptionType.STRING, "fail_content", "카운터 업데이트 실패시 표시될 텍스트를 입력하세요.", false))
|
||||||
|
|
||||||
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
override fun run(event: SlashCommandInteractionEvent, bot: JDA) {
|
||||||
val label = event.getOption("label")?.asString
|
val label = event.getOption("label")?.asString
|
||||||
val content = event.getOption("content")?.asString
|
val content = event.getOption("content")?.asString
|
||||||
|
val failContent = event.getOption("fail_content")?.asString
|
||||||
|
|
||||||
if(label == null || content == null) {
|
if(label == null || content == null) {
|
||||||
event.hook.sendMessage("명령어와 텍스트는 필수 입력입니다.").queue()
|
event.hook.sendMessage("명령어와 텍스트는 필수 입력입니다.").queue()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val user = UserService.getUser(event.user.idLong)
|
var user = UserService.getUser(event.user.idLong)
|
||||||
if(user == null) {
|
val manager = event.guild?.idLong?.let { ManagerService.getUser(it, event.user.idLong) }
|
||||||
event.hook.sendMessage("치지직 계정을 찾을 수 없습니다.").queue()
|
if(user == null && manager == null) {
|
||||||
|
event.hook.sendMessage("당신은 이 명령어를 사용할 수 없습니다.").queue()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val chzzkChannel = Connector.getChannel(user.token)
|
|
||||||
|
if (manager != null) {
|
||||||
|
user = manager.user
|
||||||
|
ManagerService.updateManager(user, event.user.idLong, event.user.effectiveName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val chzzkChannel = Connector.getChannel(user!!.token)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommandService.updateCommand(user, label, content)
|
CommandService.updateCommand(user, label, content, failContent ?: "")
|
||||||
try {
|
chzzkChannel?.let { ChzzkHandler.reloadCommand(it) }
|
||||||
ChzzkHandler.reloadCommand(chzzkChannel!!)
|
|
||||||
} catch (_: Exception) {}
|
|
||||||
event.hook.sendMessage("등록이 완료되었습니다. $label = $content").queue()
|
event.hook.sendMessage("등록이 완료되었습니다. $label = $content").queue()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
event.hook.sendMessage("에러가 발생했습니다.").queue()
|
||||||
|
@@ -10,6 +10,7 @@ object Commands: IntIdTable("commands") {
|
|||||||
val user = reference("user", Users, onDelete = ReferenceOption.CASCADE)
|
val user = reference("user", Users, onDelete = ReferenceOption.CASCADE)
|
||||||
val command = varchar("command", 255)
|
val command = varchar("command", 255)
|
||||||
val content = text("content")
|
val content = text("content")
|
||||||
|
val failContent = text("fail_content")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Command(id: EntityID<Int>) : IntEntity(id) {
|
class Command(id: EntityID<Int>) : IntEntity(id) {
|
||||||
@@ -18,4 +19,5 @@ class Command(id: EntityID<Int>) : IntEntity(id) {
|
|||||||
var user by User referencedOn Commands.user
|
var user by User referencedOn Commands.user
|
||||||
var command by Commands.command
|
var command by Commands.command
|
||||||
var content by Commands.content
|
var content by Commands.content
|
||||||
|
var failContent by Commands.failContent
|
||||||
}
|
}
|
20
src/main/kotlin/space/mori/chzzk_bot/models/Counter.kt
Normal file
20
src/main/kotlin/space/mori/chzzk_bot/models/Counter.kt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package space.mori.chzzk_bot.models
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.dao.IntEntityClass
|
||||||
|
import org.jetbrains.exposed.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||||
|
|
||||||
|
object Counters: IntIdTable("counters") {
|
||||||
|
val name = varchar("name", 255)
|
||||||
|
val value = integer("value")
|
||||||
|
val user = reference("streamer", Users)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Counter(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<Counter>(Counters)
|
||||||
|
|
||||||
|
var name by Counters.name
|
||||||
|
var value by Counters.value
|
||||||
|
var user by User referencedOn Counters.user
|
||||||
|
}
|
25
src/main/kotlin/space/mori/chzzk_bot/models/DailyCounters.kt
Normal file
25
src/main/kotlin/space/mori/chzzk_bot/models/DailyCounters.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package space.mori.chzzk_bot.models
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.dao.IntEntityClass
|
||||||
|
import org.jetbrains.exposed.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||||
|
import org.jetbrains.exposed.sql.javatime.date
|
||||||
|
|
||||||
|
object DailyCounters: IntIdTable("daily_counters") {
|
||||||
|
val name = varchar("name", 255)
|
||||||
|
val userId = varchar("user_id", 64)
|
||||||
|
val value = integer("value")
|
||||||
|
val updatedAt = date("updated_at")
|
||||||
|
val user = reference("streamer", Users)
|
||||||
|
}
|
||||||
|
|
||||||
|
class DailyCounter(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<DailyCounter>(DailyCounters)
|
||||||
|
|
||||||
|
var name by DailyCounters.name
|
||||||
|
var userId by DailyCounters.userId
|
||||||
|
var value by DailyCounters.value
|
||||||
|
var updatedAt by DailyCounters.updatedAt
|
||||||
|
var user by User referencedOn DailyCounters.user
|
||||||
|
}
|
22
src/main/kotlin/space/mori/chzzk_bot/models/Manager.kt
Normal file
22
src/main/kotlin/space/mori/chzzk_bot/models/Manager.kt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package space.mori.chzzk_bot.models
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.dao.IntEntityClass
|
||||||
|
import org.jetbrains.exposed.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||||
|
|
||||||
|
object Managers: IntIdTable("manager") {
|
||||||
|
val user = reference("user", Users)
|
||||||
|
val managerId = long("manager_id")
|
||||||
|
val discordGuildId = long("discord_guild_id")
|
||||||
|
var lastUserName = varchar("last_user_name", 255).nullable()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Manager(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<Manager>(Managers)
|
||||||
|
|
||||||
|
var user by User referencedOn Managers.user
|
||||||
|
var managerId by Managers.managerId
|
||||||
|
var discordGuildId by Managers.discordGuildId
|
||||||
|
var lastUserName by Managers.lastUserName
|
||||||
|
}
|
@@ -0,0 +1,22 @@
|
|||||||
|
package space.mori.chzzk_bot.models
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.dao.IntEntityClass
|
||||||
|
import org.jetbrains.exposed.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||||
|
|
||||||
|
object PersonalCounters: IntIdTable("personal_counters") {
|
||||||
|
val name = varchar("name", 255)
|
||||||
|
val userId = varchar("user_id", 64)
|
||||||
|
val value = integer("value")
|
||||||
|
val user = reference("streamer", Users)
|
||||||
|
}
|
||||||
|
|
||||||
|
class PersonalCounter(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<PersonalCounter>(PersonalCounters)
|
||||||
|
|
||||||
|
var name by PersonalCounters.name
|
||||||
|
var userId by PersonalCounters.userId
|
||||||
|
var value by PersonalCounters.value
|
||||||
|
var user by User referencedOn PersonalCounters.user
|
||||||
|
}
|
@@ -10,6 +10,9 @@ object Users: IntIdTable("users") {
|
|||||||
val username = varchar("username", 255)
|
val username = varchar("username", 255)
|
||||||
val token = varchar("token", 64)
|
val token = varchar("token", 64)
|
||||||
val discord = long("discord")
|
val discord = long("discord")
|
||||||
|
val liveAlertGuild = long("live_alert_guild").nullable()
|
||||||
|
val liveAlertChannel = long("live_alert_channel").nullable()
|
||||||
|
val liveAlertMessage = text("live_alert_message").nullable()
|
||||||
}
|
}
|
||||||
|
|
||||||
class User(id: EntityID<Int>) : IntEntity(id) {
|
class User(id: EntityID<Int>) : IntEntity(id) {
|
||||||
@@ -18,4 +21,7 @@ class User(id: EntityID<Int>) : IntEntity(id) {
|
|||||||
var username by Users.username
|
var username by Users.username
|
||||||
var token by Users.token
|
var token by Users.token
|
||||||
var discord by Users.discord
|
var discord by Users.discord
|
||||||
|
var liveAlertGuild by Users.liveAlertGuild
|
||||||
|
var liveAlertChannel by Users.liveAlertChannel
|
||||||
|
var liveAlertMessage by Users.liveAlertMessage
|
||||||
}
|
}
|
@@ -9,12 +9,13 @@ import space.mori.chzzk_bot.models.Commands
|
|||||||
import space.mori.chzzk_bot.models.User
|
import space.mori.chzzk_bot.models.User
|
||||||
|
|
||||||
object CommandService {
|
object CommandService {
|
||||||
fun saveCommand(user: User, command: String, content: String): Command {
|
fun saveCommand(user: User, command: String, content: String, failContent: String): Command {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction Command.new {
|
return@transaction Command.new {
|
||||||
this.user = user
|
this.user = user
|
||||||
this.command = command
|
this.command = command
|
||||||
this.content = content
|
this.content = content
|
||||||
|
this.failContent = failContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,31 +27,32 @@ object CommandService {
|
|||||||
commandRow ?: throw RuntimeException("Command not found! $command")
|
commandRow ?: throw RuntimeException("Command not found! $command")
|
||||||
commandRow.delete()
|
commandRow.delete()
|
||||||
|
|
||||||
return@transaction commandRow
|
commandRow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateCommand(user: User, command: String, content: String): Command {
|
fun updateCommand(user: User, command: String, content: String, failContent: String): Command {
|
||||||
return transaction {
|
return transaction {
|
||||||
val updated = Commands.update({Commands.user eq user.id and(Commands.command eq command)}) {
|
val updated = Commands.update({Commands.user eq user.id and(Commands.command eq command)}) {
|
||||||
it[Commands.content] = content
|
it[Commands.content] = content
|
||||||
|
it[Commands.failContent] = failContent
|
||||||
}
|
}
|
||||||
|
|
||||||
if(updated == 0) throw RuntimeException("Command not found! $command")
|
if(updated == 0) throw RuntimeException("Command not found! $command")
|
||||||
|
|
||||||
return@transaction Command.find(Commands.user eq user.id and(Commands.command eq command)).first()
|
Command.find(Commands.user eq user.id and(Commands.command eq command)).first()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCommand(id: Int): Command? {
|
fun getCommand(id: Int): Command? {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction Command.findById(id)
|
Command.findById(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCommands(user: User): List<Command> {
|
fun getCommands(user: User): List<Command> {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction Command.find(Commands.user eq user.id)
|
Command.find(Commands.user eq user.id)
|
||||||
.toList()
|
.toList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
104
src/main/kotlin/space/mori/chzzk_bot/services/CounterService.kt
Normal file
104
src/main/kotlin/space/mori/chzzk_bot/services/CounterService.kt
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package space.mori.chzzk_bot.services
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import space.mori.chzzk_bot.models.*
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
object CounterService {
|
||||||
|
fun getCounterValue(name: String, user: User): Int {
|
||||||
|
return transaction {
|
||||||
|
Counter.find {
|
||||||
|
(Counters.name eq name) and (Counters.user eq user.id)
|
||||||
|
}.singleOrNull()?.value ?: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateCounterValue(name: String, increment: Int, user: User): Int {
|
||||||
|
return transaction {
|
||||||
|
val counter = Counter.find {
|
||||||
|
(Counters.name eq name) and (Counters.user eq user.id) }.singleOrNull()
|
||||||
|
return@transaction if (counter != null) {
|
||||||
|
counter.value += increment
|
||||||
|
counter.value
|
||||||
|
} else {
|
||||||
|
val newCounter = Counter.new {
|
||||||
|
this.name = name
|
||||||
|
this.value = increment
|
||||||
|
this.user = user
|
||||||
|
}
|
||||||
|
newCounter.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPersonalCounterValue(name: String, userId: String, user: User): Int {
|
||||||
|
return transaction {
|
||||||
|
PersonalCounter.find {
|
||||||
|
(PersonalCounters.name eq name) and (PersonalCounters.userId eq userId) and (PersonalCounters.user eq user.id)
|
||||||
|
}.singleOrNull()?.value ?: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updatePersonalCounterValue(name: String, userId: String, increment: Int, user: User): Int {
|
||||||
|
return transaction {
|
||||||
|
val counter = PersonalCounter.find {
|
||||||
|
(PersonalCounters.name eq name) and (PersonalCounters.userId eq userId) and (PersonalCounters.user eq user.id)
|
||||||
|
}.singleOrNull()
|
||||||
|
|
||||||
|
return@transaction if (counter != null) {
|
||||||
|
counter.value += increment
|
||||||
|
counter.value
|
||||||
|
} else {
|
||||||
|
val newCounter = PersonalCounter.new {
|
||||||
|
this.name = name
|
||||||
|
this.value = increment
|
||||||
|
this.userId = userId
|
||||||
|
this.user = user
|
||||||
|
}
|
||||||
|
newCounter.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDailyCounterValue(name: String, userId: String, user: User): Pair<Int, Boolean> {
|
||||||
|
val today = LocalDate.now()
|
||||||
|
|
||||||
|
return transaction {
|
||||||
|
val counter = DailyCounter.find {
|
||||||
|
(DailyCounters.name eq name) and (DailyCounters.userId eq userId) and (DailyCounters.user eq user.id)
|
||||||
|
}.singleOrNull()
|
||||||
|
|
||||||
|
Pair(counter?.value ?: 0, counter?.updatedAt != today)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateDailyCounterValue(name: String, userId: String, increment: Int, user: User): Pair<Int, Boolean> {
|
||||||
|
val today = LocalDate.now()
|
||||||
|
|
||||||
|
return transaction {
|
||||||
|
val counter = DailyCounter.find {
|
||||||
|
(DailyCounters.name eq name) and (DailyCounters.userId eq userId) and (DailyCounters.user eq user.id)
|
||||||
|
}.singleOrNull()
|
||||||
|
|
||||||
|
if(counter == null) {
|
||||||
|
val newCounter = DailyCounter.new {
|
||||||
|
this.name = name
|
||||||
|
this.value = increment
|
||||||
|
this.userId = userId
|
||||||
|
this.updatedAt = today
|
||||||
|
this.user = user
|
||||||
|
}
|
||||||
|
return@transaction Pair(newCounter.value, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return@transaction if(counter.updatedAt == today)
|
||||||
|
Pair(counter.value, false)
|
||||||
|
else {
|
||||||
|
counter.value += increment
|
||||||
|
counter.updatedAt = today
|
||||||
|
Pair(counter.value, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,70 @@
|
|||||||
|
package space.mori.chzzk_bot.services
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import space.mori.chzzk_bot.models.Manager
|
||||||
|
import space.mori.chzzk_bot.models.Managers
|
||||||
|
import space.mori.chzzk_bot.models.User
|
||||||
|
|
||||||
|
object ManagerService {
|
||||||
|
fun saveManager(user: User, discordId: Long, name: String): Manager {
|
||||||
|
if (user.liveAlertGuild == null)
|
||||||
|
throw RuntimeException("${user.username} has no liveAlertGuild")
|
||||||
|
|
||||||
|
return transaction {
|
||||||
|
Manager.new {
|
||||||
|
this.user = user
|
||||||
|
this.discordGuildId = user.liveAlertGuild!!
|
||||||
|
this.managerId = discordId
|
||||||
|
this.lastUserName = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateManager(user: User, discordId: Long, name: String): Manager {
|
||||||
|
if (user.liveAlertGuild == null)
|
||||||
|
throw RuntimeException("${user.username} has no liveAlertGuild")
|
||||||
|
|
||||||
|
val manager = getUser(user.liveAlertGuild!!, discordId)
|
||||||
|
|
||||||
|
if (manager == null)
|
||||||
|
throw RuntimeException("$name isn't manager.")
|
||||||
|
manager.lastUserName = name
|
||||||
|
|
||||||
|
return manager
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUser(guildId: Long, discordId: Long): Manager? {
|
||||||
|
return transaction {
|
||||||
|
val manager = Manager.find(
|
||||||
|
(Managers.discordGuildId eq guildId) and (Managers.managerId eq discordId)
|
||||||
|
)
|
||||||
|
|
||||||
|
manager.firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllUsers(guildId: Long): List<Manager> {
|
||||||
|
return transaction {
|
||||||
|
Manager.find(Managers.discordGuildId eq guildId).toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteManager(user: User, discordId: Long): Manager {
|
||||||
|
if (user.liveAlertGuild == null)
|
||||||
|
throw RuntimeException("${user.username} has no liveAlertGuild")
|
||||||
|
return deleteManager(user.liveAlertGuild!!, discordId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteManager(guildId: Long, discordId: Long): Manager {
|
||||||
|
return transaction {
|
||||||
|
val managerRow = Manager.find((Managers.discordGuildId eq guildId) and (Managers.managerId eq discordId)).firstOrNull()
|
||||||
|
|
||||||
|
managerRow ?: throw RuntimeException("Manager not found! $discordId")
|
||||||
|
managerRow.delete()
|
||||||
|
|
||||||
|
managerRow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,13 +2,14 @@ package space.mori.chzzk_bot.services
|
|||||||
|
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.sql.update
|
||||||
import space.mori.chzzk_bot.models.User
|
import space.mori.chzzk_bot.models.User
|
||||||
import space.mori.chzzk_bot.models.Users
|
import space.mori.chzzk_bot.models.Users
|
||||||
|
|
||||||
object UserService {
|
object UserService {
|
||||||
fun saveUser(username: String, token: String, discordID: Long): User {
|
fun saveUser(username: String, token: String, discordID: Long): User {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction User.new {
|
User.new {
|
||||||
this.username = username
|
this.username = username
|
||||||
this.token = token
|
this.token = token
|
||||||
this.discord = discordID
|
this.discord = discordID
|
||||||
@@ -18,7 +19,7 @@ object UserService {
|
|||||||
|
|
||||||
fun getUser(id: Int): User? {
|
fun getUser(id: Int): User? {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction User.findById(id)
|
User.findById(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ object UserService {
|
|||||||
return transaction {
|
return transaction {
|
||||||
val users = User.find(Users.discord eq discordID)
|
val users = User.find(Users.discord eq discordID)
|
||||||
|
|
||||||
return@transaction users.firstOrNull()
|
users.firstOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,13 +35,36 @@ object UserService {
|
|||||||
return transaction {
|
return transaction {
|
||||||
val users = User.find(Users.token eq chzzkID)
|
val users = User.find(Users.token eq chzzkID)
|
||||||
|
|
||||||
return@transaction users.firstOrNull()
|
users.firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUserWithGuildId(discordGuildId: Long): User? {
|
||||||
|
return transaction {
|
||||||
|
val users = User.find(Users.liveAlertGuild eq discordGuildId)
|
||||||
|
|
||||||
|
users.firstOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllUsers(): List<User> {
|
fun getAllUsers(): List<User> {
|
||||||
return transaction {
|
return transaction {
|
||||||
return@transaction User.all().toList()
|
User.all().toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateLiveAlert(id: Int, guildId: Long, channelId: Long, alertMessage: String?): User {
|
||||||
|
return transaction {
|
||||||
|
val updated = Users.update({ Users.id eq id }) {
|
||||||
|
it[liveAlertGuild] = guildId
|
||||||
|
it[liveAlertChannel] = channelId
|
||||||
|
it[liveAlertMessage] = alertMessage ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if(updated == 0) throw RuntimeException("User not found! $id")
|
||||||
|
val users = User.find { Users.id eq id }
|
||||||
|
|
||||||
|
return@transaction users.first()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,18 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"name":"java.lang.Boolean",
|
|
||||||
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.String",
|
|
||||||
"methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.System",
|
|
||||||
"methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"space.mori.chzzk_bot.MainKt",
|
|
||||||
"methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }]
|
|
||||||
}
|
|
||||||
]
|
|
@@ -1,7 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"type":"agent-extracted",
|
|
||||||
"classes":[
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
@@ -1,5 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"interfaces":["java.sql.Connection"]
|
|
||||||
}
|
|
||||||
]
|
|
@@ -1,467 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"name":"[B"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lcom.fasterxml.jackson.databind.AbstractTypeResolver;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lcom.zaxxer.hikari.util.ConcurrentBag$IConcurrentBagEntry;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Ljava.lang.String;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Ljava.sql.Statement;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lnet.dv8tion.jda.api.entities.Guild;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lnet.dv8tion.jda.api.entities.Member;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lnet.dv8tion.jda.api.entities.Role;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lnet.dv8tion.jda.api.entities.ScheduledEvent;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lnet.dv8tion.jda.api.entities.User;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lnet.dv8tion.jda.api.entities.emoji.RichCustomEmoji;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lnet.dv8tion.jda.api.entities.sticker.GuildSticker;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lnet.dv8tion.jda.api.managers.AudioManager;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"[Lsun.security.pkcs.SignerInfo;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"android.os.Build$VERSION"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"apple.security.AppleProvider",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"ch.qos.logback.classic.BasicConfigurator",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"ch.qos.logback.classic.joran.SerializedModelConfigurator",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"ch.qos.logback.classic.util.DefaultJoranConfigurator",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.AESCipher$General",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.ARCFOURCipher",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.DESCipher",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.DESedeCipher",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.DHParameters",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.HmacCore$HmacSHA384",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.sun.crypto.provider.TlsMasterSecretGenerator",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.zaxxer.hikari.HikariConfig",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllPublicMethods":true,
|
|
||||||
"methods":[{"name":"getAllowPoolSuspension","parameterTypes":[] }, {"name":"getAutoCommit","parameterTypes":[] }, {"name":"getCatalog","parameterTypes":[] }, {"name":"getConnectionInitSql","parameterTypes":[] }, {"name":"getConnectionTestQuery","parameterTypes":[] }, {"name":"getConnectionTimeout","parameterTypes":[] }, {"name":"getDataSource","parameterTypes":[] }, {"name":"getDataSourceClassName","parameterTypes":[] }, {"name":"getDataSourceJNDI","parameterTypes":[] }, {"name":"getDataSourceProperties","parameterTypes":[] }, {"name":"getDriverClassName","parameterTypes":[] }, {"name":"getExceptionOverrideClassName","parameterTypes":[] }, {"name":"getHealthCheckProperties","parameterTypes":[] }, {"name":"getHealthCheckRegistry","parameterTypes":[] }, {"name":"getIdleTimeout","parameterTypes":[] }, {"name":"getInitializationFailTimeout","parameterTypes":[] }, {"name":"getIsolateInternalQueries","parameterTypes":[] }, {"name":"getJdbcUrl","parameterTypes":[] }, {"name":"getKeepaliveTime","parameterTypes":[] }, {"name":"getLeakDetectionThreshold","parameterTypes":[] }, {"name":"getMaxLifetime","parameterTypes":[] }, {"name":"getMaximumPoolSize","parameterTypes":[] }, {"name":"getMetricRegistry","parameterTypes":[] }, {"name":"getMetricsTrackerFactory","parameterTypes":[] }, {"name":"getMinimumIdle","parameterTypes":[] }, {"name":"getPassword","parameterTypes":[] }, {"name":"getPoolName","parameterTypes":[] }, {"name":"getReadOnly","parameterTypes":[] }, {"name":"getRegisterMbeans","parameterTypes":[] }, {"name":"getScheduledExecutor","parameterTypes":[] }, {"name":"getSchema","parameterTypes":[] }, {"name":"getThreadFactory","parameterTypes":[] }, {"name":"getTransactionIsolation","parameterTypes":[] }, {"name":"getUsername","parameterTypes":[] }, {"name":"getValidationTimeout","parameterTypes":[] }, {"name":"isAllowPoolSuspension","parameterTypes":[] }, {"name":"isAutoCommit","parameterTypes":[] }, {"name":"isIsolateInternalQueries","parameterTypes":[] }, {"name":"isReadOnly","parameterTypes":[] }, {"name":"isRegisterMbeans","parameterTypes":[] }, {"name":"setAllowPoolSuspension","parameterTypes":["boolean"] }, {"name":"setAutoCommit","parameterTypes":["boolean"] }, {"name":"setCatalog","parameterTypes":["java.lang.String"] }, {"name":"setClass","parameterTypes":["java.lang.Class"] }, {"name":"setConnectionInitSql","parameterTypes":["java.lang.String"] }, {"name":"setConnectionTestQuery","parameterTypes":["java.lang.String"] }, {"name":"setConnectionTimeout","parameterTypes":["long"] }, {"name":"setDataSource","parameterTypes":["javax.sql.DataSource"] }, {"name":"setDataSourceClassName","parameterTypes":["java.lang.String"] }, {"name":"setDataSourceJNDI","parameterTypes":["java.lang.String"] }, {"name":"setDataSourceProperties","parameterTypes":["java.util.Properties"] }, {"name":"setDriverClassName","parameterTypes":["java.lang.String"] }, {"name":"setExceptionOverrideClassName","parameterTypes":["java.lang.String"] }, {"name":"setHealthCheckProperties","parameterTypes":["java.util.Properties"] }, {"name":"setHealthCheckRegistry","parameterTypes":["java.lang.Object"] }, {"name":"setIdleTimeout","parameterTypes":["long"] }, {"name":"setInitializationFailTimeout","parameterTypes":["long"] }, {"name":"setIsolateInternalQueries","parameterTypes":["boolean"] }, {"name":"setJdbcUrl","parameterTypes":["java.lang.String"] }, {"name":"setKeepaliveTime","parameterTypes":["long"] }, {"name":"setLeakDetectionThreshold","parameterTypes":["long"] }, {"name":"setMaxLifetime","parameterTypes":["long"] }, {"name":"setMaximumPoolSize","parameterTypes":["int"] }, {"name":"setMetricRegistry","parameterTypes":["java.lang.Object"] }, {"name":"setMetricsTrackerFactory","parameterTypes":["com.zaxxer.hikari.metrics.MetricsTrackerFactory"] }, {"name":"setMinimumIdle","parameterTypes":["int"] }, {"name":"setPassword","parameterTypes":["java.lang.String"] }, {"name":"setPoolName","parameterTypes":["java.lang.String"] }, {"name":"setReadOnly","parameterTypes":["boolean"] }, {"name":"setRegisterMbeans","parameterTypes":["boolean"] }, {"name":"setScheduledExecutor","parameterTypes":["java.util.concurrent.ScheduledExecutorService"] }, {"name":"setSchema","parameterTypes":["java.lang.String"] }, {"name":"setThreadFactory","parameterTypes":["java.util.concurrent.ThreadFactory"] }, {"name":"setTransactionIsolation","parameterTypes":["java.lang.String"] }, {"name":"setUsername","parameterTypes":["java.lang.String"] }, {"name":"setValidationTimeout","parameterTypes":["long"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.zaxxer.hikari.pool.PoolBase",
|
|
||||||
"fields":[{"name":"catalog"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"com.zaxxer.hikari.pool.PoolEntry",
|
|
||||||
"fields":[{"name":"state"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.io.FilePermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.ClassValue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.Module"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.RuntimePermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.StringBuilder"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.Thread",
|
|
||||||
"fields":[{"name":"threadLocalRandomProbe"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.lang.invoke.CallSite"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.net.NetPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.net.SocketPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.net.URLPermission",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.nio.Buffer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.AlgorithmParametersSpi"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.AllPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.KeyStoreSpi"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.SecureRandomParameters"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.SecurityPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.interfaces.ECPrivateKey"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.interfaces.ECPublicKey"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.interfaces.RSAPrivateKey"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.security.interfaces.RSAPublicKey"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.sql.Date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.Date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.List",
|
|
||||||
"methods":[{"name":"copyOf","parameterTypes":["java.util.Collection"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.Optional",
|
|
||||||
"methods":[{"name":"isEmpty","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.PropertyPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.concurrent.ForkJoinTask",
|
|
||||||
"fields":[{"name":"aux"}, {"name":"status"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.concurrent.atomic.AtomicBoolean",
|
|
||||||
"fields":[{"name":"value"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.concurrent.atomic.AtomicReference",
|
|
||||||
"fields":[{"name":"value"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.concurrent.atomic.Striped64",
|
|
||||||
"fields":[{"name":"base"}, {"name":"cellsBusy"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.function.Function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"java.util.zip.DeflaterInputStream"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"javax.net.ssl.SNIHostName",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"javax.net.ssl.SSLParameters",
|
|
||||||
"methods":[{"name":"setServerNames","parameterTypes":["java.util.List"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"javax.security.auth.x500.X500Principal",
|
|
||||||
"fields":[{"name":"thisX500Name"}],
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["sun.security.x509.X500Name"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"javax.smartcardio.CardPermission"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"jdk.internal.misc.Unsafe"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlin.Metadata",
|
|
||||||
"queryAllDeclaredMethods":true,
|
|
||||||
"methods":[{"name":"bv","parameterTypes":[] }, {"name":"d1","parameterTypes":[] }, {"name":"d2","parameterTypes":[] }, {"name":"k","parameterTypes":[] }, {"name":"mv","parameterTypes":[] }, {"name":"pn","parameterTypes":[] }, {"name":"xi","parameterTypes":[] }, {"name":"xs","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlin.SafePublicationLazyImpl",
|
|
||||||
"fields":[{"name":"_value"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlin.jvm.internal.DefaultConstructorMarker"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlin.reflect.jvm.internal.ReflectionFactoryImpl",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.CancellableContinuationImpl",
|
|
||||||
"fields":[{"name":"_decisionAndIndex$volatile"}, {"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.EventLoopImplBase",
|
|
||||||
"fields":[{"name":"_delayed$volatile"}, {"name":"_isCompleted$volatile"}, {"name":"_queue$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.JobSupport",
|
|
||||||
"fields":[{"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.internal.DispatchedContinuation",
|
|
||||||
"fields":[{"name":"_reusableCancellableContinuation$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.internal.LimitedDispatcher",
|
|
||||||
"fields":[{"name":"runningWorkers$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.internal.LockFreeLinkedListNode",
|
|
||||||
"fields":[{"name":"_next$volatile"}, {"name":"_prev$volatile"}, {"name":"_removedRef$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.internal.LockFreeTaskQueue",
|
|
||||||
"fields":[{"name":"_cur$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.internal.LockFreeTaskQueueCore",
|
|
||||||
"fields":[{"name":"_next$volatile"}, {"name":"_state$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.internal.ThreadSafeHeap",
|
|
||||||
"fields":[{"name":"_size$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"kotlinx.coroutines.scheduling.CoroutineScheduler",
|
|
||||||
"fields":[{"name":"_isTerminated$volatile"}, {"name":"controlState$volatile"}, {"name":"parkedWorkersStack$volatile"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"net.dv8tion.jda.api.hooks.ListenerAdapter",
|
|
||||||
"methods":[{"name":"onGatewayPing","parameterTypes":["net.dv8tion.jda.api.events.GatewayPingEvent"] }, {"name":"onGenericGuild","parameterTypes":["net.dv8tion.jda.api.events.guild.GenericGuildEvent"] }, {"name":"onGenericSession","parameterTypes":["net.dv8tion.jda.api.events.session.GenericSessionEvent"] }, {"name":"onGuildReady","parameterTypes":["net.dv8tion.jda.api.events.guild.GuildReadyEvent"] }, {"name":"onHttpRequest","parameterTypes":["net.dv8tion.jda.api.events.http.HttpRequestEvent"] }, {"name":"onReady","parameterTypes":["net.dv8tion.jda.api.events.session.ReadyEvent"] }, {"name":"onShutdown","parameterTypes":["net.dv8tion.jda.api.events.session.ShutdownEvent"] }, {"name":"onStatusChange","parameterTypes":["net.dv8tion.jda.api.events.StatusChangeEvent"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"net.dv8tion.jda.internal.utils.FallbackLogger",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.mariadb.jdbc.Configuration",
|
|
||||||
"allDeclaredFields":true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.mariadb.jdbc.Configuration$Builder",
|
|
||||||
"allDeclaredFields":true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.mariadb.jdbc.Driver",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.slf4j.LoggerFactory"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"org.slf4j.spi.SLF4JServiceProvider"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"space.mori.chzzk_bot.discord.CommandInterface"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"space.mori.chzzk_bot.discord.commands.Ping",
|
|
||||||
"fields":[{"name":"INSTANCE"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.pkcs12.PKCS12KeyStore",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.DSA$SHA224withDSA",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.DSA$SHA256withDSA",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.NativePRNG",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }, {"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.SHA",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.SHA2$SHA224",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.SHA2$SHA256",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.SHA5$SHA384",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.SHA5$SHA512",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.X509Factory",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.provider.certpath.PKIXCertPathValidator",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.rsa.PSSParameters",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.rsa.RSAKeyFactory$Legacy",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.rsa.RSAPSSSignature",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.rsa.RSASignature$SHA224withRSA",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.rsa.RSASignature$SHA256withRSA",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.ssl.KeyManagerFactoryImpl$SunX509",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.ssl.SSLContextImpl$DefaultSSLContext",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.ssl.SSLContextImpl$TLSContext",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.util.ObjectIdentifier"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.AuthorityInfoAccessExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.AuthorityKeyIdentifierExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.BasicConstraintsExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.CRLDistributionPointsExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.CertificateExtensions"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.CertificatePoliciesExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.ExtendedKeyUsageExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.IssuerAlternativeNameExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.KeyUsageExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.NetscapeCertTypeExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.PrivateKeyUsageExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.SubjectAlternativeNameExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
|
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
|
|
||||||
}
|
|
||||||
]
|
|
@@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"resources":{
|
|
||||||
"includes":[{
|
|
||||||
"pattern":"\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/java.net.spi.InetAddressResolverProvider\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/java.sql.Driver\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/kotlin.reflect.jvm.internal.impl.util.ModuleVisibilityHelper\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/org.jetbrains.exposed.sql.DatabaseConnectionAutoRegistration\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/org.jetbrains.exposed.sql.statements.GlobalStatementInterceptor\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/org.mariadb.jdbc.plugin.Codec\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\Qlogback-test.scmo\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\Qlogback-test.xml\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\Qlogback.scmo\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\Qlogback.xml\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\Qmariadb.properties\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"\\Qspace/mori/chzzk_bot/discord/commands\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt72b/nfc.nrm\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt72b/nfkc.nrm\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt72b/uprops.icu\\E"
|
|
||||||
}, {
|
|
||||||
"pattern":"java.base:\\Qsun/net/idn/uidna.spp\\E"
|
|
||||||
}]},
|
|
||||||
"bundles":[]
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"types":[
|
|
||||||
],
|
|
||||||
"lambdaCapturingTypes":[
|
|
||||||
],
|
|
||||||
"proxies":[
|
|
||||||
]
|
|
||||||
}
|
|
35
src/main/resources/logback-debug.xml
Normal file
35
src/main/resources/logback-debug.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<configuration>
|
||||||
|
|
||||||
|
<!-- 콘솔에 출력하는 기본 로그 설정 -->
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>DEBUG</level>
|
||||||
|
</filter>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- HikariCP 로그 레벨 설정 -->
|
||||||
|
<logger name="com.zaxxer.hikari" level="INFO" />
|
||||||
|
<logger name="o.m.jdbc.client.impl.StandardClient" level="INFO" />
|
||||||
|
<logger name="o.m.jdbc.message.server.OkPacket" level="INFO" />
|
||||||
|
<logger name="o.m.jdbc.client.impl.StandardClient" level="INFO" />
|
||||||
|
|
||||||
|
<logger name="com.zaxxer.hikari.HikariConfig" level="WARN" />
|
||||||
|
<logger name="com.zaxxer.hikari.pool.PoolBase" level="WARN" />
|
||||||
|
<logger name="com.zaxxer.hikari.pool.HikariPool" level="WARN" />
|
||||||
|
<logger name="com.zaxxer.hikari.util.DriverDataSource" level="WARN" />
|
||||||
|
|
||||||
|
<!-- Exposed 로그 레벨 설정 -->
|
||||||
|
<logger name="org.jetbrains.exposed" level="INFO" />
|
||||||
|
<logger name="Exposed" level="INFO" />
|
||||||
|
<logger name="org.jetbrains.exposed.sql" level="WARN" />
|
||||||
|
<logger name="org.jetbrains.exposed.sql.transactions" level="WARN" />
|
||||||
|
|
||||||
|
<!-- 루트 로거 설정 -->
|
||||||
|
<root level="DEBUG">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
@@ -3,7 +3,7 @@
|
|||||||
<!-- 콘솔에 출력하는 기본 로그 설정 -->
|
<!-- 콘솔에 출력하는 기본 로그 설정 -->
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>DEBUG</level>
|
<level>INFO</level>
|
||||||
</filter>
|
</filter>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
Reference in New Issue
Block a user