From bd585919aec5b1a91fd0613a06645a501420a1ba Mon Sep 17 00:00:00 2001 From: RTAkland Date: Tue, 10 Sep 2024 17:44:07 +0800 Subject: [PATCH] feat: improve bv parser --- .../fancybot/commands/misc/BVParseCommand.kt | 170 ++++++++++++++++-- .../cn/rtast/fancybot/entity/bili/BVID.kt | 7 +- .../cn/rtast/fancybot/util/Resources.kt | 16 ++ src/main/resources/bili/22-coin.png | Bin 0 -> 16415 bytes src/main/resources/bili/coin.png | Bin 0 -> 3107 bytes src/main/resources/bili/favorite.png | Bin 0 -> 1847 bytes src/main/resources/bili/like.png | Bin 0 -> 1671 bytes src/main/resources/bili/reply.png | Bin 0 -> 2651 bytes src/main/resources/bili/share.png | Bin 0 -> 1885 bytes src/main/resources/bili/view.png | Bin 0 -> 2939 bytes 10 files changed, 174 insertions(+), 19 deletions(-) create mode 100644 src/main/kotlin/cn/rtast/fancybot/util/Resources.kt create mode 100644 src/main/resources/bili/22-coin.png create mode 100644 src/main/resources/bili/coin.png create mode 100644 src/main/resources/bili/favorite.png create mode 100644 src/main/resources/bili/like.png create mode 100644 src/main/resources/bili/reply.png create mode 100644 src/main/resources/bili/share.png create mode 100644 src/main/resources/bili/view.png diff --git a/src/main/kotlin/cn/rtast/fancybot/commands/misc/BVParseCommand.kt b/src/main/kotlin/cn/rtast/fancybot/commands/misc/BVParseCommand.kt index 8d5310c..c0d8d9a 100644 --- a/src/main/kotlin/cn/rtast/fancybot/commands/misc/BVParseCommand.kt +++ b/src/main/kotlin/cn/rtast/fancybot/commands/misc/BVParseCommand.kt @@ -9,35 +9,171 @@ package cn.rtast.fancybot.commands.misc import cn.rtast.fancybot.entity.bili.BVID import cn.rtast.fancybot.util.Http +import cn.rtast.fancybot.util.Resources +import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.OBMessage +import java.awt.Color +import java.awt.Font +import java.awt.Graphics2D +import java.awt.geom.RoundRectangle2D +import java.awt.image.BufferedImage +import java.io.ByteArrayOutputStream +import java.net.URI +import javax.imageio.ImageIO object BVParseCommand { private const val CID_URL = "https://api.bilibili.com/x/web-interface/view" + private const val CANVAS_WIDTH = 1000 + private const val CANVAS_HEIGHT = 600 + private val titleFont = Font("Serif", Font.ITALIC, 40).deriveFont(Font.ITALIC) + private val numberFont = Font("Serif", Font.ITALIC, 25).deriveFont(Font.ITALIC) + private val twoTwoLogo = ImageIO.read(Resources.loadFromResources("bili/22-coin.png")) + private val likeIcon = ImageIO.read(Resources.loadFromResources("bili/like.png")) + private val coinIcon = ImageIO.read(Resources.loadFromResources("bili/coin.png")) + private val viewIcon = ImageIO.read(Resources.loadFromResources("bili/view.png")) + private val shareIcon = ImageIO.read(Resources.loadFromResources("bili/share.png")) + private val favoriteIcon = ImageIO.read(Resources.loadFromResources("bili/favorite.png")) + private val replyIcon = ImageIO.read(Resources.loadFromResources("bili/reply.png")) + + private fun Int.formatNumber(): String { + return when { + this >= 100000000 -> "${this / 100000000}亿" + this >= 10000 -> { + val wan = this / 10000 + val remainder = this % 10000 + if (remainder == 0) "${wan}万" else "${wan}万${remainder}" + } + + this >= 1000 -> { + val remainder = this % 1000 + if (remainder == 0) "${this / 1000}千" else "${this / 1000}千零${remainder}" + } + + else -> this.toString() + } + } + + private fun drawImage( + image: BufferedImage, + g2d: Graphics2D, + x: Int, + y: Int, + maxWidth: Double, + maxHeight: Double, + clip: Boolean + ) { + val originalWidth = image.getWidth(null) + 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) { + g2d.clip = RoundRectangle2D.Float( + x.toFloat(), + y.toFloat(), + targetWidth.toFloat(), + targetHeight.toFloat(), + 30.toFloat(), + 30.toFloat() + ) + } + g2d.drawImage(image, x, y, targetWidth, targetHeight, null) + } + + private fun createResponseImage( + title: String, + author: String, + authorFace: String, + picUrl: String, + reply: String, + view: String, + coin: String, + share: String, + like: String, + favorite: String + ): String { + val coverImage = ImageIO.read(URI(picUrl).toURL()) + val faceImage = ImageIO.read(URI(authorFace).toURL()) + val backgroundImage = BufferedImage(CANVAS_WIDTH, CANVAS_HEIGHT, BufferedImage.TYPE_INT_RGB) + val g2d = backgroundImage.createGraphics() + g2d.color = Color(43, 43, 43) + g2d.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT) + // draw rect + g2d.color = Color(102, 102, 102) + g2d.fillRect(0, 0, CANVAS_WIDTH, 120) + g2d.color = Color.WHITE + // draw numbers + g2d.font = numberFont + g2d.drawString(like, 110, 200) + g2d.drawString(coin, 110, 290) + g2d.drawString(view, 110, 380) + g2d.drawString(favorite, 300, 380) + g2d.drawString(reply, 300, 290) + g2d.drawString(share, 300, 200) + // draw video title + val maxWidth = 500 + val fontMetrics = g2d.fontMetrics + val textWidth = fontMetrics.stringWidth(title) + val truncatedText = if (textWidth > maxWidth) { + val ellipsisWidth = fontMetrics.stringWidth("...") + val width = maxWidth - ellipsisWidth + var endIndex = title.length + while (fontMetrics.stringWidth(title.substring(0, endIndex)) > width && endIndex > 0) { + endIndex-- + } + title.substring(0, endIndex) + "..." + } else title + g2d.font = titleFont + g2d.drawString(truncatedText, 20, 70) + // draw author name + g2d.drawString(author, 40, 580) + // draw icons + this.drawImage(favoriteIcon, g2d, 230, 340, 50.0, 50.0, false) + this.drawImage(replyIcon, g2d, 230, 250, 50.0, 50.0, false) + this.drawImage(shareIcon, g2d, 230, 160, 50.0, 50.0, false) + this.drawImage(viewIcon, g2d, 40, 340, 50.0, 50.0, false) + this.drawImage(coinIcon, g2d, 40, 250, 50.0, 50.0, false) + this.drawImage(likeIcon, g2d, 40, 160, 50.0, 50.0, false) + // draw 22 logo + this.drawImage(twoTwoLogo, g2d, 800, 450, 90.0, 160.0, false) + // draw author face + this.drawImage(faceImage, g2d, 40, 480, 60.0, 60.0, true) + // draw cover image + this.drawImage(coverImage, g2d, 470, 140, 600.0, 300.0, true) + g2d.dispose() + val byteArrayOutputStream = ByteArrayOutputStream() + ImageIO.write(backgroundImage, "png", byteArrayOutputStream) + val imageBytes = byteArrayOutputStream.toByteArray() + return imageBytes.encodeToBase64() + } suspend fun parse(listener: OBMessage, message: GroupMessage) { - val bvid = if (message.rawMessage.startsWith("BV")) { - message.rawMessage - } else { - message.rawMessage.split("/")[4] - } - val cidResponse = Http.get( - CID_URL, mapOf("bvid" to bvid) + val bvid = if (message.rawMessage.startsWith("BV")) message.rawMessage + else message.rawMessage.split("/")[4] + val videoInfo = Http.get(CID_URL, mapOf("bvid" to bvid)) + val authorFace = videoInfo.data.owner.face + val title = videoInfo.data.title + val author = videoInfo.data.owner.name + val coverPicUrl = videoInfo.data.pic + val view = videoInfo.data.stat.view.formatNumber() + val share = videoInfo.data.stat.share.formatNumber() + val like = videoInfo.data.stat.like.formatNumber() + val favorite = videoInfo.data.stat.favorite.formatNumber() + val coin = videoInfo.data.stat.coin.formatNumber() + val reply = videoInfo.data.stat.reply.formatNumber() + val image = this.createResponseImage( + title, author, authorFace, + coverPicUrl, reply, view, coin, + share, like, favorite ) val msg = MessageChain.Builder() .addReply(message.messageId) - .addImage(cidResponse.data.pic) - .addText("标题: ${cidResponse.data.title}") - .addNewLine() - .addText("作者: ${cidResponse.data.owner.name}") - .addNewLine() - .addText("点赞: ${cidResponse.data.stat.like} | 观看: ${cidResponse.data.stat.view}") - .addNewLine() - .addText("收藏: ${cidResponse.data.stat.favorite} | 投币: ${cidResponse.data.stat.coin}") - .addNewLine() - .addText("https://www.bilibili.com/video/$bvid") + .addImage(image, true) .build() listener.sendGroupMessage(message.groupId, msg) } diff --git a/src/main/kotlin/cn/rtast/fancybot/entity/bili/BVID.kt b/src/main/kotlin/cn/rtast/fancybot/entity/bili/BVID.kt index 44dce7f..92f6cdc 100644 --- a/src/main/kotlin/cn/rtast/fancybot/entity/bili/BVID.kt +++ b/src/main/kotlin/cn/rtast/fancybot/entity/bili/BVID.kt @@ -19,13 +19,16 @@ data class BVID( ) data class Owner( - val name: String + val name: String, + val face: String, ) data class Stat( - val view: Long, + val view: Int, val favorite: Int, val coin: Int, val like: Int, + val reply: Int, + val share: Int, ) } \ No newline at end of file diff --git a/src/main/kotlin/cn/rtast/fancybot/util/Resources.kt b/src/main/kotlin/cn/rtast/fancybot/util/Resources.kt new file mode 100644 index 0000000..a4c2f97 --- /dev/null +++ b/src/main/kotlin/cn/rtast/fancybot/util/Resources.kt @@ -0,0 +1,16 @@ +/* + * Copyright © 2024 RTAkland + * Author: RTAkland + * Date: 2024/9/10 + */ + + +package cn.rtast.fancybot.util + +import java.io.InputStream + +object Resources { + fun loadFromResources(filename: String): InputStream { + return this::class.java.classLoader.getResourceAsStream(filename) + } +} diff --git a/src/main/resources/bili/22-coin.png b/src/main/resources/bili/22-coin.png new file mode 100644 index 0000000000000000000000000000000000000000..0f414f6a437e0fc79e71ff235d4e07b596e68ee1 GIT binary patch literal 16415 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/bili/coin.png b/src/main/resources/bili/coin.png new file mode 100644 index 0000000000000000000000000000000000000000..18acb9edbfcef65acfe59635371535c1be886af5 GIT binary patch literal 3107 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/bili/favorite.png b/src/main/resources/bili/favorite.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5af176f5d41f64dd73364f251364a3ac7b8d3a GIT binary patch literal 1847 zcmV-72gvw|P)Px*@kvBMRCr$Pok3O`IS__R4F^b=*^je;_i~DulLVHKLl6!TSVB&MbBcKn7U}F~ zm^lD;<*A**x+IlUDmKZYrIxBbRsE7$vH|@o+5)EN-fQPU0Vo^-1wa8P+yaGn zUn775P`CvO@4iL=1)y*X6yAM}0180i7AU;?8UYl5vMliD?bCFzfGJe?7a&Y+?-5LG z5WZCv%>KDJo|R;gq9VZCo2Lf@OQ-MrGkCv%`St%7@9PpkC<1_H)FV6$cPQG3aQ*M6 zll$Ri@_bS}0B>&po>X}FeT;h+=H;FANFW}7L1BL<9at~S{8Taoq5(Mi^7I)DT#Xt1 zuVoOfpFbUcCe@K}VX**ELjR_}B&Pzg0C*Ywzeq5M=TZfsTmWt!zXOL8T00�OaG> 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