feat: add view count on bv parse card

This commit is contained in:
2024-09-14 22:00:18 +08:00
parent eb65a89425
commit 78487514ce
6 files changed
+115 -58

No files matched your search

@@ -83,7 +83,7 @@ class FancyBot : OBMessage {
}
BVParseCommand.getShortUrlBVID(shortUrl)
} else {
message.rawMessage.split("/")[4]
message.rawMessage.split("?").first().split("/").filter { it.isNotEmpty() && it.isNotBlank() }.last()
}
BVParseCommand.parse(this, bvid, message)
}
@@ -7,8 +7,10 @@
package cn.rtast.fancybot.commands.parse
import cn.rtast.fancybot.entity.bili.BVID
import cn.rtast.fancybot.entity.bili.ShortUrl
import cn.rtast.fancybot.entity.bili.UserStat
import cn.rtast.fancybot.entity.bili.VideoStat
import cn.rtast.fancybot.entity.bili.ViewCount
import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.Resources
import cn.rtast.fancybot.util.drawCustomImage
@@ -30,8 +32,10 @@ import javax.imageio.ImageIO
object BVParseCommand {
private const val CID_URL = "https://api.bilibili.com/x/web-interface/view"
private const val VIDEO_STAT_URL = "https://api.bilibili.com/x/web-interface/view"
private const val USER_STAT_URL = "https://api.bilibili.com/x/relation/stat"
private const val SHORT_URL_API_URL = "https://api.bilibili.com/x/share/click"
private const val VIEW_COUNT_URL = "https://api.bilibili.com/x/player/online/total"
private const val CANVAS_WIDTH = 1000
private const val CANVAS_HEIGHT = 600
private val titleFont = Font("Serif", Font.ITALIC, 40)
@@ -46,12 +50,32 @@ object BVParseCommand {
private val tempOkHttpClient = OkHttpClient()
fun getShortUrlBVID(shortUrl: String): String {
val request = Request.Builder().url(shortUrl.split(" ").last()).build()
val redirectedUrl = tempOkHttpClient.newCall(request).execute()
redirectedUrl.use {
return it.request.url.toString().split("/")[4].split("?").first()
private fun generateShortUrl(bvid: String, oid: Long): String {
val result = Http.post<ShortUrl>(
SHORT_URL_API_URL, mapOf(
"buvid" to bvid,
"build" to 6114514,
"platform" to "unix",
"share_channel" to "COPY",
"share_mode" to 2,
"share_id" to "main.ugc-video-detail.0.0.pv",
"oid" to oid
)
)
return result.data.content.split(" ").last()
}
private fun getViewCount(bvid: String, cid: Long): String {
return Http.get<ViewCount>(
VIEW_COUNT_URL, mapOf(
"bvid" to bvid,
"cid" to cid
)
).data.total
}
private fun getVideoStat(bvid: String): VideoStat {
return Http.get<VideoStat>(VIDEO_STAT_URL, mapOf("bvid" to bvid))
}
private fun createResponseImage(
@@ -66,6 +90,7 @@ object BVParseCommand {
like: String,
favorite: String,
fans: Int,
viewCount: String,
): String {
val coverImage = ImageIO.read(URI(picUrl).toURL())
val faceImage = ImageIO.read(URI(authorFace).toURL())
@@ -104,6 +129,8 @@ object BVParseCommand {
// draw fans count
g2d.font = numberFont
g2d.drawString(fans.formatNumber() + "粉丝", 120, 520)
// draw viewing count
g2d.drawString("${viewCount}人正在观看", 40, 460)
// draw author face
g2d.drawCustomImage(faceImage, 40, 480, 60.0, 60.0, true)
// draw cover image
@@ -112,8 +139,18 @@ object BVParseCommand {
return canvas.toByteArray().encodeToBase64()
}
fun getShortUrlBVID(shortUrl: String): String {
val request = Request.Builder().url(shortUrl.split(" ").last()).build()
val redirectedUrl = tempOkHttpClient.newCall(request).execute()
redirectedUrl.use {
return it.request.url.toString().split("/")[4].split("?").first()
}
}
suspend fun parse(listener: OBMessage, bvid: String, message: GroupMessage) {
val videoInfo = Http.get<BVID>(CID_URL, mapOf("bvid" to bvid))
val videoInfo = this.getVideoStat(bvid)
val viewCount = this.getViewCount(bvid, videoInfo.data.cid)
val shortUrl = this.generateShortUrl(bvid, videoInfo.data.aid)
val fans = Http.get<UserStat>(USER_STAT_URL, mapOf("vmid" to videoInfo.data.owner.mid)).data.follower
val authorFace = videoInfo.data.owner.face
val title = videoInfo.data.title
@@ -128,11 +165,12 @@ object BVParseCommand {
val image = this.createResponseImage(
title, author, authorFace,
coverPicUrl, reply, view, coin,
share, like, favorite, fans
share, like, favorite, fans, viewCount
)
val msg = MessageChain.Builder()
.addReply(message.messageId)
.addImage(image, true)
.addText(shortUrl)
.build()
listener.sendGroupMessage(message.groupId, msg)
}
@@ -0,0 +1,16 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/14
*/
package cn.rtast.fancybot.entity.bili
data class ShortUrl(
val data: Data
) {
data class Data(
val content: String
)
}
@@ -7,10 +7,11 @@
package cn.rtast.fancybot.entity.bili
data class BVID(
data class VideoStat(
val data: Data
) {
data class Data(
val aid: Long,
val pic: String,
val title: String,
val owner: Owner,
@@ -0,0 +1,16 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/14
*/
package cn.rtast.fancybot.entity.bili
data class ViewCount(
val data: Data
) {
data class Data(
val total: String
)
}
+32 -46
View File
@@ -100,7 +100,7 @@ object Http {
@JvmOverloads
inline fun <reified T> post(
url: String,
formBody: Map<String, String>? = null,
formBody: Map<String, Any>? = null,
headers: Map<String, String>? = null,
params: Map<String, Any>? = null
): T {
@@ -108,7 +108,7 @@ object Http {
val paramsUrl = buildParams(url, params)
formBody?.let {
it.forEach { (key, value) ->
body.add(key, value)
body.add(key, value.toString())
}
}
val request = Request.Builder()
@@ -146,48 +146,34 @@ object Http {
return this.executeRequest(headerRequest.build())
}
inline fun <reified T> getAsync(
url: String,
params: Map<String, Any>? = null,
headers: Map<String, String>? = null,
noinline callback: (T?) -> Unit
) {
val paramsUrl = buildParams(url, params)
val request = Request.Builder()
.url(paramsUrl)
.get()
executeRequestAsync(request, headers) { response ->
try {
callback(response.fromJson<T>())
} catch (e: Exception) {
e.printStackTrace()
callback(null)
}
}
}
inline fun <reified T> postAsync(
url: String,
jsonBody: String,
headers: Map<String, String>? = null,
params: Map<String, Any>? = null,
noinline callback: (T?) -> Unit
) {
val body = jsonBody.toRequestBody(jsonMediaType)
val paramsUrl = buildParams(url, params)
val request = Request.Builder()
.post(body)
.url(paramsUrl)
this.addHeaders(request, jsonHeader)
executeRequestAsync(request, headers) { response ->
try {
callback(response.fromJson<T>())
} catch (e: Exception) {
e.printStackTrace()
callback(null)
}
}
}
// @JvmOverloads
// fun post(
// url: String,
// form: Map<String, Any>,
// headers: Map<String, String>? = null,
// params: Map<String, Any>? = null
// ): String {
// val formBody = FormBody.Builder()
// form.forEach {
// formBody.add(it.key, it.value.toString())
// }
// val paramsUrl = buildParams(url, params)
// val request = Request.Builder()
// .post(formBody.build())
// .url(paramsUrl)
// this.addHeaders(request, jsonHeader)
// val headerRequest = addHeaders(request, headers)
// return this.executeRequest(headerRequest.build())
// }
//
// @JvmOverloads
// inline fun <reified T> post(
// url: String,
// form: Map<String, Any>,
// headers: Map<String, String>? = null,
// params: Map<String, Any>? = null
// ): T {
// val result = post(url, form, headers, params)
// return result.fromJson<T>()
// }
}