mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Shamrock
: support upload resource by NtKernel
Signed-off-by: 白池 <whitechi73@outlook.com>
This commit is contained in:
parent
92ebe0c6a8
commit
fca66f3259
@ -6,7 +6,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public interface IKernelMsgService {
|
||||
void deleteMsg(Contact contact, ArrayList<Long> msgIdList, IOperateCallback callback);
|
||||
void deleteMsg(Contact contact, ArrayList<Long> msgIdList, IOperateCallback cb);
|
||||
|
||||
void fetchLongMsg(Contact contact, long msgId);
|
||||
|
||||
|
@ -9,6 +9,7 @@ import io.ktor.utils.io.core.writeFully
|
||||
import io.ktor.utils.io.core.writeInt
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import moe.fuqiuluo.qqinterface.servlet.msg.MessageTempHandler
|
||||
|
||||
import moe.fuqiuluo.shamrock.remote.action.handlers.GetHistoryMsg
|
||||
import moe.fuqiuluo.shamrock.remote.service.listener.AioListener
|
||||
@ -80,11 +81,11 @@ internal object PacketSvc: BaseSvc() {
|
||||
fakeReceive("trpc.msg.olpush.OlPushService.MsgPush", 10000, msgPush.toByteArray())
|
||||
return withTimeoutOrNull(5000L) {
|
||||
suspendCancellableCoroutine {
|
||||
AioListener.registerTemporaryMsgListener(msgSeq) {
|
||||
MessageTempHandler.registerTemporaryMsgListener(msgSeq) {
|
||||
it.resume(this.msgId)
|
||||
}
|
||||
it.invokeOnCancellation {
|
||||
AioListener.unregisterTemporaryMsgListener(msgSeq)
|
||||
MessageTempHandler.unregisterTemporaryMsgListener(msgSeq)
|
||||
}
|
||||
}
|
||||
} ?: -1L
|
||||
|
@ -1,16 +1,9 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.ark
|
||||
|
||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||
import moe.fuqiuluo.shamrock.remote.service.listener.AioListener
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.data.ArkAppInfo
|
||||
import tencent.im.oidb.cmd0xb77.oidb_cmd0xb77
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
internal object ArkMsgSvc: BaseSvc() {
|
||||
fun tryShareMusic(
|
@ -6,10 +6,10 @@ import io.ktor.client.request.url
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.encodeURLQueryComponent
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.data.Region
|
||||
import moe.fuqiuluo.shamrock.helper.Level
|
||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||
import moe.fuqiuluo.shamrock.tools.*
|
||||
|
@ -1,4 +1,5 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.ark
|
||||
package moe.fuqiuluo.qqinterface.servlet.ark.data
|
||||
|
||||
sealed class ArkAppInfo(
|
||||
val appId: Long,
|
||||
val version: String,
|
@ -1,4 +1,4 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.ark
|
||||
package moe.fuqiuluo.qqinterface.servlet.ark.data
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -0,0 +1,34 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.msg
|
||||
|
||||
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||
import moe.fuqiuluo.shamrock.helper.Level
|
||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||
import java.util.Collections
|
||||
|
||||
internal object MessageTempHandler {
|
||||
// 通过MSG SEQ临时监听器
|
||||
private val tempMessageListenerMap = Collections.synchronizedMap(HashMap<Long, suspend MsgRecord.() -> Unit>())
|
||||
|
||||
fun registerTemporaryMsgListener(
|
||||
msgSeq: Long,
|
||||
listener: suspend MsgRecord.() -> Unit
|
||||
) {
|
||||
LogCenter.log({ "注册临时消息监听器: $msgSeq" }, Level.DEBUG)
|
||||
tempMessageListenerMap[msgSeq] = listener
|
||||
}
|
||||
|
||||
fun unregisterTemporaryMsgListener(msgSeq: Long) {
|
||||
tempMessageListenerMap.remove(msgSeq)
|
||||
}
|
||||
|
||||
suspend fun notify(record: MsgRecord): Boolean {
|
||||
tempMessageListenerMap.firstNotNullOfOrNull {
|
||||
if (it.key == record.msgSeq) it else null
|
||||
}?.let {
|
||||
it.value(record)
|
||||
tempMessageListenerMap.remove(it.key)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
@ -12,10 +12,10 @@ import moe.fuqiuluo.qqinterface.servlet.ark.WeatherSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.msg.toJson
|
||||
import moe.fuqiuluo.qqinterface.servlet.msg.toSegments
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.*
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.PictureResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.Private
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.PictureResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.Private
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.Transfer
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.Troop
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.Troop
|
||||
import moe.fuqiuluo.shamrock.helper.*
|
||||
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
||||
import moe.fuqiuluo.shamrock.helper.Level
|
||||
|
@ -3,7 +3,6 @@ package moe.fuqiuluo.qqinterface.servlet.msg.maker
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import com.tencent.mobileqq.app.QQAppInterface
|
||||
import com.tencent.mobileqq.data.MessageForPic
|
||||
import com.tencent.mobileqq.emoticon.QQSysFaceUtil
|
||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||
import com.tencent.mobileqq.qroute.QRoute
|
||||
@ -17,17 +16,17 @@ import kotlinx.serialization.json.JsonPrimitive
|
||||
import moe.fuqiuluo.qqinterface.servlet.CardSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.LbsSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.ArkAppInfo
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.data.ArkAppInfo
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.ArkMsgSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.WeatherSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.*
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.FileTransfer
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.PictureResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.Private
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.PictureResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.Private
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.Transfer
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.Troop
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.VideoResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.VoiceResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.Troop
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.VideoResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.VoiceResource
|
||||
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
||||
import moe.fuqiuluo.shamrock.helper.ContactHelper
|
||||
import moe.fuqiuluo.shamrock.helper.IllegalParamsException
|
||||
|
@ -0,0 +1,19 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.structures
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UploadResult(
|
||||
@SerialName("files") val files: List<CommFileInfo>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class CommFileInfo(
|
||||
@SerialName("mode_id") val modeId: Long,
|
||||
@SerialName("name") val fileName: String,
|
||||
@SerialName("size") val fileSize: Long,
|
||||
@SerialName("md5") val md5: String,
|
||||
@SerialName("uuid") val uuid: String,
|
||||
@SerialName("sub_id") val subId: String,
|
||||
)
|
@ -1,14 +1,29 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import com.tencent.qqnt.kernel.nativeinterface.CommonFileInfo
|
||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
||||
import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback
|
||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
||||
import com.tencent.qqnt.kernel.nativeinterface.PicElement
|
||||
import com.tencent.qqnt.kernel.nativeinterface.QQNTWrapperUtil
|
||||
import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.TryUpPicData
|
||||
import moe.fuqiuluo.shamrock.helper.Level
|
||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
||||
import moe.fuqiuluo.shamrock.tools.slice
|
||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
||||
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||
import protobuf.auto.toByteArray
|
||||
import protobuf.oidb.TrpcOidb
|
||||
@ -31,13 +46,115 @@ import protobuf.oidb.cmd0x388.Cmd0x388ReqBody
|
||||
import protobuf.oidb.cmd0x388.Cmd0x388RspBody
|
||||
import protobuf.oidb.cmd0x388.TryUpImgReq
|
||||
import java.io.File
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.random.Random
|
||||
import kotlin.random.nextUInt
|
||||
import kotlin.random.nextULong
|
||||
import kotlin.time.Duration
|
||||
|
||||
internal object NtV2RichMediaSvc: BaseSvc() {
|
||||
private const val GROUP_PIC_UPLOAD_TO = "100000000"
|
||||
|
||||
private val requestIdSeq = atomic(2L)
|
||||
|
||||
/**
|
||||
* 批量上传图片
|
||||
*/
|
||||
suspend fun tryUploadGroupPicByNt(
|
||||
imageFiles: ArrayList<File>,
|
||||
timeout: Duration
|
||||
): Result<MutableList<CommonFileInfo>> {
|
||||
require(imageFiles.size in 1 .. 10) { "imageFiles.size() must be in 1 .. 10" }
|
||||
|
||||
val messages = imageFiles.map { file ->
|
||||
val elem = MsgElement()
|
||||
runCatching {
|
||||
elem.elementType = MsgConstant.KELEMTYPEPIC
|
||||
val pic = PicElement()
|
||||
pic.md5HexStr = QQNTWrapperUtil.CppProxy.genFileMd5Hex(file.absolutePath)
|
||||
val msgService = NTServiceFetcher.kernelService.msgService!!
|
||||
val originalPath = msgService.getRichMediaFilePathForMobileQQSend(
|
||||
RichMediaFilePathInfo(
|
||||
2, 0, pic.md5HexStr, file.name, 1, 0, null, "", true
|
||||
)
|
||||
)
|
||||
if (!QQNTWrapperUtil.CppProxy.fileIsExist(originalPath) || QQNTWrapperUtil.CppProxy.getFileSize(
|
||||
originalPath
|
||||
) != file.length()
|
||||
) {
|
||||
val thumbPath = msgService.getRichMediaFilePathForMobileQQSend(
|
||||
RichMediaFilePathInfo(
|
||||
2, 0, pic.md5HexStr, file.name, 2, 720, null, "", true
|
||||
)
|
||||
)
|
||||
QQNTWrapperUtil.CppProxy.copyFile(file.absolutePath, originalPath)
|
||||
QQNTWrapperUtil.CppProxy.copyFile(file.absolutePath, thumbPath)
|
||||
}
|
||||
val options = BitmapFactory.Options()
|
||||
options.inJustDecodeBounds = true
|
||||
BitmapFactory.decodeFile(file.absolutePath, options)
|
||||
val exifInterface = ExifInterface(file.absolutePath)
|
||||
val orientation = exifInterface.getAttributeInt(
|
||||
ExifInterface.TAG_ORIENTATION,
|
||||
ExifInterface.ORIENTATION_UNDEFINED
|
||||
)
|
||||
if (orientation != ExifInterface.ORIENTATION_ROTATE_90 && orientation != ExifInterface.ORIENTATION_ROTATE_270) {
|
||||
pic.picWidth = options.outWidth
|
||||
pic.picHeight = options.outHeight
|
||||
} else {
|
||||
pic.picWidth = options.outHeight
|
||||
pic.picHeight = options.outWidth
|
||||
}
|
||||
pic.sourcePath = file.absolutePath
|
||||
pic.fileSize = QQNTWrapperUtil.CppProxy.getFileSize(file.absolutePath)
|
||||
pic.original = true
|
||||
pic.picType = FileUtils.getPicType(file)
|
||||
elem.picElement = pic
|
||||
}.onFailure {
|
||||
LogCenter.log(it.stackTraceToString(), Level.WARN)
|
||||
elem.elementType = 0
|
||||
}
|
||||
return@map elem
|
||||
}.filter {
|
||||
it.elementType == MsgConstant.KELEMTYPEPIC
|
||||
}
|
||||
if (messages.isEmpty()) {
|
||||
return Result.failure(Exception("no valid image files"))
|
||||
}
|
||||
val result: MutableList<CommonFileInfo> = withTimeoutOrNull(timeout) {
|
||||
suspendCancellableCoroutine {
|
||||
val result = mutableListOf<CommonFileInfo>()
|
||||
val uniseq = MessageHelper.generateMsgId(MsgConstant.KCHATTYPEGROUP)
|
||||
val contact = Contact(MsgConstant.KCHATTYPEGROUP, GROUP_PIC_UPLOAD_TO, GROUP_PIC_UPLOAD_TO)
|
||||
RichMediaUploadHandler.registerListener(uniseq.qqMsgId) upload@{
|
||||
if (uniseq.qqMsgId == msgId) {
|
||||
result.add(commonFileInfo)
|
||||
}
|
||||
return@upload false
|
||||
}
|
||||
MessageHelper.sendMessageWithMsgId(
|
||||
contact = contact,
|
||||
message = ArrayList(messages),
|
||||
uniseq = uniseq.qqMsgId
|
||||
) { code, _ ->
|
||||
NTServiceFetcher.kernelService
|
||||
.wrapperSession.msgService
|
||||
.deleteMsg(contact, arrayListOf(uniseq.qqMsgId), null)
|
||||
RichMediaUploadHandler.removeListener(uniseq.qqMsgId)
|
||||
if (code != 110 && code != 4) {
|
||||
it.resume(null)
|
||||
} else {
|
||||
it.resume(result)
|
||||
}
|
||||
}
|
||||
it.invokeOnCancellation {
|
||||
RichMediaUploadHandler.removeListener(uniseq.qqMsgId)
|
||||
}
|
||||
}
|
||||
} ?: return Result.failure(Exception("timeout"))
|
||||
return Result.success(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取NT图片的RKEY
|
||||
*/
|
||||
@ -173,6 +290,9 @@ internal object NtV2RichMediaSvc: BaseSvc() {
|
||||
LogCenter.log("requestUploadPic => rsp: $rsp")
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用OldBDH获取图片上传状态以及图片上传服务器
|
||||
*/
|
||||
suspend fun requestUploadGroupPic(
|
||||
groupId: ULong,
|
||||
md5: String,
|
||||
@ -215,13 +335,5 @@ internal object NtV2RichMediaSvc: BaseSvc() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class TryUpPicData(
|
||||
@SerialName("ukey") val uKey: ByteArray,
|
||||
@SerialName("exist") val exist: Boolean,
|
||||
@SerialName("file_id") val fileId: ULong,
|
||||
@SerialName("up_ip") var upIp: ArrayList<Long>? = null,
|
||||
@SerialName("up_port") var upPort: ArrayList<Int>? = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package moe.fuqiuluo.shamrock.remote.service.api
|
||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||
|
||||
import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo
|
||||
|
@ -1,14 +1,19 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||
|
||||
import com.tencent.mobileqq.data.MessageForPic
|
||||
import com.tencent.mobileqq.data.MessageForShortVideo
|
||||
import com.tencent.mobileqq.data.MessageRecord
|
||||
import com.tencent.mobileqq.transfile.FileMsg
|
||||
import com.tencent.mobileqq.transfile.TransferRequest
|
||||
import moe.fuqiuluo.shamrock.utils.MD5
|
||||
import java.io.File
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.ResourceType.*
|
||||
import moe.fuqiuluo.shamrock.helper.TransfileHelper
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.ResourceType.*
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.ContactType
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.PictureResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.Resource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.ResourceType
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.TransTarget
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.VideoResource
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.VoiceResource
|
||||
|
||||
internal object Transfer: FileTransfer() {
|
||||
private val ROUTE = mapOf<ContactType, Map<ResourceType, suspend TransTarget.(Resource) -> Boolean>>(
|
||||
|
@ -1,4 +1,4 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||
package moe.fuqiuluo.qqinterface.servlet.transfile.data
|
||||
|
||||
import com.tencent.mobileqq.data.MessageRecord
|
||||
|
@ -1,4 +1,4 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||
package moe.fuqiuluo.qqinterface.servlet.transfile.data
|
||||
|
||||
import java.io.File
|
||||
|
@ -0,0 +1,13 @@
|
||||
package moe.fuqiuluo.qqinterface.servlet.transfile.data
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class TryUpPicData(
|
||||
@SerialName("ukey") val uKey: ByteArray,
|
||||
@SerialName("exist") val exist: Boolean,
|
||||
@SerialName("file_id") val fileId: ULong,
|
||||
@SerialName("up_ip") var upIp: ArrayList<Long>? = null,
|
||||
@SerialName("up_port") var upPort: ArrayList<Int>? = null,
|
||||
)
|
@ -205,27 +205,24 @@ internal object MessageHelper {
|
||||
fun sendMessageWithMsgId(
|
||||
contact: Contact,
|
||||
message: ArrayList<MsgElement>,
|
||||
uniseq: Long,
|
||||
callback: IOperateCallback
|
||||
): SendMsgResult {
|
||||
val uniseq = generateMsgId(contact.chatType)
|
||||
val nonMsg: Boolean = message.isEmpty()
|
||||
return if (!nonMsg) {
|
||||
if (!nonMsg) {
|
||||
val service = QRoute.api(IMsgService::class.java)
|
||||
if (callback is MsgSvc.MessageCallback) {
|
||||
callback.msgHash = uniseq.msgHashId
|
||||
}
|
||||
|
||||
service.sendMsg(
|
||||
contact,
|
||||
uniseq.qqMsgId,
|
||||
uniseq,
|
||||
message,
|
||||
callback
|
||||
)
|
||||
|
||||
uniseq.copy(msgTime = System.currentTimeMillis())
|
||||
} else {
|
||||
uniseq.copy(msgTime = 0, msgHashId = 0)
|
||||
}
|
||||
return SendMsgResult(
|
||||
msgTime = if (nonMsg) 0 else System.currentTimeMillis(),
|
||||
msgHashId = 0,
|
||||
qqMsgId = uniseq
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun sendMessageNoCb(
|
||||
|
@ -3,7 +3,7 @@ package moe.fuqiuluo.shamrock.helper
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import kotlinx.serialization.json.Json
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.ArkAppInfo
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.data.ArkAppInfo
|
||||
import moe.fuqiuluo.qqinterface.servlet.ark.ArkMsgSvc
|
||||
import moe.fuqiuluo.shamrock.tools.GlobalClient
|
||||
import moe.fuqiuluo.shamrock.tools.asInt
|
||||
|
@ -24,8 +24,7 @@ internal object SendMsgByResid : IActionHandler() {
|
||||
val resId = session.getString("res_id")
|
||||
val peerId = session.getString("peer_id")
|
||||
val messageType = session.getString("message_type")
|
||||
invoke(resId, peerId, messageType)
|
||||
return ok("ok", session.echo)
|
||||
return invoke(peerId, resId, messageType, session.echo)
|
||||
}
|
||||
|
||||
suspend operator fun invoke(peerId: String, resId: String, messageType: String, echo: JsonElement = EmptyJsonString): String {
|
||||
@ -55,4 +54,6 @@ internal object SendMsgByResid : IActionHandler() {
|
||||
BaseSvc.sendBufferAW("MessageSvc.PbSendMsg", true, req.toByteArray())
|
||||
return ok("ok", echo)
|
||||
}
|
||||
|
||||
override val requiredParams: Array<String> = arrayOf("res_id", "peer_id", "message_type")
|
||||
}
|
@ -1,15 +1,18 @@
|
||||
package moe.fuqiuluo.shamrock.remote.action.handlers
|
||||
|
||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||
import moe.fuqiuluo.shamrock.tools.jsonArray
|
||||
import moe.fuqiuluo.symbols.OneBotHandler
|
||||
|
||||
@OneBotHandler("send_private_msg", ["send_private_message"])
|
||||
@OneBotHandler("send_private_msg", ["send_private_message", "send_friend_msg"])
|
||||
internal object SendPrivateMessage : IActionHandler() {
|
||||
override suspend fun internalHandle(session: ActionSession): String {
|
||||
val userId = session.getLong("user_id")
|
||||
val userId = session.getString("user_id").let {
|
||||
if (it == "self") TicketSvc.getUin() else it
|
||||
}
|
||||
val groupId = session.getLongOrNull("group_id")
|
||||
val chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP
|
||||
val retryCnt = session.getIntOrNull("retry_cnt")
|
||||
@ -19,21 +22,21 @@ internal object SendPrivateMessage : IActionHandler() {
|
||||
val message = session.getString("message")
|
||||
SendMessage(
|
||||
chatType = chatType,
|
||||
peerId = userId.toString(),
|
||||
peerId = userId,
|
||||
message = message,
|
||||
autoEscape = autoEscape,
|
||||
echo = session.echo,
|
||||
fromId = groupId?.toString() ?: userId.toString(),
|
||||
fromId = groupId?.toString() ?: userId,
|
||||
retryCnt = retryCnt ?: 5,
|
||||
recallDuration = recallDuration
|
||||
)
|
||||
} else {
|
||||
SendMessage(
|
||||
chatType = chatType,
|
||||
peerId = userId.toString(),
|
||||
peerId = userId,
|
||||
message = if (session.isArray("message")) session.getArray("message") else listOf(session.getObject("message")).jsonArray,
|
||||
echo = session.echo,
|
||||
fromId = groupId?.toString() ?: userId.toString(),
|
||||
fromId = groupId?.toString() ?: userId,
|
||||
retryCnt = retryCnt ?: 5,
|
||||
recallDuration = recallDuration
|
||||
)
|
||||
|
@ -22,7 +22,7 @@ import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||
import moe.fuqiuluo.shamrock.helper.TransfileHelper
|
||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||
import moe.fuqiuluo.shamrock.remote.service.api.RichMediaUploadHandler
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.RichMediaUploadHandler
|
||||
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||
import moe.fuqiuluo.shamrock.utils.MD5
|
||||
|
@ -0,0 +1,63 @@
|
||||
package moe.fuqiuluo.shamrock.remote.action.handlers
|
||||
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import moe.fuqiuluo.qqinterface.servlet.structures.CommFileInfo
|
||||
import moe.fuqiuluo.qqinterface.servlet.structures.UploadResult
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc
|
||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||
import moe.fuqiuluo.symbols.OneBotHandler
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@OneBotHandler("upload_group_image", ["upload_group_pic"])
|
||||
internal object UploadGroupPic: IActionHandler() {
|
||||
override suspend fun internalHandle(session: ActionSession): String {
|
||||
val pic = session.getString("file")
|
||||
return invoke(pic, session.echo)
|
||||
}
|
||||
|
||||
suspend operator fun invoke(
|
||||
picture: String,
|
||||
echo: JsonElement = EmptyJsonString
|
||||
): String {
|
||||
if (ShamrockConfig.isDev()) {
|
||||
val file = picture.let {
|
||||
val md5 = it.replace(
|
||||
regex = "[{}\\-]".toRegex(),
|
||||
replacement = ""
|
||||
).split(".")[0].lowercase()
|
||||
if (md5.length == 32) {
|
||||
FileUtils.getFileByMd5(it)
|
||||
} else {
|
||||
FileUtils.parseAndSave(it)
|
||||
}
|
||||
}
|
||||
if (!file.exists()) {
|
||||
return logic("picture file is not exists", echo)
|
||||
}
|
||||
NtV2RichMediaSvc.tryUploadGroupPicByNt(
|
||||
imageFiles = arrayListOf(file),
|
||||
timeout = 30.seconds
|
||||
).onSuccess {
|
||||
return ok(UploadResult(it.map {
|
||||
CommFileInfo(
|
||||
modeId = it.fileModelId,
|
||||
fileName = it.fileName,
|
||||
fileSize = it.fileSize,
|
||||
md5 = it.md5,
|
||||
uuid = it.uuid,
|
||||
subId = it.subId
|
||||
)
|
||||
}), echo)
|
||||
}.onFailure {
|
||||
return logic("upload failed: ${it.message ?: it.toString()}", echo)
|
||||
}
|
||||
}
|
||||
return logic("upload failed", echo)
|
||||
}
|
||||
|
||||
override val requiredParams: Array<String> = arrayOf("file")
|
||||
}
|
@ -14,16 +14,13 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import moe.fuqiuluo.shamrock.helper.ContactHelper
|
||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||
import moe.fuqiuluo.shamrock.helper.TransfileHelper
|
||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||
import moe.fuqiuluo.shamrock.remote.service.api.RichMediaUploadHandler
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.RichMediaUploadHandler
|
||||
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||
import moe.fuqiuluo.shamrock.utils.MD5
|
||||
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
||||
import moe.fuqiuluo.qqinterface.servlet.msg.MessageTempHandler
|
||||
import moe.fuqiuluo.qqinterface.servlet.msg.toCQCode
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
|
||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||
@ -16,7 +17,7 @@ import moe.fuqiuluo.shamrock.helper.Level
|
||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||
import moe.fuqiuluo.shamrock.helper.db.MessageDB
|
||||
import moe.fuqiuluo.shamrock.remote.service.api.GlobalEventTransmitter
|
||||
import moe.fuqiuluo.shamrock.remote.service.api.RichMediaUploadHandler
|
||||
import moe.fuqiuluo.qqinterface.servlet.transfile.RichMediaUploadHandler
|
||||
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageTempSource
|
||||
import moe.fuqiuluo.shamrock.remote.service.data.push.PostType
|
||||
import java.util.ArrayList
|
||||
@ -24,9 +25,6 @@ import java.util.Collections
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
internal object AioListener : IKernelMsgListener {
|
||||
// 通过MSG SEQ临时监听器
|
||||
private val tempMessageListenerMap = Collections.synchronizedMap(HashMap<Long, suspend MsgRecord.() -> Unit>())
|
||||
|
||||
override fun onRecvMsg(msgList: ArrayList<MsgRecord>) {
|
||||
if (msgList.isEmpty()) return
|
||||
|
||||
@ -37,27 +35,9 @@ internal object AioListener : IKernelMsgListener {
|
||||
}
|
||||
}
|
||||
|
||||
fun registerTemporaryMsgListener(
|
||||
msgSeq: Long,
|
||||
listener: suspend MsgRecord.() -> Unit
|
||||
) {
|
||||
LogCenter.log({ "注册临时消息监听器: $msgSeq" }, Level.DEBUG)
|
||||
tempMessageListenerMap[msgSeq] = listener
|
||||
}
|
||||
|
||||
fun unregisterTemporaryMsgListener(msgSeq: Long) {
|
||||
tempMessageListenerMap.remove(msgSeq)
|
||||
}
|
||||
|
||||
private suspend fun handleMsg(record: MsgRecord) {
|
||||
try {
|
||||
tempMessageListenerMap.firstNotNullOfOrNull {
|
||||
if (it.key == record.msgSeq) it else null
|
||||
}?.let {
|
||||
it.value(record)
|
||||
tempMessageListenerMap.remove(it.key)
|
||||
return
|
||||
}
|
||||
if (MessageTempHandler.notify(record)) return
|
||||
if (record.msgSeq < 0) return
|
||||
|
||||
val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId)
|
||||
@ -432,7 +412,7 @@ internal object AioListener : IKernelMsgListener {
|
||||
}
|
||||
|
||||
override fun onRichMediaUploadComplete(notifyInfo: FileTransNotifyInfo) {
|
||||
LogCenter.log("onRichMediaUploadComplete($notifyInfo)", Level.DEBUG)
|
||||
LogCenter.log("[BDH] 资源上传完成(${notifyInfo.trasferStatus}, ${notifyInfo.fileId}, ${notifyInfo.msgId}, ${notifyInfo.commonFileInfo})")
|
||||
RichMediaUploadHandler.notify(notifyInfo)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user