Skip to content

Commit

Permalink
Add voice support
Browse files Browse the repository at this point in the history
  • Loading branch information
yyuueexxiinngg committed Aug 20, 2020
1 parent 798d47e commit 8a1fbf3
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 4 deletions.
27 changes: 25 additions & 2 deletions src/main/kotlin/tech/mihoyo/mirai/PluginBase.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package tech.mihoyo.mirai

import io.ktor.util.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import net.mamoe.mirai.Bot
import net.mamoe.mirai.LowLevelAPI
Expand All @@ -20,11 +18,14 @@ import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.message.MessageEvent
import net.mamoe.mirai.message.TempMessageEvent
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.Voice
import net.mamoe.mirai.utils.currentTimeMillis
import tech.mihoyo.mirai.SessionManager.allSession
import tech.mihoyo.mirai.SessionManager.closeSession
import tech.mihoyo.mirai.util.HttpClient
import tech.mihoyo.mirai.util.toUHexString
import java.io.File
import kotlin.reflect.jvm.isAccessible

object PluginBase : PluginBase() {
private lateinit var config: Config
Expand All @@ -33,6 +34,7 @@ object PluginBase : PluginBase() {
override fun onLoad() {
}

@OptIn(LowLevelAPI::class)
override fun onEnable() {
config = loadConfig("setting.yml")
debug = if (config.exist("debug")) config.getBoolean("debug") else false
Expand Down Expand Up @@ -120,6 +122,20 @@ object PluginBase : PluginBase() {
saveImageAsync("$imageMD5.cqimg", cqImgContent).start()
}
}

if (session.shouldCacheRecord) {
message.filterIsInstance<Voice>().forEach { voice ->
val voiceUrl = if (voice.url != null) voice.url else {
val voiceUrlFiled = voice::class.members.find { it.name == "_url" }
voiceUrlFiled?.isAccessible = true
"http://grouptalk.c2c.qq.com${voiceUrlFiled?.call(voice)}"
}
val voiceBytes = voiceUrl?.let { it -> HttpClient.getBytes(it) }
if (voiceBytes != null) {
saveRecordAsync("${voice.md5.toUHexString("")}.cqrecord", voiceBytes).start()
}
}
}
}
}
}
Expand All @@ -132,8 +148,15 @@ object PluginBase : PluginBase() {
}

private val imageFold: File = File(dataFolder, "image").apply { mkdirs() }
private val recordFold: File = File(dataFolder, "record").apply { mkdirs() }

internal fun image(imageName: String) = File(imageFold, imageName)
internal fun record(recordName: String) = File(recordFold, recordName)

fun saveRecordAsync(name: String, data: ByteArray) =
async {
record(name).apply { writeBytes(data) }
}

