Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
This commit is contained in:
Him188 2020-08-18 19:55:12 +08:00
commit 6c21971ce0
7 changed files with 35 additions and 31 deletions

View File

@ -453,7 +453,7 @@ internal class GroupImpl(
* 上传一个语音消息以备发送.
* 请注意这是一个实验性api且随时会被删除
* @throws EventCancelledException 当发送消息事件被取消
* @throws OverFileSizeMaxException 图片文件过大而被服务器拒绝上传时. (最大大小约为 1 MB)
* @throws OverFileSizeMaxException 语音文件过大而被服务器拒绝上传时. (最大大小约为 1 MB)
*/
@JvmSynthetic
@MiraiExperimentalAPI
@ -465,16 +465,24 @@ internal class GroupImpl(
throw OverFileSizeMaxException()
}
val md5 = MiraiPlatformUtils.md5(content)
val codec = with(content.copyOfRange(0, 10).toUHexString("")) {
when {
startsWith("2321414D52") -> 0 // amr
startsWith("02232153494C4B5F5633") -> 1 // silk V3
else -> 0 // use amr by default
}
}
return bot.network.run {
val response: PttStore.GroupPttUp.Response.RequireUpload =
PttStore.GroupPttUp(bot.client, bot.id, 0L, md5, content.size.toLong()).sendAndExpect()
PttStore.GroupPttUp(bot.client, bot.id, id, md5, content.size.toLong(), codec).sendAndExpect()
HighwayHelper.uploadPttToServers(
bot,
response.uploadIpList.zip(response.uploadPortList),
content,
md5,
response.uKey,
response.fileKey
response.fileKey,
codec
)
Voice("${md5.toUHexString("")}.amr", md5, content.size.toLong(), "")
}

View File

@ -413,9 +413,8 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
logger.info { "Syncing friend message history..." }
withTimeoutOrNull(30000) {
launch(CoroutineName("Syncing friend message history")) { syncFromEvent<MessageSvcPbGetMsg.GetMsgSuccess, Unit> { Unit } }
// 别问我为什么要发两个 我也不知道 反正它能用
MessageSvcPbGetMsg(bot.client, MsgSvc.SyncFlag.START, null, firstSync = true).sendAndExpect<Packet>()
MessageSvcPbGetMsg(bot.client, MsgSvc.SyncFlag.START, null, firstSync = true).sendAndExpect<Packet>()
MessageSvcPbGetMsg(bot.client, MsgSvc.SyncFlag.START, null).sendAndExpect<Packet>()
} ?: error("timeout syncing friend message history")
logger.info { "Syncing friend message history: Success" }
}

View File

