feat: add jue command
This commit is contained in:
6 files changed
+129
-21
No files matched your search
@@ -27,6 +27,7 @@ import cn.rtast.fancybot.commands.misc.AntiRevokeCommand
|
|||||||
import cn.rtast.fancybot.commands.misc.CompilerCommand
|
import cn.rtast.fancybot.commands.misc.CompilerCommand
|
||||||
import cn.rtast.fancybot.commands.misc.FKXQSCommand
|
import cn.rtast.fancybot.commands.misc.FKXQSCommand
|
||||||
import cn.rtast.fancybot.commands.misc.HitokotoCommand
|
import cn.rtast.fancybot.commands.misc.HitokotoCommand
|
||||||
|
import cn.rtast.fancybot.commands.misc.JueCommand
|
||||||
import cn.rtast.fancybot.commands.misc.LikeMeCommand
|
import cn.rtast.fancybot.commands.misc.LikeMeCommand
|
||||||
import cn.rtast.fancybot.commands.misc.RUACommand
|
import cn.rtast.fancybot.commands.misc.RUACommand
|
||||||
import cn.rtast.fancybot.commands.misc.RemakeCommand
|
import cn.rtast.fancybot.commands.misc.RemakeCommand
|
||||||
@@ -63,7 +64,6 @@ import cn.rtast.rob.entity.FileEvent
|
|||||||
import cn.rtast.rob.entity.GetMessage
|
import cn.rtast.rob.entity.GetMessage
|
||||||
import cn.rtast.rob.entity.GroupMessage
|
import cn.rtast.rob.entity.GroupMessage
|
||||||
import cn.rtast.rob.entity.GroupRevokeMessage
|
import cn.rtast.rob.entity.GroupRevokeMessage
|
||||||
import cn.rtast.rob.entity.PrivateMessage
|
|
||||||
import cn.rtast.rob.enums.ArrayMessageType
|
import cn.rtast.rob.enums.ArrayMessageType
|
||||||
import cn.rtast.rob.util.ob.MessageChain
|
import cn.rtast.rob.util.ob.MessageChain
|
||||||
import cn.rtast.rob.util.ob.OneBotListener
|
import cn.rtast.rob.util.ob.OneBotListener
|
||||||
@@ -86,8 +86,10 @@ class FancyBot : OneBotListener {
|
|||||||
val messageId = message.messageId
|
val messageId = message.messageId
|
||||||
println("$sender($senderId: $groupId >>> $messageId): $msg")
|
println("$sender($senderId: $groupId >>> $messageId): $msg")
|
||||||
|
|
||||||
|
if (message.rawMessage.toList().any { it in arrayListOf<Char>('*', '-', '/', '+', '=') }) {
|
||||||
val calculateResult = CalculateCommand.parse(message.rawMessage)
|
val calculateResult = CalculateCommand.parse(message.rawMessage)
|
||||||
calculateResult?.let { message.reply(calculateResult) }
|
calculateResult?.let { message.reply(calculateResult) }
|
||||||
|
}
|
||||||
|
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
message.message.forEach {
|
message.message.forEach {
|
||||||
@@ -220,7 +222,8 @@ val commands = listOf(
|
|||||||
MusicPlayUrlCommand(), DomainPriceCommand(),
|
MusicPlayUrlCommand(), DomainPriceCommand(),
|
||||||
SendMailCommand(), ZiBiCommand(),
|
SendMailCommand(), ZiBiCommand(),
|
||||||
UnsetZiBiCommand(), WikipediaCommand(),
|
UnsetZiBiCommand(), WikipediaCommand(),
|
||||||
AsciiArtCommand(), StatusCommand()
|
AsciiArtCommand(), StatusCommand(),
|
||||||
|
JueCommand()
|
||||||
)
|
)
|
||||||
|
|
||||||
val START_UP_TIME = Instant.now().epochSecond
|
val START_UP_TIME = Instant.now().epochSecond
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2024 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2024/9/21
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.fancybot.commands.misc
|
||||||
|
|
||||||
|
import cn.rtast.fancybot.util.Resources
|
||||||
|
import cn.rtast.fancybot.util.drawCircularImage
|
||||||
|
import cn.rtast.fancybot.util.makeGif
|
||||||
|
import cn.rtast.fancybot.util.str.encodeToBase64
|
||||||
|
import cn.rtast.fancybot.util.toBufferedImage
|
||||||
|
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 com.madgag.gif.fmsware.GifDecoder
|
||||||
|
import java.awt.image.BufferedImage
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
|
class JueCommand : BaseCommand() {
|
||||||
|
override val commandNames = listOf("撅")
|
||||||
|
|
||||||
|
private val avatarUrl = "https://q1.qlogo.cn/g?b=qq&nk=#{}&s=640"
|
||||||
|
|
||||||
|
private fun createJueGIF(source: String, target: String): String {
|
||||||
|
val baseGIF = Resources.loadFromResources("misc/jue.gif")
|
||||||
|
val sourceAvatar = URI(avatarUrl.replace("#{}", source)).toURL().readBytes().toBufferedImage()
|
||||||
|
val targetAvatar = URI(avatarUrl.replace("#{}", target)).toURL().readBytes().toBufferedImage()
|
||||||
|
val decoder = GifDecoder()
|
||||||
|
decoder.read(baseGIF)
|
||||||
|
val frames = mutableListOf<BufferedImage>()
|
||||||
|
|
||||||
|
fun drawFrame(index: Int, sourceX: Int, sourceY: Int, targetX: Int, targetY: Int) {
|
||||||
|
val frame = decoder.getFrame(index)
|
||||||
|
val g2d = frame.createGraphics()
|
||||||
|
g2d.drawCircularImage(sourceAvatar, sourceX, sourceY, 126.0, 126.0)
|
||||||
|
g2d.drawCircularImage(targetAvatar, targetX, targetY, 126.0, 126.0)
|
||||||
|
g2d.dispose()
|
||||||
|
frames.add(frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
(0 until decoder.frameCount).forEach {
|
||||||
|
when (it) {
|
||||||
|
0 -> drawFrame(it, 115, -12, 3, 175)
|
||||||
|
1 -> drawFrame(it, 109, 2, 10, 170)
|
||||||
|
2 -> drawFrame(it, 130, -13, 5, 154)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val gifBytes = decoder.makeGif(frames)
|
||||||
|
val gif = gifBytes.encodeToBase64()
|
||||||
|
return gif
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
|
||||||
|
val target = message.message.find { it.type == ArrayMessageType.at }?.data?.qq.toString()
|
||||||
|
val source = message.sender.userId.toString()
|
||||||
|
val gif = this.createJueGIF(source, target)
|
||||||
|
val msg = MessageChain.Builder().addImage(gif, true).build()
|
||||||
|
listener.sendGroupMessage(message.groupId, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
package cn.rtast.fancybot.commands.parse
|
package cn.rtast.fancybot.commands.parse
|
||||||
|
|
||||||
|
import cn.rtast.fancybot.util.makeGif
|
||||||
import cn.rtast.fancybot.util.str.encodeToBase64
|
import cn.rtast.fancybot.util.str.encodeToBase64
|
||||||
import cn.rtast.rob.entity.GetMessage
|
import cn.rtast.rob.entity.GetMessage
|
||||||
import cn.rtast.rob.enums.ArrayMessageType
|
import cn.rtast.rob.enums.ArrayMessageType
|
||||||
@@ -24,16 +25,7 @@ object ReverseGIFCommand {
|
|||||||
val decoder = GifDecoder()
|
val decoder = GifDecoder()
|
||||||
decoder.read(gifStream)
|
decoder.read(gifStream)
|
||||||
val frames = (0 until decoder.frameCount).map { decoder.getFrame(it) }.reversed()
|
val frames = (0 until decoder.frameCount).map { decoder.getFrame(it) }.reversed()
|
||||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
val gifBytes = decoder.makeGif(frames)
|
||||||
val encoder = AnimatedGifEncoder()
|
|
||||||
encoder.start(byteArrayOutputStream)
|
|
||||||
encoder.setRepeat(0)
|
|
||||||
for (i in frames.indices) {
|
|
||||||
encoder.setDelay(decoder.getDelay(decoder.frameCount - i - 1))
|
|
||||||
encoder.addFrame(frames[i])
|
|
||||||
}
|
|
||||||
encoder.finish()
|
|
||||||
val gifBytes = byteArrayOutputStream.toByteArray()
|
|
||||||
return gifBytes.encodeToBase64()
|
return gifBytes.encodeToBase64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2024 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2024/9/21
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.fancybot.util
|
||||||
|
|
||||||
|
import com.madgag.gif.fmsware.AnimatedGifEncoder
|
||||||
|
import com.madgag.gif.fmsware.GifDecoder
|
||||||
|
import java.awt.image.BufferedImage
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
|
||||||
|
fun GifDecoder.makeGif(frames: List<BufferedImage>): ByteArray {
|
||||||
|
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||||
|
val encoder = AnimatedGifEncoder()
|
||||||
|
encoder.start(byteArrayOutputStream)
|
||||||
|
encoder.setRepeat(0)
|
||||||
|
for (i in frames.indices) {
|
||||||
|
encoder.setDelay(this.getDelay(this.frameCount - i - 1))
|
||||||
|
encoder.addFrame(frames[i])
|
||||||
|
}
|
||||||
|
encoder.finish()
|
||||||
|
return byteArrayOutputStream.toByteArray()
|
||||||
|
}
|
||||||
@@ -9,12 +9,25 @@ package cn.rtast.fancybot.util
|
|||||||
|
|
||||||
import cn.rtast.fancybot.configManager
|
import cn.rtast.fancybot.configManager
|
||||||
import java.awt.Graphics2D
|
import java.awt.Graphics2D
|
||||||
|
import java.awt.geom.Ellipse2D
|
||||||
import java.awt.geom.RoundRectangle2D
|
import java.awt.geom.RoundRectangle2D
|
||||||
import java.awt.image.BufferedImage
|
import java.awt.image.BufferedImage
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import javax.imageio.ImageIO
|
import javax.imageio.ImageIO
|
||||||
|
|
||||||
|
|
||||||
|
private fun BufferedImage.getScaledWidth(maxWidth: Double, maxHeight: Double): Pair<Int, Int> {
|
||||||
|
val originalWidth = this.getWidth(null)
|
||||||
|
val originalHeight = this.getHeight(null)
|
||||||
|
val widthScale = maxWidth / originalWidth
|
||||||
|
val heightScale = maxHeight / originalHeight
|
||||||
|
val scale = minOf(widthScale, heightScale)
|
||||||
|
val targetWidth = (originalWidth * scale).toInt()
|
||||||
|
val targetHeight = (originalHeight * scale).toInt()
|
||||||
|
return targetWidth to targetHeight
|
||||||
|
}
|
||||||
|
|
||||||
fun Graphics2D.drawCustomImage(
|
fun Graphics2D.drawCustomImage(
|
||||||
image: BufferedImage,
|
image: BufferedImage,
|
||||||
x: Int,
|
x: Int,
|
||||||
@@ -23,13 +36,7 @@ fun Graphics2D.drawCustomImage(
|
|||||||
maxHeight: Double,
|
maxHeight: Double,
|
||||||
clip: Boolean = false
|
clip: Boolean = false
|
||||||
) {
|
) {
|
||||||
val originalWidth = image.getWidth(null)
|
val (targetWidth, targetHeight) = image.getScaledWidth(maxWidth, maxHeight)
|
||||||
val originalHeight = image.getHeight(null)
|
|
||||||
val widthScale = maxWidth / originalWidth
|
|
||||||
val heightScale = maxHeight / originalHeight
|
|
||||||
val scale = minOf(widthScale, heightScale)
|
|
||||||
val targetWidth = (originalWidth * scale).toInt()
|
|
||||||
val targetHeight = (originalHeight * scale).toInt()
|
|
||||||
if (clip) {
|
if (clip) {
|
||||||
this.clip = RoundRectangle2D.Float(
|
this.clip = RoundRectangle2D.Float(
|
||||||
x.toFloat(),
|
x.toFloat(),
|
||||||
@@ -41,6 +48,21 @@ fun Graphics2D.drawCustomImage(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
this.drawImage(image, x, y, targetWidth, targetHeight, null)
|
this.drawImage(image, x, y, targetWidth, targetHeight, null)
|
||||||
|
this.clip = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Graphics2D.drawCircularImage(
|
||||||
|
image: BufferedImage,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
maxWidth: Double,
|
||||||
|
maxHeight: Double,
|
||||||
|
) {
|
||||||
|
val (targetWidth, targetHeight) = image.getScaledWidth(maxWidth, maxHeight)
|
||||||
|
val circle = Ellipse2D.Double(x.toDouble(), y.toDouble(), targetWidth.toDouble(), targetHeight.toDouble());
|
||||||
|
this.clip = circle
|
||||||
|
this.drawImage(image, x, y, targetWidth, targetHeight, null)
|
||||||
|
this.clip = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BufferedImage.scaleImage(size: Pair<Int, Int>): BufferedImage {
|
fun BufferedImage.scaleImage(size: Pair<Int, Int>): BufferedImage {
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
Reference in New Issue
Block a user