Files
FancyBot/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt
T

207 lines
8.4 KiB
Kotlin

/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/8/26
*/
package cn.rtast.fancybot
import cn.rtast.fancybot.commands.misc.ScanQRCodeCommand
import cn.rtast.fancybot.commands.misc.ShortLinkCommand.Companion.makeShortLink
import cn.rtast.fancybot.commands.parse.*
import cn.rtast.fancybot.enums.WSType
import cn.rtast.fancybot.util.*
import cn.rtast.fancybot.util.file.getFileType
import cn.rtast.fancybot.util.misc.ImageBed
import cn.rtast.fancybot.util.misc.initCommandAndItem
import cn.rtast.fancybot.util.misc.initFilesDir
import cn.rtast.fancybot.util.misc.initSetuIndex
import cn.rtast.fancybot.util.misc.toURI
import cn.rtast.fancybot.util.misc.toURL
import cn.rtast.rob.ROneBotFactory
import cn.rtast.rob.entity.*
import cn.rtast.rob.entity.lagrange.FileEvent
import cn.rtast.rob.entity.lagrange.PokeEvent
import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.enums.QQFace
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
import cn.rtast.rob.util.ob.asNode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import java.net.URI
class FancyBot : OneBotListener {
private val logger = Logger.getLogger<FancyBot>()
private val coroutineScope = CoroutineScope(Dispatchers.IO)
private val githubRegex = Regex("""github\.com/([^/]+)/([^/]+)""")
override suspend fun onWebsocketOpenEvent() {
this.sendPrivateMessage(configManager.startUpNoticeUser, "FancyBot启动完成~")
}
override suspend fun onGroupMessage(message: GroupMessage, json: String) {
val sender = message.sender.nickname
val senderId = message.sender.userId
val msg = message.rawMessage
val groupId = message.groupId
val messageId = message.messageId
logger.info("$sender($senderId: $groupId >>> $messageId): $msg")
logger.trace("$sender($senderId: $groupId >>> $messageId: $json")
if (message.message.any { it.type == ArrayMessageType.face && it.data.id.toString() == "419" }) {
message.reply("你发牛魔的火车呢, 我直接就是打断")
}
if (message.rawMessage.contains("原神")) {
(0..10).forEach { _ ->
message.reaction(QQFace.entries.random())
}
message.reply("你原神牛魔呢")
}
ReverseGIFCommand.callback(message)
AsciiArtCommand.callback(message)
ScanQRCodeCommand.callback(message)
BVParseCommand.parse(this, message)
if (message.rawMessage.toList().any { it in arrayListOf('*', '-', '/', '+', '=') }) {
val calculateResult = CalculateCommand.parse(message.rawMessage)
calculateResult?.let { message.reply(calculateResult) }
}
if (message.message.any { it.type == ArrayMessageType.reply }) { // Image url parse
val command = message.message.reversed().find { it.type == ArrayMessageType.text }!!.data.text!!
val replyId = message.message.find { it.type == ArrayMessageType.reply }!!.data.id!!
if (command.contains("图来") || command.contains("图链")) {
val getMsg = this.getMessage(replyId.toString().toLong())
ImageURLCommand.callback(message, getMsg)
}
if (command.contains("图床")) {
val getMsg = this.getMessage(replyId.toString().toLong())
val imagesUrl = ImageURLCommand.getImageUrl(getMsg)
if (imagesUrl.isEmpty()) {
message.reply("这个消息里没有图片呢!")
} else {
try {
if (imagesUrl.size == 1) {
val imageByteArray = imagesUrl[0].toURL().readBytes()
val imageFileType = imageByteArray.getFileType()
val imageBedUrl = ImageBed.upload(imageByteArray, imageFileType)
val msg = MessageChain.Builder()
.addText(imageBedUrl.makeShortLink())
.addNewLine(2)
.addText(imageBedUrl)
.build()
message.reply(msg)
} else {
val messages = mutableListOf<MessageChain>()
imagesUrl.forEach {
val imageByteArray = it.toURL().readBytes()
val imageFileType = imageByteArray.getFileType()
val imageBedUrl = ImageBed.upload(imageByteArray, imageFileType)
val msg = MessageChain.Builder()
.addText(imageBedUrl.makeShortLink())
.addNewLine(2)
.addText(imageBedUrl)
.build()
messages.add(msg)
}
message.reply(messages.asNode(configManager.selfId))
}
} catch (e: Exception) {
message.reply("上传失败: ${e.message}")
}
}
}
}
val matchedResult = githubRegex.find(message.rawMessage)
if (message.rawMessage.contains("github.com") && matchedResult != null) {
val (user, repo) = matchedResult.destructured
GitHubParseCommand.parse(message, user, repo)
}
coroutineScope.launch {
message.message.forEach {
if (it.type == ArrayMessageType.image) {
val filename = it.data.file!!.split("=").last() + ".png"
URI(it.data.file!!).toURL().openConnection().inputStream.use { input ->
File("$ROOT_PATH/caches/images/$filename").outputStream().use { output ->
output.write(input.readBytes())
}
}
}
}
}
}
override suspend fun onGroupMessageRevoke(message: GroupRevokeMessage) {
if (!configManager.enableAntiRevoke) return
val msg = MessageChain.Builder()
.addText("用户: ${message.userId} 被: ${message.operatorId} 撤回了一条消息")
.addNewLine()
.addText("使用/revoke ${message.messageId} 来获取被撤回的消息")
.build()
this.sendGroupMessage(message.groupId, msg)
}
override suspend fun onWebsocketErrorEvent(ex: Exception) {
ex.printStackTrace()
}
override suspend fun onAddFriendRequest(event: AddFriendRequest) {
event.approve()
}
override suspend fun onGroupFileUpload(event: FileEvent) {
event.saveTo("$ROOT_PATH/caches/")
}
override suspend fun onLeaveEvent(groupId: Long, userId: Long, operator: Long, time: Long) {
val msg = MessageChain.Builder()
.addText("有人坐飞船离开了本星系~")
.addNewLine()
.addText("QQ: $userId | 操作者: ${if (operator == 0L) "主动退出" else operator}")
.addNewLine()
.addText("下次再见吧~~~")
.build()
this.sendGroupMessage(groupId, msg)
}
override suspend fun onPoke(event: PokeEvent) {
event.groupId?.let {
if (event.targetId == configManager.selfId) {
val msg = MessageChain.Builder()
.addAt(event.userId)
.addText("你${event.action.first()}牛魔呢")
.build()
this.sendGroupMessage(it, msg)
}
}
}
}
suspend fun main() {
val fancyBot = FancyBot()
val workType = configManager.wsType
val accessToken = configManager.accessToken
val rob = if (workType == WSType.Client) {
val address = configManager.wsAddress
ROneBotFactory.createClient(address, accessToken, fancyBot)
.also { it.addListeningGroups(*configManager.listeningGroups.toLongArray()) }
} else {
val port = configManager.wsPort
ROneBotFactory.createServer(port, accessToken, fancyBot)
.also { it.addListeningGroups(*configManager.listeningGroups.toLongArray()) }
}
initDatabase()
initFilesDir()
initCommandAndItem(rob)
initSetuIndex()
}