fun saveImageAsync(name: String, data: ByteArray) =
async {
Expand Down
4 changes: 4 additions & 0 deletions src/main/kotlin/tech/mihoyo/mirai/Session.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class BotSession internal constructor(val bot: Bot, val config: ConfigSection, c
Session(coroutineContext, bot.id) {
private val heartbeatConfig = if (config.containsKey("heartbeat")) config.getConfigSection("heartbeat") else null
val shouldCacheImage = if (config.containsKey("cacheImage")) config.getBoolean("cacheImage") else false
val shouldCacheRecord = if (config.containsKey("cacheRecord")) config.getBoolean("cacheRecord") else false
val heartbeatEnabled =
heartbeatConfig?.let { if (it.containsKey("enable")) it.getBoolean("enable") else false } ?: false
val heartbeatInterval =
Expand All @@ -67,6 +68,9 @@ class BotSession internal constructor(val bot: Bot, val config: ConfigSection, c
if (shouldCacheImage) logger.info("Bot: ${bot.id} 已开启接收图片缓存, 将会缓存收取到的所有图片")
else logger.info("Bot: ${bot.id} 未开启接收图片缓存, 将不会缓存收取到的所有图片, 如需开启, 请在当前Bot配置中添加cacheImage=true")

if(shouldCacheRecord) logger.info("Bot: ${bot.id} 已开启接收语音缓存, 将会缓存收取到的所有语音")
else logger.info("Bot: ${bot.id} 未开启接收语音缓存, 将不会缓存收取到的所有语音, 如需开启, 请在当前Bot配置中添加cacheRecord=true")

if (heartbeatEnabled) logger.info("Bot: ${bot.id} 已开启心跳机制, 设定的心跳发送频率为 $heartbeatInterval 毫秒")
}

Expand Down
40 changes: 39 additions & 1 deletion src/main/kotlin/tech/mihoyo/mirai/util/CQMessgeParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ import kotlinx.coroutines.withContext
import kotlinx.serialization.json.*
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.getGroupOrNull
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.message.uploadImage
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.currentTimeMillis
import tech.mihoyo.mirai.PluginBase
import tech.mihoyo.mirai.PluginBase.saveImageAsync
import tech.mihoyo.mirai.PluginBase.saveRecordAsync
import java.io.ByteArrayInputStream
import java.io.File
import java.net.URL
Expand Down Expand Up @@ -158,6 +160,9 @@ private suspend fun convertToMiraiMessage(
args["image"]
)
}
"record" -> {
return tryResolveMedia("record", contact, args)
}
"contact" -> {
return if (args["type"] == "qq") {
RichMessageHelper.contactQQ(bot, args["id"]!!.toLong())
Expand Down Expand Up @@ -338,6 +343,8 @@ suspend fun tryResolveMedia(type: String, contact: Contact?, args: Map<String, S
} else {
if (type == "image") {
media = tryResolveCachedImage(filePath, contact)
} else if (type == "record") {
media = tryResolveCachedRecord(filePath, contact)
}
if (media == null) {
val file = getDataFile(type, filePath)
Expand Down Expand Up @@ -398,6 +405,22 @@ suspend fun tryResolveMedia(type: String, contact: Contact?, args: Map<String, S
}
}
}
"record" -> {
if (useCache) {
media = tryResolveCachedRecord(urlHash, contact)
}
if (media == null || !useCache) {
mediaBytes = HttpClient.getBytes(mediaUrl!!)
media = HttpClient.getInputStream(mediaUrl!!)
.let { stream ->
contact?.let { (it as Group).uploadVoice(stream) }
}

if (useCache && mediaBytes != null) {
saveRecordAsync("$urlHash.cqrecord", mediaBytes!!).start()
}
}
}
}
}
}
Expand All @@ -411,9 +434,24 @@ suspend fun tryResolveMedia(type: String, contact: Contact?, args: Map<String, S
media = withContext(Dispatchers.IO) { contact!!.uploadImage(bis) }
return media as Image
}
"record" -> {
media = withContext(Dispatchers.IO) { (contact!! as Group).uploadVoice(mediaBytes!!.inputStream()) }
return media as Voice
}
}
}
return PlainText("插件无法获取到图片" + if (mediaUrl != null) ", 原图链接: $mediaUrl" else "")
return PlainText("插件无法获取到媒体" + if (mediaUrl != null) ", 媒体链接: $mediaUrl" else "")
}

suspend fun tryResolveCachedRecord(name: String, contact: Contact?): Voice? {
val cacheFile = getDataFile("record", "$name.cqrecord")
if (cacheFile != null) {
if (cacheFile.canRead()) {
logger.info("此语音已缓存, 如需删除缓存请至 ${cacheFile.absolutePath}")
return contact?.let { (it as Group).uploadVoice(cacheFile.inputStream()) }
}
}
return null
}

suspend fun tryResolveCachedImage(name: String, contact: Contact?): Image? {
Expand Down
15 changes: 14 additions & 1 deletion src/main/kotlin/tech/mihoyo/mirai/util/HttpClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,29 @@ package tech.mihoyo.mirai.util

import io.ktor.client.request.*
import io.ktor.http.*
import java.io.InputStream

class HttpClient {
companion object {
private val http = io.ktor.client.HttpClient()
private val ua =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36"

suspend fun getBytes(url: String): ByteArray {
return http.request {
url(url)
headers {
append("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")
append("User-Agent", ua)
}
method = HttpMethod.Get
}
}

suspend fun getInputStream(url: String): InputStream {
return http.request {
url(url)
headers {
append("User-Agent", ua)
}
method = HttpMethod.Get
}
Expand Down

0 comments on commit 8a1fbf3

Please sign in to comment.