diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index a723856..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Build FancyBot -on: - - push -jobs: - build: - strategy: - matrix: - java: - - 17 - os: - - ubuntu-latest - runs-on: ${{ matrix.os }} - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Validate gradle wrapper - uses: gradle/wrapper-validation-action@v1 - - name: Setup jdk ${{ matrix.java }} - uses: actions/setup-java@v1 - with: - java-version: ${{ matrix.java }} - - name: Make Gradle wrapper executable - run: chmod +x ./gradlew - - name: Build - run: ./gradlew build - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - with: - name: FancyBot - path: | - **/build/libs/*.jar \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 329231b..b833392 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,8 +27,12 @@ tasks.compileJava { dependencies { + val exposedVersion = "0.53.0" implementation(libs.rOneBot) implementation(libs.okhttp) + implementation("org.jetbrains.exposed:exposed-core:$exposedVersion") + implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion") + implementation("org.xerial:sqlite-jdbc:3.46.1.0") } tasks.build { diff --git a/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt b/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt index fbb5fa5..d811df5 100644 --- a/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt +++ b/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt @@ -16,6 +16,7 @@ import cn.rtast.fancybot.commands.MyPointCommand import cn.rtast.fancybot.commands.SignCommand import cn.rtast.fancybot.entity.enums.WSType import cn.rtast.fancybot.util.file.ConfigManager +import cn.rtast.fancybot.util.initDatabase import cn.rtast.rob.ROneBotFactory import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.util.ob.OBMessage @@ -25,6 +26,10 @@ class FancyBot : OBMessage { override suspend fun onGroupMessage(websocket: WebSocket, message: GroupMessage, json: String) { println(message.rawMessage) } + + override suspend fun onWebsocketError(webSocket: WebSocket, ex: Exception) { + println(ex.printStackTrace()) + } } val commands = listOf( @@ -39,7 +44,7 @@ val commands = listOf( val configManager = ConfigManager() -fun main() { +suspend fun main() { val fancyBot = FancyBot() val workType = configManager.wsType val accessToken = configManager.accessToken @@ -52,4 +57,5 @@ fun main() { } val commandManager = rob.commandManager commands.forEach { commandManager.register(it) } + initDatabase() } \ No newline at end of file diff --git a/src/main/kotlin/cn/rtast/fancybot/commands/FKXQSCommand.kt b/src/main/kotlin/cn/rtast/fancybot/commands/FKXQSCommand.kt index 9f61cf7..0b886c1 100644 --- a/src/main/kotlin/cn/rtast/fancybot/commands/FKXQSCommand.kt +++ b/src/main/kotlin/cn/rtast/fancybot/commands/FKXQSCommand.kt @@ -7,7 +7,7 @@ package cn.rtast.fancybot.commands -import cn.rtast.fancybot.entity.fkxqs.FKXQS +import cn.rtast.fancybot.entity.FKXQS import cn.rtast.fancybot.util.Http import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.util.BaseCommand diff --git a/src/main/kotlin/cn/rtast/fancybot/commands/SignCommand.kt b/src/main/kotlin/cn/rtast/fancybot/commands/SignCommand.kt index acf8d85..0524e9d 100644 --- a/src/main/kotlin/cn/rtast/fancybot/commands/SignCommand.kt +++ b/src/main/kotlin/cn/rtast/fancybot/commands/SignCommand.kt @@ -23,12 +23,12 @@ class SignCommand : BaseCommand() { return } val randomPoint = signManager.sign(message.sender.userId) - listener.sendGroupMessage(message.groupId, "你获得了 $randomPoint 点分数!\n发送‘/我的分数’ 即可查看当前的分数") + listener.sendGroupMessage(message.groupId, "你获得了 $randomPoint 点分数!\n发送‘/我的点数’ 即可查看当前的点数") } } class MyPointCommand: BaseCommand() { - override val commandNames = listOf("/我的分数", "/mp") + override val commandNames = listOf("/我的点数", "/mp") override suspend fun executeGroup(listener: OBMessage, message: GroupMessage, args: List) { val status = signManager.getStatus(message.sender.userId) @@ -36,7 +36,7 @@ class MyPointCommand: BaseCommand() { listener.sendGroupMessage(message.groupId, "你还没有签到过呢! 先发送‘/签到’再来查询吧~") return } else { - listener.sendGroupMessage(message.groupId, "你当前的分数为: ${status.points}") + listener.sendGroupMessage(message.groupId, "你当前的点数为: ${status.points}") } } } \ No newline at end of file diff --git a/src/main/kotlin/cn/rtast/fancybot/entity/fkxqs/FKXQS.kt b/src/main/kotlin/cn/rtast/fancybot/entity/FKXQS.kt similarity index 81% rename from src/main/kotlin/cn/rtast/fancybot/entity/fkxqs/FKXQS.kt rename to src/main/kotlin/cn/rtast/fancybot/entity/FKXQS.kt index 3a1a3f6..2a3e81d 100644 --- a/src/main/kotlin/cn/rtast/fancybot/entity/fkxqs/FKXQS.kt +++ b/src/main/kotlin/cn/rtast/fancybot/entity/FKXQS.kt @@ -5,7 +5,7 @@ */ -package cn.rtast.fancybot.entity.fkxqs +package cn.rtast.fancybot.entity data class FKXQS( val data: Data, diff --git a/src/main/kotlin/cn/rtast/fancybot/entity/JrrpTable.kt b/src/main/kotlin/cn/rtast/fancybot/entity/JrrpTable.kt new file mode 100644 index 0000000..2102bc0 --- /dev/null +++ b/src/main/kotlin/cn/rtast/fancybot/entity/JrrpTable.kt @@ -0,0 +1,25 @@ +/* + * Copyright © 2024 RTAkland + * Author: RTAkland + * Date: 2024/8/30 + */ + + +package cn.rtast.fancybot.entity + +import org.jetbrains.exposed.sql.Table + +object JrrpTable : Table("jrrp") { + val id = integer("id").autoIncrement() + val userId = long("userId").uniqueIndex() + val timestamp = long("timestamp") + val point = long("point") + + override val primaryKey = PrimaryKey(id) +} + +data class JrrpRecord( + val id: Long, + val timestamp: Long, + var points: Long, +) \ No newline at end of file diff --git a/src/main/kotlin/cn/rtast/fancybot/entity/SignTable.kt b/src/main/kotlin/cn/rtast/fancybot/entity/SignTable.kt new file mode 100644 index 0000000..d90fc53 --- /dev/null +++ b/src/main/kotlin/cn/rtast/fancybot/entity/SignTable.kt @@ -0,0 +1,19 @@ +/* + * Copyright © 2024 RTAkland + * Author: RTAkland + * Date: 2024/8/30 + */ + + +package cn.rtast.fancybot.entity + +import org.jetbrains.exposed.sql.Table + +object SignTable : Table("sign") { + val id = integer("id").autoIncrement() + val userId = long("userId").uniqueIndex() + val timestamp = long("timestamp") + val point = long("point") + + override val primaryKey = PrimaryKey(id) +} \ No newline at end of file diff --git a/src/main/kotlin/cn/rtast/fancybot/entity/jrrp/JrrpRecord.kt b/src/main/kotlin/cn/rtast/fancybot/entity/jrrp/JrrpRecord.kt deleted file mode 100644 index fd22b52..0000000 --- a/src/main/kotlin/cn/rtast/fancybot/entity/jrrp/JrrpRecord.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright © 2024 RTAkland - * Author: RTAkland - * Date: 2024/8/29 - */ - - -package cn.rtast.fancybot.entity.jrrp - -data class JrrpRecord( - val id: Long, - val timestamp: Long, - var points: Long, -) \ No newline at end of file diff --git a/src/main/kotlin/cn/rtast/fancybot/util/Database.kt b/src/main/kotlin/cn/rtast/fancybot/util/Database.kt new file mode 100644 index 0000000..e59f063 --- /dev/null +++ b/src/main/kotlin/cn/rtast/fancybot/util/Database.kt @@ -0,0 +1,27 @@ +/* + * Copyright © 2024 RTAkland + * Author: RTAkland + * Date: 2024/8/30 + */ + + +package cn.rtast.fancybot.util + +import cn.rtast.fancybot.ROOT_PATH +import cn.rtast.fancybot.entity.JrrpTable +import cn.rtast.fancybot.entity.SignTable +import kotlinx.coroutines.Dispatchers +import org.jetbrains.exposed.sql.Database +import org.jetbrains.exposed.sql.SchemaUtils +import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction + +suspend fun initDatabase() { + Database.connect("jdbc:sqlite:file:$ROOT_PATH/data.sqlite", "org.sqlite.JDBC") + suspendedTransaction { + SchemaUtils.createMissingTablesAndColumns(JrrpTable) + SchemaUtils.createMissingTablesAndColumns(SignTable) + } +} + +suspend fun suspendedTransaction(block: suspend () -> T): T = + newSuspendedTransaction(Dispatchers.IO) { block() } \ No newline at end of file diff --git a/src/main/kotlin/cn/rtast/fancybot/util/DateUtil.kt b/src/main/kotlin/cn/rtast/fancybot/util/DateUtil.kt index 68a8f44..fc8c6cd 100644 --- a/src/main/kotlin/cn/rtast/fancybot/util/DateUtil.kt +++ b/src/main/kotlin/cn/rtast/fancybot/util/DateUtil.kt @@ -8,13 +8,10 @@ package cn.rtast.fancybot.util import java.time.Instant -import java.time.LocalDate import java.time.ZoneId -fun Long.isSameDay(other: Long): Boolean { - val currentDate = LocalDate.now() - val dateToCompare = Instant.ofEpochSecond(other) - .atZone(ZoneId.systemDefault()) - .toLocalDate() - return currentDate == dateToCompare +fun Long.isSameDay(otherTimestamp: Long, zoneId: ZoneId = ZoneId.systemDefault()): Boolean { + val thisDate = Instant.ofEpochMilli(this).atZone(zoneId).toLocalDate() + val otherDate = Instant.ofEpochMilli(otherTimestamp).atZone(zoneId).toLocalDate() + return thisDate == otherDate } diff --git a/src/main/kotlin/cn/rtast/fancybot/util/file/JrrpManager.kt b/src/main/kotlin/cn/rtast/fancybot/util/file/JrrpManager.kt index cbdcfc8..31b296d 100644 --- a/src/main/kotlin/cn/rtast/fancybot/util/file/JrrpManager.kt +++ b/src/main/kotlin/cn/rtast/fancybot/util/file/JrrpManager.kt @@ -7,25 +7,57 @@ package cn.rtast.fancybot.util.file -import cn.rtast.fancybot.entity.jrrp.JrrpRecord -import cn.rtast.fancybot.util.JsonFileHandler +import cn.rtast.fancybot.entity.JrrpRecord +import cn.rtast.fancybot.entity.JrrpTable +import cn.rtast.fancybot.util.suspendedTransaction import cn.rtast.fancybot.util.isSameDay +import org.jetbrains.exposed.sql.insert +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.update import java.time.Instant import kotlin.random.Random -class JrrpManager : JsonFileHandler>("jrrp.json", listOf()) { +class JrrpManager { - fun isJrrped(id: Long): Boolean { - val allJrrp = this.readArray>() - val user = allJrrp.find { it.id == id } ?: return false - return user.timestamp.isSameDay(Instant.now().epochSecond) + private suspend fun getRecord(id: Long): JrrpRecord? { + return suspendedTransaction { + JrrpTable.selectAll().where { JrrpTable.userId eq id }.map { + JrrpRecord( + it[JrrpTable.userId], + it[JrrpTable.timestamp], + it[JrrpTable.point], + ) + }.singleOrNull() + } } - fun jrrp(id: Long): Int { - val allJrrp = this.readArray>() - allJrrp.removeAll { it.id == id } - allJrrp.add(JrrpRecord(id, Instant.now().epochSecond, 0)) - this.write(allJrrp) - return Random.nextInt(0, 101) + suspend fun isJrrped(id: Long): Boolean { + val record = getRecord(id) + return if (record != null) { + record.timestamp.isSameDay(Instant.now().epochSecond) + } else { + false + } + } + + suspend fun jrrp(id: Long): Long { + val randomPoint = Random.nextLong(0, 101) + if (getRecord(id) == null) { + suspendedTransaction { + JrrpTable.insert { + it[userId] = id + it[timestamp] = Instant.now().epochSecond + it[point] = 0 + } + } + } + val record = getRecord(id) + suspendedTransaction { + JrrpTable.update({ JrrpTable.userId eq id }) { + it[point] = record?.points!! + randomPoint + it[timestamp] = Instant.now().epochSecond + } + } + return randomPoint } } \ No newline at end of file diff --git a/src/main/kotlin/cn/rtast/fancybot/util/file/SignManager.kt b/src/main/kotlin/cn/rtast/fancybot/util/file/SignManager.kt index 1bf961e..06e2389 100644 --- a/src/main/kotlin/cn/rtast/fancybot/util/file/SignManager.kt +++ b/src/main/kotlin/cn/rtast/fancybot/util/file/SignManager.kt @@ -7,33 +7,64 @@ package cn.rtast.fancybot.util.file -import cn.rtast.fancybot.entity.jrrp.JrrpRecord -import cn.rtast.fancybot.util.JsonFileHandler +import cn.rtast.fancybot.entity.JrrpRecord +import cn.rtast.fancybot.entity.SignTable +import cn.rtast.fancybot.entity.SignTable.point +import cn.rtast.fancybot.entity.SignTable.timestamp +import cn.rtast.fancybot.entity.SignTable.userId +import cn.rtast.fancybot.util.suspendedTransaction import cn.rtast.fancybot.util.isSameDay +import org.jetbrains.exposed.sql.insert +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.update import java.time.Instant import kotlin.random.Random -class SignManager : JsonFileHandler>("sign.json", listOf()) { +class SignManager { - fun isSigned(id: Long): Boolean { - val allSign = this.readArray>() - val user = allSign.find { it.id == id } ?: return false - return user.timestamp.isSameDay(Instant.now().epochSecond) + private suspend fun getRecord(id: Long): JrrpRecord? { + return suspendedTransaction { + SignTable.selectAll().where { userId eq id }.map { + JrrpRecord( + it[userId], + it[timestamp], + it[point], + ) + }.singleOrNull() + } } - fun sign(id: Long): Long { - val allSign = this.readArray>() + suspend fun isSigned(id: Long): Boolean { + val record = getRecord(id) + return if (record != null) { + record.timestamp.isSameDay(Instant.now().epochSecond) + } else { + false + } + } + + suspend fun sign(id: Long): Long { val randomPoint = Random.nextLong(0, 101) - val current = allSign.find { it.id == id } ?: JrrpRecord(id, Instant.now().epochSecond, 0) - current.points = randomPoint + current.points - allSign.remove(current) - allSign.add(current) - this.write(allSign) - return randomPoint + current.points + if (getRecord(id) == null) { + suspendedTransaction { + SignTable.insert { + it[userId] = id + it[timestamp] = Instant.now().epochSecond + it[point] = 0 + } + } + } + val record = getRecord(id) + suspendedTransaction { + SignTable.update({ userId eq id }) { + it[point] = record?.points!! + randomPoint + it[timestamp] = Instant.now().epochSecond + } + } + return randomPoint } - fun getStatus(id: Long): JrrpRecord? { - val allSign = this.readArray>() - return allSign.find { it.id == id } + suspend fun getStatus(id: Long): JrrpRecord? { + return getRecord(id) } } \ No newline at end of file