@ -128,8 +128,6 @@ internal open class QQAndroidClient(
lateinit var fileStoragePushFSSvcList: FileStoragePushFSSvcListFuckKotlin
internal val firstSyncPackets: AtomicInt = atomic(0) // 启动时候仅将所有好友信息设为已读的包
internal suspend inline fun useNextServers(crossinline block: suspend (host: String, port: Int) -> Unit) {
if (bot.client.serverList.isEmpty()) {
throw NoServerAvailableException(null)

View File

@ -190,7 +190,9 @@ internal object HighwayHelper {
servers: List<Pair<Int, Int>>,
content: ByteArray,
md5: ByteArray,
uKey: ByteArray, fileKey: ByteArray
uKey: ByteArray,
fileKey: ByteArray,
codec: Int
) {
servers.retryWithServers(10 * 1000, {
throw IllegalStateException("cannot upload ptt, failed on all servers.", it)
@ -199,7 +201,7 @@ internal object HighwayHelper {
"[Highway] Uploading ptt to ${s}:$i, size=${content.size.toLong().sizeToString()}"
}
val time = measureTime {
uploadPttToServer(s, i, content, md5, uKey, fileKey)
uploadPttToServer(s, i, content, md5, uKey, fileKey, codec)
}
bot.network.logger.verbose {
"[Highway] Uploading ptt: succeed at ${(content.size.toDouble() / 1024 / time.inSeconds).roundToInt()} KiB/s"
@ -214,7 +216,9 @@ internal object HighwayHelper {
serverPort: Int,
content: ByteArray,
md5: ByteArray,
uKey: ByteArray, fileKey: ByteArray
uKey: ByteArray,
fileKey: ByteArray,
codec: Int
) {
MiraiPlatformUtils.Http.post<String> {
url("http://$serverIp:$serverPort")
@ -224,7 +228,7 @@ internal object HighwayHelper {
parameter("filesize", content.size)
parameter("bmd5", md5.toUHexString(""))
parameter("mType", "pttDu")
parameter("voice_encodec", 0)
parameter("voice_encodec", codec)
body = content
}
}

View File

@ -61,14 +61,10 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
client: QQAndroidClient,
syncFlag: MsgSvc.SyncFlag = MsgSvc.SyncFlag.START,
syncCookie: ByteArray?, //PbPushMsg.msg.msgHead.msgTime
firstSync: Boolean = false
): OutgoingPacket = buildOutgoingUniPacket(
client
) {
//println("syncCookie=${client.c2cMessageSync.syncCookie?.toUHexString()}")
if (firstSync) {
client.firstSyncPackets.getAndAdd(1)
}
writeProtoBuf(
MsgSvc.PbGetMsgReq.serializer(),
MsgSvc.PbGetMsgReq(
@ -150,10 +146,13 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
val messages = resp.uinPairMsgs.asFlow()
.filterNot { it.msg == null }
.flatMapConcat { it.msg!!.asFlow() }
.also {
MessageSvcPbDeleteMsg.delete(bot, it)
} // 删除消息
.flatMapConcat {
it.msg!!.asFlow()
.filter { msg: MsgComm.Msg -> msg.msgHead.msgTime > it.lastReadTime.toLong() and 4294967295L }
}.also {
MessageSvcPbDeleteMsg.delete(bot, it) // 删除消息
// todo 实现一个锁来防止重复收到消息
}
.mapNotNull<MsgComm.Msg, Packet> { msg ->
suspend fun createGroupForBot(groupUin: Long): Group? {
@ -277,9 +276,6 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
*/
166 -> {
if (bot.client.firstSyncPackets.value != 0) {
return@mapNotNull null
}
if (msg.msgHead.fromUin == bot.id) {
loop@ while (true) {
val instance = bot.client.getFriendSeq()
@ -383,9 +379,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
override suspend fun QQAndroidBot.handle(packet: Response) {
when (packet.syncFlagFromServer) {
MsgSvc.SyncFlag.STOP -> {
if (client.firstSyncPackets.value != 0) {
client.firstSyncPackets.getAndDecrement()
}
}
MsgSvc.SyncFlag.START -> {

View File

@ -175,15 +175,15 @@ public abstract class Group : Contact(), CoroutineScope {
/**
* 上传一个语音消息以备发送.
* 请手动关闭输入流
* 请使用mar格式
* 请使用amr或silk格式
* 请注意这是一个实验性api且随时会被删除
* @throws EventCancelledException 当发送消息事件被取消
* @throws OverFileSizeMaxException 图片文件过大而被服务器拒绝上传时. (最大大小约为 1 MB)
* @throws OverFileSizeMaxException 语音文件过大而被服务器拒绝上传时. (最大大小约为 1 MB)
*/
@JvmSynthetic
@MiraiExperimentalAPI
@SinceMirai("1.2.0")
public abstract suspend fun uploadVoice(input: InputStream): Voice
public abstract suspend fun uploadGroupVoice(input: InputStream): Voice
public companion object {

View File

@ -119,14 +119,15 @@ public suspend fun File.uploadAsImage(contact: Contact): Image {
}
/**
* [Dispatchers.IO] 中将文件作为语音上传后构造 [Image]
* [Dispatchers.IO] 中将文件作为语音上传后构造 [Voice]
* 请手动关闭输入流
* 请使用mar格式
* 请使用amr或silk格式
* 注意这只是个实验性功能且随时可能会删除
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
@MiraiExperimentalAPI
@SinceMirai("1.2.0")
public suspend fun InputStream.uploadAsGroupVoice(group: Group): Voice {
return group.uploadGroupVoice(this)
}