2024-08-27 18:44:32 +08:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2024 RTAkland
|
|
|
|
|
* Author: RTAkland
|
|
|
|
|
* Date: 2024/8/26
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package cn.rtast.fancybot
|
|
|
|
|
|
2024-10-27 18:19:32 +08:00
|
|
|
import cn.rtast.fancybot.commands.misc.JueCommand
|
2024-10-14 22:41:01 +08:00
|
|
|
import cn.rtast.fancybot.commands.misc.PastebinCommand
|
2024-10-11 19:28:22 +08:00
|
|
|
import cn.rtast.fancybot.commands.misc.ReactionCommand
|
2024-10-06 21:18:23 +08:00
|
|
|
import cn.rtast.fancybot.commands.misc.ScanQRCodeCommand
|
2024-10-14 22:41:01 +08:00
|
|
|
import cn.rtast.fancybot.commands.misc.ShortLinkCommand.Companion.makeShortLink
|
2024-09-27 15:22:24 +08:00
|
|
|
import cn.rtast.fancybot.commands.parse.*
|
2024-10-13 10:52:37 +08:00
|
|
|
import cn.rtast.fancybot.commands.reply.ImageBedCommand
|
2024-10-27 17:43:06 +08:00
|
|
|
import cn.rtast.fancybot.commands.reply.SpeedUpGIFCommand
|
2024-10-26 11:46:32 +08:00
|
|
|
import cn.rtast.fancybot.entity.nailong.NaiLongDetectPayload
|
|
|
|
|
import cn.rtast.fancybot.entity.nailong.NaiLongDetectResponse
|
2024-10-02 21:02:05 +08:00
|
|
|
import cn.rtast.fancybot.enums.WSType
|
2024-10-07 19:13:51 +08:00
|
|
|
import cn.rtast.fancybot.util.*
|
2024-10-27 18:19:32 +08:00
|
|
|
import cn.rtast.fancybot.util.misc.ImageBed
|
2024-10-11 17:12:50 +08:00
|
|
|
import cn.rtast.fancybot.util.misc.convertToDate
|
2024-10-15 18:58:12 +08:00
|
|
|
import cn.rtast.fancybot.util.misc.initBackgroundTasks
|
|
|
|
|
import cn.rtast.fancybot.util.misc.initCommand
|
2024-10-09 13:06:43 +08:00
|
|
|
import cn.rtast.fancybot.util.misc.initFilesDir
|
2024-10-15 18:58:12 +08:00
|
|
|
import cn.rtast.fancybot.util.misc.initItems
|
2024-10-09 13:06:43 +08:00
|
|
|
import cn.rtast.fancybot.util.misc.initSetuIndex
|
2024-10-29 11:47:25 +08:00
|
|
|
import cn.rtast.fancybot.util.misc.makeGif
|
2024-10-27 18:19:32 +08:00
|
|
|
import cn.rtast.fancybot.util.misc.toBufferedImage
|
|
|
|
|
import cn.rtast.fancybot.util.misc.toByteArray
|
|
|
|
|
import cn.rtast.fancybot.util.misc.toGrayscale
|
|
|
|
|
import cn.rtast.fancybot.util.misc.toURL
|
|
|
|
|
import cn.rtast.fancybot.util.str.encodeToBase64
|
2024-10-26 11:46:32 +08:00
|
|
|
import cn.rtast.fancybot.util.str.toJson
|
2024-08-27 18:44:32 +08:00
|
|
|
import cn.rtast.rob.ROneBotFactory
|
2024-09-25 12:51:34 +08:00
|
|
|
import cn.rtast.rob.entity.*
|
2024-10-24 19:27:06 +08:00
|
|
|
import cn.rtast.rob.entity.custom.BeKickEvent
|
2024-10-31 14:02:04 +08:00
|
|
|
import cn.rtast.rob.entity.custom.ErrorEvent
|
2024-10-25 19:44:33 +08:00
|
|
|
import cn.rtast.rob.entity.custom.MemberKickEvent
|
2024-10-24 19:27:06 +08:00
|
|
|
import cn.rtast.rob.entity.custom.MemberLeaveEvent
|
2024-09-27 19:36:56 +08:00
|
|
|
import cn.rtast.rob.entity.lagrange.FileEvent
|
2024-09-28 12:37:18 +08:00
|
|
|
import cn.rtast.rob.entity.lagrange.PokeEvent
|
2024-09-06 10:58:55 +08:00
|
|
|
import cn.rtast.rob.enums.ArrayMessageType
|
2024-10-01 20:18:19 +08:00
|
|
|
import cn.rtast.rob.enums.QQFace
|
2024-09-02 11:30:58 +08:00
|
|
|
import cn.rtast.rob.util.ob.MessageChain
|
2024-10-25 14:25:43 +08:00
|
|
|
import cn.rtast.rob.util.ob.OneBotAction
|
2024-09-19 11:06:40 +08:00
|
|
|
import cn.rtast.rob.util.ob.OneBotListener
|
2024-10-29 11:47:25 +08:00
|
|
|
import com.madgag.gif.fmsware.GifDecoder
|
2024-09-20 22:23:43 +08:00
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
2024-10-24 16:55:14 +08:00
|
|
|
import kotlinx.coroutines.delay
|
2024-09-20 22:23:43 +08:00
|
|
|
import kotlinx.coroutines.launch
|
2024-10-29 11:47:25 +08:00
|
|
|
import kotlinx.coroutines.withContext
|
2024-09-19 15:11:40 +08:00
|
|
|
import java.io.File
|
2024-09-20 22:23:43 +08:00
|
|
|
import java.net.URI
|
2024-08-27 18:44:32 +08:00
|
|
|
|
2024-09-19 11:06:40 +08:00
|
|
|
class FancyBot : OneBotListener {
|
2024-09-02 11:30:58 +08:00
|
|
|
|
2024-10-07 19:13:51 +08:00
|
|
|
private val logger = Logger.getLogger<FancyBot>()
|
2024-09-20 22:23:43 +08:00
|
|
|
private val coroutineScope = CoroutineScope(Dispatchers.IO)
|
|
|
|
|
|
2024-10-25 14:25:43 +08:00
|
|
|
override suspend fun onWebsocketOpenEvent(action: OneBotAction) {
|
|
|
|
|
action.sendPrivateMessage(configManager.noticeUser, "FancyBot启动完成~")
|
2024-09-22 20:51:39 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-07 18:07:56 +08:00
|
|
|
override suspend fun onGroupMessage(message: GroupMessage, json: String) {
|
2024-09-03 12:32:52 +08:00
|
|
|
val sender = message.sender.nickname
|
|
|
|
|
val senderId = message.sender.userId
|
|
|
|
|
val msg = message.rawMessage
|
|
|
|
|
val groupId = message.groupId
|
2024-09-19 18:15:42 +08:00
|
|
|
val messageId = message.messageId
|
2024-10-07 19:13:51 +08:00
|
|
|
logger.info("$sender($senderId: $groupId >>> $messageId): $msg")
|
|
|
|
|
logger.trace("$sender($senderId: $groupId >>> $messageId: $json")
|
2024-09-18 13:06:23 +08:00
|
|
|
|
2024-09-28 16:31:55 +08:00
|
|
|
if (message.message.any { it.type == ArrayMessageType.face && it.data.id.toString() == "419" }) {
|
|
|
|
|
message.reply("你发牛魔的火车呢, 我直接就是打断")
|
|
|
|
|
}
|
2024-09-27 23:31:01 +08:00
|
|
|
|
2024-10-24 16:55:14 +08:00
|
|
|
if (message.text.contains("原神")) {
|
|
|
|
|
(0..10).forEach { _ -> message.reaction(QQFace.entries.random()) }
|
2024-09-24 14:56:51 +08:00
|
|
|
message.reply("你原神牛魔呢")
|
2024-10-24 16:55:14 +08:00
|
|
|
delay(1500L)
|
|
|
|
|
message.reply("但是话又说回来.....启动!!")
|
2024-09-24 14:56:51 +08:00
|
|
|
}
|
|
|
|
|
|
2024-10-13 10:52:37 +08:00
|
|
|
GitHubParseCommand.parse(message)
|
2024-09-28 16:31:55 +08:00
|
|
|
ReverseGIFCommand.callback(message)
|
|
|
|
|
AsciiArtCommand.callback(message)
|
2024-10-06 21:18:23 +08:00
|
|
|
ScanQRCodeCommand.callback(message)
|
2024-10-31 14:02:04 +08:00
|
|
|
BiliVideoParseCommand.parse(message)
|
|
|
|
|
BiliUserParseCommand.parse(message)
|
2024-10-13 11:57:56 +08:00
|
|
|
DouyinVideoParseCommand.parse(message)
|
2024-10-15 15:40:33 +08:00
|
|
|
YoutubeVideoParseCommand.parse(message)
|
2024-09-28 16:31:55 +08:00
|
|
|
|
2024-10-24 16:55:14 +08:00
|
|
|
if (message.text.toList().any { it in arrayListOf('*', '-', '/', '+', '=') }) {
|
2024-09-21 16:03:28 +08:00
|
|
|
val calculateResult = CalculateCommand.parse(message.rawMessage)
|
|
|
|
|
calculateResult?.let { message.reply(calculateResult) }
|
|
|
|
|
}
|
2024-10-27 18:19:32 +08:00
|
|
|
|
|
|
|
|
if (message.message.any { it.type == ArrayMessageType.at }) {
|
|
|
|
|
if (message.text.contains("/取头像")) {
|
|
|
|
|
val target = message.message.find { it.type == ArrayMessageType.at }?.data?.qq!!
|
|
|
|
|
val avatar = JueCommand.AVATAR_REPLACE_URL.replace("#{}", target)
|
|
|
|
|
val msg = MessageChain.Builder()
|
|
|
|
|
if (message.text.contains("黑白")) {
|
|
|
|
|
val greyscale = avatar.toURL()
|
|
|
|
|
.readBytes().toBufferedImage()
|
|
|
|
|
.toGrayscale().toByteArray()
|
|
|
|
|
val greyscaleShortLink = ImageBed.upload(greyscale).makeShortLink()
|
|
|
|
|
msg.addImage(greyscale.encodeToBase64(), true)
|
|
|
|
|
.addText(greyscaleShortLink)
|
|
|
|
|
} else {
|
|
|
|
|
val shortLink = avatar.makeShortLink()
|
|
|
|
|
msg.addImage(avatar).addText(shortLink)
|
|
|
|
|
}
|
|
|
|
|
message.reply(msg.build())
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-21 13:36:21 +08:00
|
|
|
|
2024-10-12 20:59:31 +08:00
|
|
|
if (message.message.any { it.type == ArrayMessageType.reply }) {
|
2024-09-24 00:48:23 +08:00
|
|
|
val command = message.message.reversed().find { it.type == ArrayMessageType.text }!!.data.text!!
|
|
|
|
|
val replyId = message.message.find { it.type == ArrayMessageType.reply }!!.data.id!!
|
2024-10-24 19:27:06 +08:00
|
|
|
val getMsg = message.action.getMessage(replyId.toString().toLong())
|
2024-10-14 22:41:01 +08:00
|
|
|
val plainTextContent = getMsg.message
|
|
|
|
|
.filter { it.type == ArrayMessageType.text }
|
|
|
|
|
.joinToString { it.data.text!! }
|
2024-10-27 18:01:54 +08:00
|
|
|
if (command.contains("/倒放") || command.contains("/df")) ReverseGIFCommand.reverse(message, getMsg)
|
|
|
|
|
if (command.contains("/图来") || command.contains("/图链")) ImageURLCommand.callback(message, getMsg)
|
|
|
|
|
if (command.contains("/图床")) ImageBedCommand.execute(getMsg, message)
|
2024-10-27 18:42:30 +08:00
|
|
|
if (command.contains("/reaction")) ReactionCommand.reaction(
|
|
|
|
|
message.action,
|
|
|
|
|
message.groupId,
|
|
|
|
|
getMsg.messageId
|
|
|
|
|
)
|
2024-10-27 18:00:34 +08:00
|
|
|
if (command.contains("/sl") || command.contains("/short")) message.reply(
|
|
|
|
|
plainTextContent.trim().makeShortLink()
|
|
|
|
|
)
|
2024-10-12 20:59:31 +08:00
|
|
|
if (command.contains("/ascii") || command.contains("/asc")) {
|
|
|
|
|
val url = AsciiArtCommand.getImageUrl(getMsg)
|
|
|
|
|
val image = AsciiArtCommand.generateAsciiArt(url)
|
|
|
|
|
message.reply(image)
|
|
|
|
|
}
|
2024-10-27 18:00:34 +08:00
|
|
|
if (command.contains("/pb") || command.contains("/pastebin")) {
|
|
|
|
|
val pastebinUrl = PastebinCommand.createPastebin(plainTextContent)
|
|
|
|
|
message.reply(pastebinUrl)
|
2024-10-11 19:36:22 +08:00
|
|
|
}
|
2024-10-27 18:01:54 +08:00
|
|
|
if (command.contains("/加速")) {
|
2024-10-27 18:00:34 +08:00
|
|
|
val multiply = command.split("加速").last().toFloat()
|
|
|
|
|
SpeedUpGIFCommand.speedUp(message, getMsg, multiply)
|
2024-10-09 13:06:43 +08:00
|
|
|
}
|
2024-10-27 18:25:34 +08:00
|
|
|
if (command.contains("/黑白")) {
|
|
|
|
|
val msg = MessageChain.Builder()
|
|
|
|
|
getMsg.message.filter { it.type == ArrayMessageType.image || it.type == ArrayMessageType.mface }
|
|
|
|
|
.forEach {
|
2024-10-29 11:47:25 +08:00
|
|
|
val imgUrl = it.data.file!!
|
|
|
|
|
val decoder = GifDecoder()
|
|
|
|
|
val imageStream = withContext(Dispatchers.IO) { imgUrl.toURL().openStream() }
|
|
|
|
|
decoder.read(imageStream)
|
|
|
|
|
if (decoder.frameCount == 0) {
|
|
|
|
|
msg.addImage(imageStream.readBytes().toBufferedImage().toByteArray().encodeToBase64(), true)
|
|
|
|
|
} else {
|
|
|
|
|
val frames = (0 until decoder.frameCount).map { decoder.getFrame(it).toGrayscale() }
|
|
|
|
|
val base64 = decoder.makeGif(frames).encodeToBase64()
|
|
|
|
|
msg.addImage(base64, true)
|
|
|
|
|
}
|
2024-10-27 18:25:34 +08:00
|
|
|
}
|
|
|
|
|
message.reply(msg.build())
|
|
|
|
|
}
|
2024-09-24 00:48:23 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-27 23:31:01 +08:00
|
|
|
coroutineScope.launch {
|
2024-10-27 17:43:06 +08:00
|
|
|
if (message.images.isNotEmpty()) {
|
|
|
|
|
message.images.forEach {
|
|
|
|
|
val payload = NaiLongDetectPayload(it.file).toJson()
|
|
|
|
|
val result = Http.post<NaiLongDetectResponse>(configManager.naiLongApiUrl, payload)
|
|
|
|
|
logger.info("奶龙识别结果: ${result.result}")
|
|
|
|
|
if (result.result) {
|
|
|
|
|
message.reply("本群禁止发奶龙!")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-27 23:31:01 +08:00
|
|
|
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 ->
|
2024-10-06 20:48:50 +08:00
|
|
|
File("$ROOT_PATH/caches/images/$filename").outputStream().use { output ->
|
2024-09-27 23:31:01 +08:00
|
|
|
output.write(input.readBytes())
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-13 16:19:54 +08:00
|
|
|
}
|
2024-09-12 11:18:57 +08:00
|
|
|
}
|
2024-09-06 10:58:55 +08:00
|
|
|
}
|
2024-08-27 18:44:32 +08:00
|
|
|
}
|
2024-08-30 17:50:01 +08:00
|
|
|
|
2024-09-07 18:07:56 +08:00
|
|
|
override suspend fun onGroupMessageRevoke(message: GroupRevokeMessage) {
|
2024-09-18 13:06:23 +08:00
|
|
|
if (!configManager.enableAntiRevoke) return
|
2024-09-02 11:30:58 +08:00
|
|
|
val msg = MessageChain.Builder()
|
|
|
|
|
.addText("用户: ${message.userId} 被: ${message.operatorId} 撤回了一条消息")
|
|
|
|
|
.addNewLine()
|
|
|
|
|
.addText("使用/revoke ${message.messageId} 来获取被撤回的消息")
|
|
|
|
|
.build()
|
2024-10-25 14:25:43 +08:00
|
|
|
message.action.sendGroupMessage(message.groupId, msg)
|
2024-09-02 11:30:58 +08:00
|
|
|
}
|
|
|
|
|
|
2024-10-31 14:02:04 +08:00
|
|
|
override suspend fun onWebsocketErrorEvent(event: ErrorEvent) {
|
|
|
|
|
event.exception.printStackTrace()
|
2024-08-30 17:50:01 +08:00
|
|
|
}
|
2024-09-19 11:06:40 +08:00
|
|
|
|
2024-10-24 19:27:06 +08:00
|
|
|
override suspend fun onAddFriendRequest(event: AddFriendRequestEvent) {
|
2024-09-19 11:06:40 +08:00
|
|
|
event.approve()
|
|
|
|
|
}
|
2024-09-19 15:11:40 +08:00
|
|
|
|
|
|
|
|
override suspend fun onGroupFileUpload(event: FileEvent) {
|
2024-10-06 18:07:32 +08:00
|
|
|
event.saveTo("$ROOT_PATH/caches/")
|
2024-09-19 15:11:40 +08:00
|
|
|
}
|
2024-09-20 22:03:56 +08:00
|
|
|
|
2024-10-24 19:27:06 +08:00
|
|
|
override suspend fun onLeaveEvent(event: MemberLeaveEvent) {
|
2024-10-25 19:44:33 +08:00
|
|
|
val nickname = event.action.getGroupMemberInfo(event.groupId, event.userId).nickname
|
2024-09-20 22:03:56 +08:00
|
|
|
val msg = MessageChain.Builder()
|
2024-10-25 19:44:33 +08:00
|
|
|
.addText("有人坐飞船离开了本星系~(主动退出)")
|
2024-09-20 22:03:56 +08:00
|
|
|
.addNewLine()
|
2024-10-25 19:44:33 +08:00
|
|
|
.addText("QQ: $nickname(${event.userId})")
|
|
|
|
|
.addNewLine()
|
|
|
|
|
.addText("下次再见吧~~~")
|
|
|
|
|
.build()
|
|
|
|
|
event.action.sendGroupMessage(event.groupId, msg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override suspend fun onMemberKick(event: MemberKickEvent) {
|
|
|
|
|
val nickname = event.action.getGroupMemberInfo(event.groupId, event.userId).nickname
|
|
|
|
|
val msg = MessageChain.Builder()
|
|
|
|
|
.addText("有人坐飞船离开了本星系~(管理员踢出)")
|
|
|
|
|
.addNewLine()
|
|
|
|
|
.addText("QQ: $nickname(${event.userId})")
|
2024-09-20 22:03:56 +08:00
|
|
|
.addNewLine()
|
|
|
|
|
.addText("下次再见吧~~~")
|
|
|
|
|
.build()
|
2024-10-24 19:27:06 +08:00
|
|
|
event.action.sendGroupMessage(event.groupId, msg)
|
2024-09-20 22:03:56 +08:00
|
|
|
}
|
2024-09-28 12:37:18 +08:00
|
|
|
|
2024-10-11 13:47:26 +08:00
|
|
|
override suspend fun onGroupPoke(event: PokeEvent) {
|
|
|
|
|
if (event.targetId == configManager.selfId) {
|
|
|
|
|
val msg = MessageChain.Builder()
|
|
|
|
|
.addAt(event.userId)
|
2024-10-27 11:02:06 +08:00
|
|
|
.addText("你${event.pokeAction.first()}牛魔呢")
|
2024-10-11 13:47:26 +08:00
|
|
|
.build()
|
2024-10-27 11:02:06 +08:00
|
|
|
event.action.sendGroupMessage(event.groupId!!, msg)
|
2024-09-28 12:37:18 +08:00
|
|
|
}
|
|
|
|
|
}
|
2024-10-11 17:12:50 +08:00
|
|
|
|
2024-10-24 19:27:06 +08:00
|
|
|
override suspend fun onBeKicked(event: BeKickEvent) {
|
|
|
|
|
blackListManager.insertGroup(event.groupId, event.operator, event.time)
|
2024-10-25 14:25:43 +08:00
|
|
|
event.action.sendPrivateMessage(
|
2024-10-11 17:12:50 +08:00
|
|
|
configManager.noticeUser,
|
2024-10-24 19:27:06 +08:00
|
|
|
"被: ${event.groupId}踢出! 操作人: ${event.operator} 时间: ${event.time.convertToDate()} 已将其拉入黑名单!"
|
2024-10-11 17:12:50 +08:00
|
|
|
)
|
|
|
|
|
}
|
2024-08-29 14:36:06 +08:00
|
|
|
}
|
|
|
|
|
|
2024-08-30 17:50:01 +08:00
|
|
|
suspend fun main() {
|
2024-10-25 14:25:43 +08:00
|
|
|
val fancyBot = FancyBot()
|
|
|
|
|
val workType = configManager.wsType
|
|
|
|
|
val accessToken = configManager.accessToken
|
2024-10-25 19:44:33 +08:00
|
|
|
val instance = when (workType) {
|
|
|
|
|
WSType.Client -> ROneBotFactory.createClient(configManager.wsAddress, accessToken, fancyBot)
|
|
|
|
|
WSType.Server -> ROneBotFactory.createServer(configManager.wsPort, accessToken, fancyBot)
|
2024-10-25 14:25:43 +08:00
|
|
|
}
|
2024-10-25 19:44:33 +08:00
|
|
|
instance.addListeningGroups(*configManager.listeningGroups.toLongArray())
|
2024-10-25 14:25:43 +08:00
|
|
|
|
2024-08-30 17:50:01 +08:00
|
|
|
initDatabase()
|
2024-09-19 15:11:40 +08:00
|
|
|
initFilesDir()
|
2024-10-24 16:55:14 +08:00
|
|
|
initCommand()
|
2024-10-06 18:20:53 +08:00
|
|
|
initSetuIndex()
|
2024-10-15 18:58:12 +08:00
|
|
|
initItems()
|
2024-10-24 16:55:14 +08:00
|
|
|
initBackgroundTasks(instance)
|
2024-08-27 18:44:32 +08:00
|
|
|
}
|