Skip to content

Commit

Permalink
修复萌新榜无法发送的问题;
Browse files Browse the repository at this point in the history
为部分函数添加 suspend 关键字,减少因本插件阻塞线程导致 mcl 自动重启。
  • Loading branch information
rainlodo committed May 12, 2024
1 parent 7493b18 commit ca80262
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 63 deletions.
50 changes: 31 additions & 19 deletions src/main/kotlin/ExtraFeatures.kt
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
package org.iris.wiki

import org.iris.wiki.config.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.message.data.At
import net.mamoe.mirai.message.data.MessageChainBuilder
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
import org.iris.wiki.config.shipClassList
import org.iris.wiki.config.shipTechPointsMap
import org.iris.wiki.config.techClassList
import org.iris.wiki.utils.UpdateUtils.updateShipTechPoints
import java.awt.BasicStroke
import java.awt.Color
import java.awt.Font
import java.awt.FontMetrics
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.message.data.MessageChainBuilder
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
import java.io.ByteArrayOutputStream
import javax.imageio.ImageIO


suspend fun techPointTable(commandList: Array<String>, sender: Member) {
if (commandList[1] == "筛选" && commandList[2] in shipClassList && commandList[3] in techClassList) {
if (shipTechPointsMap.isEmpty()) {
updateShipTechPoints() // 可能存在 mcl 启动时科技点数据获取失败的情况
}

suspend fun techPointTable(commandList: Array<String>, sender: Member){
if (commandList[1] == "筛选" && commandList[2] in shipClassList && commandList[3] in techClassList){
val imageBytes = drawTechPointTable(commandList[2], commandList[3], commandList[4].toInt())?.toExternalResource()
val imageBytes =
drawTechPointTable(commandList[2], commandList[3], commandList[4].toInt())?.toExternalResource()
val builder = MessageChainBuilder()
if (imageBytes != null){
if (imageBytes != null) {
val img = sender.uploadImage(imageBytes)
builder.add(At(sender))
builder.add(img)
val msg = builder.build()
sender.group.sendMessage(msg)
}
else{
withContext(Dispatchers.IO) {
imageBytes.close()
}
} else {
sender.group.sendMessage("out of Index")
}
}
Expand All @@ -36,14 +48,14 @@ private fun drawTechPointTable(shipClass: String, techClass: String, pageNumber:
val height = 600

if ((pageNumber - 1) * 10 > shipTechPointsMap[shipClass]?.get(techClass)?.size!!) return null

var tableData: MutableList<MutableList<String>>? = null
tableData = try {
val tableData: MutableList<MutableList<String>>? = try {
shipTechPointsMap[shipClass]?.get(techClass)?.subList(
(pageNumber - 1) * 10, pageNumber * 10)
} catch (e: Exception){
(pageNumber - 1) * 10, pageNumber * 10
) // 一页十条
} catch (e: Exception) {
shipTechPointsMap[shipClass]?.get(techClass)?.subList(
(pageNumber - 1) * 10, shipTechPointsMap[shipClass]?.get(techClass)?.size!!)
(pageNumber - 1) * 10, shipTechPointsMap[shipClass]?.get(techClass)?.size!!
)
}

// println(tableData)
Expand Down Expand Up @@ -86,7 +98,7 @@ private fun drawTechPointTable(shipClass: String, techClass: String, pageNumber:
val x = j * cellWidth + (cellWidth - textWidth) / 2
val y = (i + 1) * cellHeight - (cellHeight - textHeight) / 2

if (j == 0){
if (j == 0) {
val textColor = countryColors[tableData[i][2]] ?: Color.BLACK
g2d.color = textColor
}
Expand Down
1 change: 0 additions & 1 deletion src/main/kotlin/Listener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ internal object Listener {

val channel = GlobalEventChannel.parentScope(Wiki)

@OptIn(MiraiExperimentalApi::class)
fun subscribe() {
channel.subscribeAlways<GroupMessageEvent> {

Expand Down
7 changes: 4 additions & 3 deletions src/main/kotlin/Wiki.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.iris.wiki

import kotlinx.coroutines.launch
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregister
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
Expand Down Expand Up @@ -54,15 +55,15 @@ object Wiki : KotlinPlugin(
WikiConfigCommand.register()
ReplyCommand.register()

UpdateUtils.updateAll()
launch {
UpdateUtils.updateAll() // 更新舰船、科技点等数据
}
}

override fun onDisable() {

WikiConfigCommand.unregister()
ReplyCommand.unregister()


super.onDisable()
}

Expand Down
4 changes: 3 additions & 1 deletion src/main/kotlin/data/ImagesData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ data class ImagesData (
val src = ImageUtil.getImageAsExResource(url)
// println(url + "size:" + src.size)
val imageId: String = src.uploadAsImage(sender.group).imageId
src.close()
withContext(Dispatchers.IO) {
src.close()
}
builder.add(Image(imageId))
}
return builder.build()
Expand Down
24 changes: 16 additions & 8 deletions src/main/kotlin/utils/HttpUtils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.iris.wiki.utils

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
Expand Down Expand Up @@ -34,13 +36,20 @@ object HttpUtils {
}


fun get(url: String): String {
val request = Request.Builder().url(url)
suspend fun get(url: String): String = withContext(Dispatchers.IO) {
val request = Request.Builder()
.url(url)
.header("cookie", cookie)
.header("Content-Type", "application/json; charset=utf-8")
.header("user-agent", ua.random())
.get().build()
return sendRequest(request)
.get()
.build()
try {
val response = client.newCall(request).execute()
response.body!!.string()
} catch (_: Exception) {
""
}
}

fun post(url: String, postBody: String): String {
Expand All @@ -53,8 +62,8 @@ object HttpUtils {
}


fun getByteArray(url: String) : ByteArrayOutputStream? {
try{
fun getByteArray(url: String): ByteArrayOutputStream? {
try {

val request = Request.Builder().url(url)
.header("cookie", cookie)
Expand All @@ -76,8 +85,7 @@ object HttpUtils {
infoStream.write((Math.random() * 100).toInt() + 1)
infoStream.close()
return infoStream
}
catch (e: Exception) {
} catch (e: Exception) {
return null
}
}
Expand Down
87 changes: 67 additions & 20 deletions src/main/kotlin/utils/ImageUtils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.iris.wiki.utils

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.mamoe.mirai.utils.ExternalResource
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
import okhttp3.Headers
Expand All @@ -16,36 +18,79 @@ import java.io.*
import java.net.URL
import java.util.concurrent.TimeUnit
import javax.imageio.ImageIO
import javax.imageio.ImageReader
import javax.imageio.stream.ImageInputStream
import javax.net.ssl.*
import kotlin.io.path.Path


class ImageUtil {
companion object {
private val client = OkHttpClient().newBuilder().connectTimeout(600000, TimeUnit.MILLISECONDS).readTimeout(
600000,
private val client = OkHttpClient().newBuilder().connectTimeout(60000, TimeUnit.MILLISECONDS).readTimeout(
60000,
TimeUnit.MILLISECONDS
)
private val headers = Headers.Builder()
.add(
"user-agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59"
)
.add("Referer", "https://www.pixiv.net")
private var isChange: Boolean = false

/**
减少颜色位数,降低数据量
**/
private fun reduceColorDepth(image: BufferedImage): BufferedImage {
// 维持图片宽高不变并将颜色映射到 8 位颜色空间
val reducedColorImage = BufferedImage(image.width, image.height, BufferedImage.TYPE_BYTE_INDEXED)
val g2d: Graphics2D = reducedColorImage.createGraphics()
g2d.drawImage(image, 0, 0, null)
g2d.dispose()

return reducedColorImage
}

private fun loadImageData(imageUri: String): Pair<BufferedImage, String> {
// 读取图像和获取格式
val imageInputStream = ImageIO.createImageInputStream(
if (imageUri.startsWith("http")) URL(imageUri).openStream() // 需要转化为 InputStream
else File(imageUri)
)

val imageReaders = ImageIO.getImageReaders(imageInputStream)
if (!imageReaders.hasNext()) throw RuntimeException("Cannot detect image format.")
val reader: ImageReader = imageReaders.next()
val format = reader.formatName
// 读取图像数据
reader.input = imageInputStream
val imgData = reader.read(0)
imageInputStream.close() // 关闭流
return imgData to format // 返回图片数据和图片格式
}

/**
* 将图片链接读取到内存转换成ByteArrayOutputStream,方便操作
*/
fun getImageAsExResource(imageUri: String): ExternalResource {
// 强度榜目前直接获取是 jpg 格式
val suffix = if (imageUri.endsWith("png")) "png" else "jpg" // 假设只有这两种格式
return if (imageUri.startsWith("http")) {
imageToBytes(randomNoise(ImageIO.read(URL(imageUri))), suffix).toByteArray().toExternalResource()
} else {
imageToBytes(randomNoise(ImageIO.read(File(imageUri))), suffix).toByteArray().toExternalResource()
suspend fun getImageAsExResource(imageUri: String): ExternalResource {
// 获取图像数据和格式
val (imgData, format) = withContext(Dispatchers.IO) {
loadImageData(imageUri)
}

// 将图像转换为字节数组
var imgBytes = imageToBytes(imgData, format)
val maxSize = 150000000

// 如果图像数据大于阈值,则减少颜色深度以减小文件大小
if (imgBytes.size() > maxSize) {
val reducedColorImage = reduceColorDepth(imgData)
imgBytes = imageToBytes(reducedColorImage, format)
}

println("url: $imageUri, Image took ${imgBytes.size()} bytes.")
return imgBytes.toByteArray().toExternalResource()
}

fun randomNoise(image: BufferedImage): BufferedImage {
Expand All @@ -62,8 +107,10 @@ class ImageUtil {
/**
* 从图片中随机截取一部分
*/
fun getImagePiece(imagePath: String, w: Int, h: Int): BufferedImage {
val image = ImageIO.read(File(imagePath))
suspend fun getImagePiece(imagePath: String, w: Int, h: Int): BufferedImage {
val image = withContext(Dispatchers.IO) {
ImageIO.read(File(imagePath))
}
while (true) {
var transparentCount = 0;
val piece = image.getSubimage(
Expand All @@ -86,10 +133,10 @@ class ImageUtil {
}

fun getImage(imageUri: String): BufferedImage {
if (imageUri.startsWith("http")) {
return ImageIO.read(URL(imageUri))
return if (imageUri.startsWith("http")) {
ImageIO.read(URL(imageUri))
} else {
return ImageIO.read(Path(imageUri).toFile())
ImageIO.read(Path(imageUri).toFile())
}
}

Expand All @@ -113,7 +160,7 @@ class ImageUtil {
fun rotate(src: Image, angel: Int): ByteArrayOutputStream {
val srcWidth: Int = src.getWidth(null);
val srcHeight: Int = src.getHeight(null);
val rectDes: Rectangle? = CalcRotatedSize(
val rectDes: Rectangle? = calcRotatedSize(
Rectangle(
Dimension(
srcWidth, srcHeight
Expand Down Expand Up @@ -172,12 +219,12 @@ class ImageUtil {
* @param angel 角度
* @return 目标矩形
*/
private fun CalcRotatedSize(src: Rectangle, angel: Int): Rectangle {
private fun calcRotatedSize(src: Rectangle, angel: Int): Rectangle {
val cos = Math.abs(Math.cos(Math.toRadians(angel.toDouble())))
val sin = Math.abs(Math.sin(Math.toRadians(angel.toDouble())))
val des_width = (src.width * cos).toInt() + (src.height * sin).toInt()
val des_height = (src.height * cos).toInt() + (src.width * sin).toInt()
return Rectangle(Dimension(des_width, des_height))
val desWidth = (src.width * cos).toInt() + (src.height * sin).toInt()
val desHeight = (src.height * cos).toInt() + (src.width * sin).toInt()
return Rectangle(Dimension(desWidth, desHeight))
}

}
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/utils/ParserUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import java.net.URLEncoder

object ParserUtils {

fun parse(data: String, commandList: List<String>): Data? {
suspend fun parse(data: String, commandList: List<String>): Data? {
if (data.isEmpty()) {
return TextData("网络连接错误,请重试喵")
}
Expand Down Expand Up @@ -192,13 +192,13 @@ object ParserUtils {
try {
doc.select("div[class='center']").select("img").forEach {
val url = it.attr("src")
println(url)
// println(url)
imagesData.images.add(url)
}
if (imagesData.images.isEmpty()) {
doc.select("span[id='${commandList[1]}']")[0].parent().nextElementSibling().select(
doc.select("span[id='${commandList[1]}']")[0].parent()?.nextElementSibling()?.select(
"img"
).forEach {
)?.forEach {
val url = it.attr("src").split(Regex("/[\\d]*px-"))[0]
imagesData.images.add(url)
}
Expand Down Expand Up @@ -393,7 +393,7 @@ object ParserUtils {
return list
}

fun searchResult2Data(list: List<String>, commandList: List<String>): Data? {
suspend fun searchResult2Data(list: List<String>, commandList: List<String>): Data? {
return when (list.size) {
0 -> null
1 -> {
Expand Down
Loading

0 comments on commit ca80262

Please sign in to comment.