diff --git a/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt b/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt index 6d9cc50..c479168 100644 --- a/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt +++ b/src/main/kotlin/cn/rtast/fancybot/FancyBot.kt @@ -76,19 +76,26 @@ class FancyBot : OneBotListener { calculateResult?.let { message.reply(calculateResult) } } - if (message.message.any { it.type == ArrayMessageType.reply }) { // Image url parse + if (message.message.any { it.type == ArrayMessageType.reply }) { val command = message.message.reversed().find { it.type == ArrayMessageType.text }!!.data.text!! val replyId = message.message.find { it.type == ArrayMessageType.reply }!!.data.id!! + val getMsg = this.getMessage(replyId.toString().toLong()) + if (command.contains("/ascii") || command.contains("/asc")) { + // 使用回复消息的方式直接对一个图片进行生成Ascii art的操作 + val url = AsciiArtCommand.getImageUrl(getMsg) + val image = AsciiArtCommand.generateAsciiArt(url) + message.reply(image) + } if (command.contains("图来") || command.contains("图链")) { - val getMsg = this.getMessage(replyId.toString().toLong()) + // 获取一个或多个图片的链接, 并且生成一个或多个短链接 ImageURLCommand.callback(message, getMsg) } if (command.contains("reaction")) { - val getMsg = this.getMessage(replyId.toString().toLong()) + // 使用reaction刷屏回应一条消息 ReactionCommand.reaction(this, message, getMsg.messageId) } if (command.contains("图床")) { - val getMsg = this.getMessage(replyId.toString().toLong()) + // 将一个图片上传到图床 val imagesUrl = ImageURLCommand.getImageUrl(getMsg) if (imagesUrl.isEmpty()) { message.reply("这个消息里没有图片呢!") diff --git a/src/main/kotlin/cn/rtast/fancybot/commands/parse/AsciiArtCommand.kt b/src/main/kotlin/cn/rtast/fancybot/commands/parse/AsciiArtCommand.kt index a50e4d2..a65b789 100644 --- a/src/main/kotlin/cn/rtast/fancybot/commands/parse/AsciiArtCommand.kt +++ b/src/main/kotlin/cn/rtast/fancybot/commands/parse/AsciiArtCommand.kt @@ -15,11 +15,13 @@ import cn.rtast.fancybot.util.misc.ImageBed import cn.rtast.fancybot.util.misc.makeGif import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.fancybot.util.misc.toByteArray +import cn.rtast.rob.entity.GetMessage import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.enums.ArrayMessageType import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.OneBotListener +import cn.rtast.rob.util.ob.asMessageChain import com.madgag.gif.fmsware.GifDecoder import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -91,62 +93,89 @@ class AsciiArtCommand : BaseCommand() { return img } + suspend fun generateAsciiArt(url: String): MessageChain { + val gifStream = withContext(Dispatchers.IO) { URI(url).toURL().openStream() } + val decoder = GifDecoder() + try { + decoder.read(gifStream) + if (decoder.frameCount == 0) { + val bufferedImage = withContext(Dispatchers.IO) { ImageIO.read(URI(url).toURL()) } + val imageBytes = bufferedImage.convertToAscii() + .saveAsciiArtToImage(bufferedImage.width, bufferedImage.height) + .toByteArray() + val imageBedUrl = ImageBed.upload(imageBytes, imageBytes.getFileType()) + val msg = MessageChain.Builder() + .addImage(imageBytes.encodeToBase64(), true) + .addText(imageBedUrl) + .build() + return msg + } else { + logger.info("制作GIF Ascii art中, 总帧数: ${decoder.frameCount}") + val frames = (0 until decoder.frameCount).map { decoder.getFrame(it) } + val asciiFrames = mutableListOf() + val width = frames.first().width + val height = frames.first().height + frames.forEachIndexed { index, item -> + asciiFrames.add(item.convertToAscii().saveAsciiArtToImage(width, height)) + logger.info("帧:${index}处理完成") + } + logger.info("合成GIF中...") + val gifBytes = decoder.makeGif(asciiFrames) + val imageBedUrl = ImageBed.upload(gifBytes, gifBytes.getFileType()).makeShortLink() + logger.info("合并完成") + val gifBase64 = gifBytes.encodeToBase64() + logger.info("处理后的图片大小: ${(gifBytes.size / 1024 / 1024).toInt()}MB") + val msg = MessageChain.Builder() + .addImage(gifBase64, true) + .addText(imageBedUrl) + .build() + return msg + } + } catch (_: OutOfMemoryError) { + return listOf("GIF处理失败: 内存溢出").asMessageChain() + logger.info("GIF处理失败: 内存溢出") + } catch (e: Exception) { + return listOf("处理GIF失败: ${e.message}").asMessageChain() + logger.info("gif处理失败: ${e.message}") + } + } + suspend fun callback(message: GroupMessage) { if (message.sender.userId !in waitingList) return waitingList.removeIf { it == message.sender.userId } if (message.message.any { it.type == ArrayMessageType.image } || message.message.any { it.type == ArrayMessageType.mface }) { - val url = if (message.message.any { it.type == ArrayMessageType.image }) - message.message.find { it.type == ArrayMessageType.image }!!.data.file!! - else message.message.find { it.type == ArrayMessageType.mface }!!.data.url!! - val gifStream = withContext(Dispatchers.IO) { URI(url).toURL().openStream() } - val decoder = GifDecoder() - try { - decoder.read(gifStream) - if (decoder.frameCount == 0) { - val bufferedImage = withContext(Dispatchers.IO) { ImageIO.read(URI(url).toURL()) } - val imageBytes = bufferedImage.convertToAscii() - .saveAsciiArtToImage(bufferedImage.width, bufferedImage.height) - .toByteArray() - val imageBedUrl = ImageBed.upload(imageBytes, imageBytes.getFileType()) - val msg = MessageChain.Builder() - .addImage(imageBytes.encodeToBase64(), true) - .addText(imageBedUrl) - .build() - message.reply(msg) - } else { - logger.info("制作GIF Ascii art中, 总帧数: ${decoder.frameCount}") - val frames = (0 until decoder.frameCount).map { decoder.getFrame(it) } - val asciiFrames = mutableListOf() - val width = frames.first().width - val height = frames.first().height - frames.forEachIndexed { index, item -> - asciiFrames.add(item.convertToAscii().saveAsciiArtToImage(width, height)) - logger.info("帧:${index}处理完成") - } - logger.info("合成GIF中...") - val gifBytes = decoder.makeGif(asciiFrames) - val imageBedUrl = ImageBed.upload(gifBytes, gifBytes.getFileType()).makeShortLink() - logger.info("合并完成") - val gifBase64 = gifBytes.encodeToBase64() - logger.info("处理后的图片大小: ${(gifBytes.size / 1024 / 1024).toInt()}MB") - val msg = MessageChain.Builder() - .addImage(gifBase64, true) - .addText(imageBedUrl) - .build() - message.reply(msg) - } - } catch (_: OutOfMemoryError) { - message.reply("GIF处理失败: 内存溢出") - logger.info("GIF处理失败: 内存溢出") - } catch (e: Exception) { - message.reply("处理GIF失败: ${e.message}") - logger.info("gif处理失败: ${e.message}") - } + val url = this.getImageUrl(message) + val msg = this.generateAsciiArt(url) + message.reply(msg) } else { message.reply("回复错误已取消本次操作") } } + + fun getImageUrl(groupMessage: GroupMessage): String { + return getImageUrlFromUnified(toUnifiedMessage(groupMessage)) + } + + fun getImageUrl(getMessageData: GetMessage.Data): String { + return getImageUrlFromUnified(toUnifiedMessage(getMessageData)) + } + + private fun getImageUrlFromUnified(messages: List): String { + return if (messages.any { it.type == ArrayMessageType.image }) + messages.find { it.type == ArrayMessageType.image }!!.file!! + else messages.find { it.type == ArrayMessageType.mface }!!.url!! + } + + private fun toUnifiedMessage(groupMessage: GroupMessage): List { + return groupMessage.message.map { UnifiedMessage(it.type, it.data.file, it.data.url) } + } + + private fun toUnifiedMessage(getMessageData: GetMessage.Data): List { + return getMessageData.message.map { UnifiedMessage(it.type, it.data.file, it.data.url) } + } + + private data class UnifiedMessage(val type: ArrayMessageType, val file: String?, val url: String?) } override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List) {