mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Shamrock
: 实现事件推送
Signed-off-by: 白池 <whitechi73@outlook.com>
This commit is contained in:
parent
a95d8d85e8
commit
3a07116093
@ -1,28 +1,41 @@
|
|||||||
package kritor.service
|
package kritor.service
|
||||||
|
|
||||||
|
import io.grpc.Status
|
||||||
|
import io.grpc.StatusRuntimeException
|
||||||
import io.kritor.event.EventRequest
|
import io.kritor.event.EventRequest
|
||||||
import io.kritor.event.EventServiceGrpcKt
|
import io.kritor.event.EventServiceGrpcKt
|
||||||
import io.kritor.event.EventStructure
|
import io.kritor.event.EventStructure
|
||||||
import io.kritor.event.EventType
|
import io.kritor.event.EventType
|
||||||
|
import io.kritor.event.RequestPushEvent
|
||||||
import io.kritor.event.eventStructure
|
import io.kritor.event.eventStructure
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.channelFlow
|
import kotlinx.coroutines.flow.channelFlow
|
||||||
import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter
|
import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter
|
||||||
|
|
||||||
object EventService: EventServiceGrpcKt.EventServiceCoroutineImplBase() {
|
object EventService: EventServiceGrpcKt.EventServiceCoroutineImplBase() {
|
||||||
override fun registerActiveListener(request: EventRequest): Flow<EventStructure> {
|
override fun registerActiveListener(request: RequestPushEvent): Flow<EventStructure> {
|
||||||
return channelFlow {
|
return channelFlow {
|
||||||
when(request.type!!) {
|
when(request.type!!) {
|
||||||
EventType.CORE_EVENT -> TODO()
|
EventType.EVENT_TYPE_CORE_EVENT -> {}
|
||||||
EventType.MESSAGE -> GlobalEventTransmitter.onMessageEvent {
|
EventType.EVENT_TYPE_MESSAGE -> GlobalEventTransmitter.onMessageEvent {
|
||||||
send(eventStructure {
|
send(eventStructure {
|
||||||
this.type = EventType.MESSAGE
|
this.type = EventType.EVENT_TYPE_MESSAGE
|
||||||
this.message = it.second
|
this.message = it.second
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
EventType.NOTICE -> TODO()
|
EventType.EVENT_TYPE_NOTICE -> GlobalEventTransmitter.onRequestEvent {
|
||||||
EventType.REQUEST -> TODO()
|
send(eventStructure {
|
||||||
EventType.UNRECOGNIZED -> TODO()
|
this.type = EventType.EVENT_TYPE_NOTICE
|
||||||
|
this.request = it
|
||||||
|
})
|
||||||
|
}
|
||||||
|
EventType.EVENT_TYPE_REQUEST -> GlobalEventTransmitter.onNoticeEvent {
|
||||||
|
send(eventStructure {
|
||||||
|
this.type = EventType.EVENT_TYPE_NOTICE
|
||||||
|
this.notice = it
|
||||||
|
})
|
||||||
|
}
|
||||||
|
EventType.UNRECOGNIZED -> throw StatusRuntimeException(Status.INVALID_ARGUMENT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,42 @@ package moe.fuqiuluo.shamrock.internals
|
|||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
|
import io.kritor.event.GroupApplyType
|
||||||
|
import io.kritor.event.GroupMemberBanType
|
||||||
|
import io.kritor.event.GroupMemberDecreasedType
|
||||||
|
import io.kritor.event.GroupMemberIncreasedType
|
||||||
import io.kritor.event.MessageEvent
|
import io.kritor.event.MessageEvent
|
||||||
|
import io.kritor.event.NoticeEvent
|
||||||
|
import io.kritor.event.NoticeType
|
||||||
|
import io.kritor.event.RequestType
|
||||||
|
import io.kritor.event.RequestsEvent
|
||||||
import io.kritor.event.Scene
|
import io.kritor.event.Scene
|
||||||
import io.kritor.event.contact
|
import io.kritor.event.contact
|
||||||
|
import io.kritor.event.essenceMessageNotice
|
||||||
|
import io.kritor.event.friendApplyRequest
|
||||||
|
import io.kritor.event.friendFileComeNotice
|
||||||
|
import io.kritor.event.friendPokeNotice
|
||||||
|
import io.kritor.event.friendRecallNotice
|
||||||
|
import io.kritor.event.groupAdminChangedNotice
|
||||||
|
import io.kritor.event.groupApplyRequest
|
||||||
|
import io.kritor.event.groupFileComeNotice
|
||||||
|
import io.kritor.event.groupMemberBannedNotice
|
||||||
|
import io.kritor.event.groupMemberDecreasedNotice
|
||||||
|
import io.kritor.event.groupMemberIncreasedNotice
|
||||||
|
import io.kritor.event.groupPokeNotice
|
||||||
|
import io.kritor.event.groupRecallNotice
|
||||||
|
import io.kritor.event.groupSignNotice
|
||||||
|
import io.kritor.event.groupUniqueTitleChangedNotice
|
||||||
|
import io.kritor.event.groupWholeBanNotice
|
||||||
import io.kritor.event.messageEvent
|
import io.kritor.event.messageEvent
|
||||||
|
import io.kritor.event.noticeEvent
|
||||||
|
import io.kritor.event.requestsEvent
|
||||||
import io.kritor.event.sender
|
import io.kritor.event.sender
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.flow.FlowCollector
|
import kotlinx.coroutines.flow.FlowCollector
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.io.core.BytePacketBuilder
|
|
||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
import qq.service.msg.toKritorMessages
|
import qq.service.msg.toKritorMessages
|
||||||
|
|
||||||
@ -22,16 +47,16 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
private val messageEventFlow by lazy {
|
private val messageEventFlow by lazy {
|
||||||
MutableSharedFlow<Pair<MsgRecord, MessageEvent>>()
|
MutableSharedFlow<Pair<MsgRecord, MessageEvent>>()
|
||||||
}
|
}
|
||||||
//private val noticeEventFlow by lazy {
|
private val noticeEventFlow by lazy {
|
||||||
// MutableSharedFlow<NoticeEvent>()
|
MutableSharedFlow<NoticeEvent>()
|
||||||
//}
|
}
|
||||||
//private val requestEventFlow by lazy {
|
private val requestEventFlow by lazy {
|
||||||
// MutableSharedFlow<RequestEvent>()
|
MutableSharedFlow<RequestsEvent>()
|
||||||
//}
|
}
|
||||||
|
|
||||||
//private suspend fun pushNotice(noticeEvent: NoticeEvent) = noticeEventFlow.emit(noticeEvent)
|
private suspend fun pushNotice(noticeEvent: NoticeEvent) = noticeEventFlow.emit(noticeEvent)
|
||||||
|
|
||||||
//private suspend fun pushRequest(requestEvent: RequestEvent) = requestEventFlow.emit(requestEvent)
|
private suspend fun pushRequest(requestEvent: RequestsEvent) = requestEventFlow.emit(requestEvent)
|
||||||
|
|
||||||
private suspend fun transMessageEvent(record: MsgRecord, message: MessageEvent) = messageEventFlow.emit(record to message)
|
private suspend fun transMessageEvent(record: MsgRecord, message: MessageEvent) = messageEventFlow.emit(record to message)
|
||||||
|
|
||||||
@ -135,10 +160,9 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
/**
|
/**
|
||||||
* 文件通知 通知器
|
* 文件通知 通知器
|
||||||
*/
|
**/
|
||||||
object FileNoticeTransmitter {
|
object FileNoticeTransmitter {
|
||||||
/**
|
/**
|
||||||
* 推送私聊文件事件
|
* 推送私聊文件事件
|
||||||
@ -153,23 +177,19 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
expireTime: Long,
|
expireTime: Long,
|
||||||
url: String
|
url: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = msgTime,
|
this.type = NoticeType.FRIEND_FILE_COME
|
||||||
selfId = app.longAccountUin,
|
this.time = msgTime.toInt()
|
||||||
postType = PostType.Notice,
|
this.friendFileCome = friendFileComeNotice {
|
||||||
type = NoticeType.PrivateUpload,
|
this.fileId = fileId
|
||||||
operatorId = userId,
|
this.fileName = fileName
|
||||||
userId = userId,
|
this.operator = userId
|
||||||
senderId = userId,
|
this.fileSize = fileSize
|
||||||
privateFile = PrivateFileMsg(
|
this.expireTime = expireTime.toInt()
|
||||||
id = fileId,
|
this.fileSubId = fileSubId
|
||||||
name = fileName,
|
this.url = url
|
||||||
size = fileSize,
|
}
|
||||||
url = url,
|
})
|
||||||
subId = fileSubId,
|
|
||||||
expire = expireTime
|
|
||||||
)
|
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,22 +206,19 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
bizId: Int,
|
bizId: Int,
|
||||||
url: String
|
url: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = msgTime,
|
this.type = NoticeType.GROUP_FILE_COME
|
||||||
selfId = app.longAccountUin,
|
this.time = msgTime.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupFileCome = groupFileComeNotice {
|
||||||
type = NoticeType.GroupUpload,
|
this.groupId = groupId
|
||||||
operatorId = userId,
|
this.operator = userId
|
||||||
userId = userId,
|
this.fileId = uuid
|
||||||
groupId = groupId,
|
this.fileName = fileName
|
||||||
file = GroupFileMsg(
|
this.fileSize = fileSize
|
||||||
id = uuid,
|
this.biz = bizId
|
||||||
name = fileName,
|
this.url = url
|
||||||
size = fileSize,
|
}
|
||||||
busid = bizId.toLong(),
|
})
|
||||||
url = url
|
|
||||||
)
|
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,68 +228,80 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
*/
|
*/
|
||||||
object GroupNoticeTransmitter {
|
object GroupNoticeTransmitter {
|
||||||
suspend fun transGroupSign(time: Long, target: Long, action: String?, rankImg: String?, groupCode: Long): Boolean {
|
suspend fun transGroupSign(time: Long, target: Long, action: String?, rankImg: String?, groupCode: Long): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = time,
|
this.type = NoticeType.GROUP_SIGN
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupSign = groupSignNotice {
|
||||||
type = NoticeType.Notify,
|
this.groupId = groupCode
|
||||||
subType = NoticeSubType.Sign,
|
this.targetUin = target
|
||||||
userId = target,
|
this.action = action ?: ""
|
||||||
groupId = groupCode,
|
this.suffix = ""
|
||||||
target = target,
|
this.rankImage = rankImg ?: ""
|
||||||
signDetail = SignDetail(
|
}
|
||||||
rankImg = rankImg,
|
})
|
||||||
action = action
|
|
||||||
)
|
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun transGroupPoke(time: Long, operation: Long, target: Long, action: String?, suffix: String?, actionImg: String?, groupCode: Long): Boolean {
|
suspend fun transGroupPoke(time: Long, operator: Long, target: Long, action: String?, suffix: String?, actionImg: String?, groupCode: Long): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = time,
|
this.type = NoticeType.GROUP_POKE
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupPoke = groupPokeNotice {
|
||||||
type = NoticeType.Notify,
|
this.action = action ?: ""
|
||||||
subType = NoticeSubType.Poke,
|
this.target = target
|
||||||
operatorId = operation,
|
this.operator = operator
|
||||||
userId = operation,
|
this.suffix = suffix ?: ""
|
||||||
groupId = groupCode,
|
this.actionImage = actionImg ?: ""
|
||||||
target = target,
|
}
|
||||||
pokeDetail = PokeDetail(
|
})
|
||||||
action = action,
|
|
||||||
suffix = suffix,
|
|
||||||
actionImg = actionImg
|
|
||||||
)
|
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun transGroupMemberNumChanged(
|
suspend fun transGroupMemberNumIncreased(
|
||||||
time: Long,
|
time: Long,
|
||||||
target: Long,
|
target: Long,
|
||||||
targetUid: String,
|
targetUid: String,
|
||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
operator: Long,
|
operator: Long,
|
||||||
operatorUid: String,
|
operatorUid: String,
|
||||||
noticeType: NoticeType,
|
type: GroupMemberIncreasedType
|
||||||
noticeSubType: NoticeSubType
|
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = time,
|
this.type = NoticeType.GROUP_MEMBER_INCREASE
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupMemberIncrease = groupMemberIncreasedNotice {
|
||||||
type = noticeType,
|
this.groupId = groupCode
|
||||||
subType = noticeSubType,
|
this.operatorUid = operatorUid
|
||||||
operatorId = operator,
|
this.operatorUin = operator
|
||||||
userId = target,
|
this.targetUid = targetUid
|
||||||
senderId = operator,
|
this.targetUin = target
|
||||||
target = target,
|
this.type = type
|
||||||
groupId = groupCode,
|
}
|
||||||
targetUid = targetUid,
|
})
|
||||||
operatorUid = operatorUid,
|
return true
|
||||||
userUid = targetUid
|
}
|
||||||
))
|
|
||||||
|
suspend fun transGroupMemberNumDecreased(
|
||||||
|
time: Long,
|
||||||
|
target: Long,
|
||||||
|
targetUid: String,
|
||||||
|
groupCode: Long,
|
||||||
|
operator: Long,
|
||||||
|
operatorUid: String,
|
||||||
|
type: GroupMemberDecreasedType
|
||||||
|
): Boolean {
|
||||||
|
pushNotice(noticeEvent {
|
||||||
|
this.type = NoticeType.GROUP_MEMBER_INCREASE
|
||||||
|
this.time = time.toInt()
|
||||||
|
this.groupMemberDecrease = groupMemberDecreasedNotice {
|
||||||
|
this.groupId = groupCode
|
||||||
|
this.operatorUid = operatorUid
|
||||||
|
this.operatorUin = operator
|
||||||
|
this.targetUid = targetUid
|
||||||
|
this.targetUin = target
|
||||||
|
this.type = type
|
||||||
|
}
|
||||||
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,25 +312,39 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
setAdmin: Boolean
|
setAdmin: Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = msgTime,
|
this.type = NoticeType.GROUP_ADMIN_CHANGED
|
||||||
selfId = app.longAccountUin,
|
this.time = msgTime.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupAdminChanged = groupAdminChangedNotice {
|
||||||
type = NoticeType.GroupAdminChange,
|
this.groupId = groupCode
|
||||||
subType = if (setAdmin) NoticeSubType.Set else NoticeSubType.UnSet,
|
this.targetUid = targetUid
|
||||||
operatorId = 0,
|
this.targetUin = target
|
||||||
userId = target,
|
this.isAdmin = setAdmin
|
||||||
userUid = targetUid,
|
}
|
||||||
target = target,
|
})
|
||||||
targetUid = targetUid,
|
return true
|
||||||
groupId = groupCode
|
}
|
||||||
))
|
|
||||||
|
suspend fun transGroupWholeBan(
|
||||||
|
msgTime: Long,
|
||||||
|
operator: Long,
|
||||||
|
groupCode: Long,
|
||||||
|
isOpen: Boolean
|
||||||
|
): Boolean {
|
||||||
|
pushNotice(noticeEvent {
|
||||||
|
this.type = NoticeType.GROUP_WHOLE_BAN
|
||||||
|
this.time = msgTime.toInt()
|
||||||
|
this.groupWholeBan = groupWholeBanNotice {
|
||||||
|
this.groupId = groupCode
|
||||||
|
this.isWholeBan = isOpen
|
||||||
|
this.operator = operator
|
||||||
|
}
|
||||||
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun transGroupBan(
|
suspend fun transGroupBan(
|
||||||
msgTime: Long,
|
msgTime: Long,
|
||||||
subType: NoticeSubType,
|
|
||||||
operator: Long,
|
operator: Long,
|
||||||
operatorUid: String,
|
operatorUid: String,
|
||||||
target: Long,
|
target: Long,
|
||||||
@ -309,43 +352,46 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
duration: Int
|
duration: Int
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = msgTime,
|
this.type = NoticeType.GROUP_MEMBER_BANNED
|
||||||
selfId = app.longAccountUin,
|
this.time = msgTime.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupMemberBanned = groupMemberBannedNotice {
|
||||||
type = NoticeType.GroupBan,
|
this.groupId = groupCode
|
||||||
subType = subType,
|
this.operatorUid = operatorUid
|
||||||
operatorId = operator,
|
this.operatorUin = operator
|
||||||
userId = target,
|
this.targetUid = targetUid
|
||||||
senderId = operator,
|
this.targetUin = target
|
||||||
target = target,
|
this.duration = duration
|
||||||
groupId = groupCode,
|
this.type = if (duration > 0) GroupMemberBanType.BAN
|
||||||
duration = duration,
|
else GroupMemberBanType.LIFT_BAN
|
||||||
operatorUid = operatorUid,
|
}
|
||||||
targetUid = targetUid
|
})
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun transGroupMsgRecall(
|
suspend fun transGroupMsgRecall(
|
||||||
time: Long,
|
time: Long,
|
||||||
operator: Long,
|
operator: Long,
|
||||||
|
operatorUid: String,
|
||||||
target: Long,
|
target: Long,
|
||||||
|
targetUid: String,
|
||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
msgHash: Int,
|
msgId: Long,
|
||||||
tipText: String
|
tipText: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = time,
|
this.type = NoticeType.GROUP_RECALL
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupRecall = groupRecallNotice {
|
||||||
type = NoticeType.GroupRecall,
|
this.groupId = groupCode
|
||||||
operatorId = operator,
|
this.operatorUid = operatorUid
|
||||||
userId = target,
|
this.operatorUin = operator
|
||||||
msgId = msgHash,
|
this.targetUid = targetUid
|
||||||
tip = tipText,
|
this.targetUin = target
|
||||||
groupId = groupCode
|
this.messageId = msgId
|
||||||
))
|
this.tipText = tipText
|
||||||
|
}
|
||||||
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,16 +402,7 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
newCard: String,
|
newCard: String,
|
||||||
groupId: Long
|
groupId: Long
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
|
||||||
time = time,
|
|
||||||
selfId = app.longAccountUin,
|
|
||||||
postType = PostType.Notice,
|
|
||||||
type = NoticeType.GroupCard,
|
|
||||||
userId = targetId,
|
|
||||||
cardNew = newCard,
|
|
||||||
cardOld = oldCard,
|
|
||||||
groupId = groupId
|
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,16 +412,15 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
title: String,
|
title: String,
|
||||||
groupId: Long
|
groupId: Long
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = time,
|
this.type = NoticeType.GROUP_MEMBER_UNIQUE_TITLE_CHANGED
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupMemberUniqueTitleChanged = groupUniqueTitleChangedNotice {
|
||||||
type = NoticeType.Notify,
|
this.groupId = groupId
|
||||||
userId = targetId,
|
this.target = targetId
|
||||||
groupId = groupId,
|
this.title = title
|
||||||
title = title,
|
}
|
||||||
subType = NoticeSubType.Title
|
})
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,21 +428,21 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
time: Long,
|
time: Long,
|
||||||
senderUin: Long,
|
senderUin: Long,
|
||||||
operatorUin: Long,
|
operatorUin: Long,
|
||||||
msgId: Int,
|
msgId: Long,
|
||||||
groupId: Long,
|
groupId: Long,
|
||||||
subType: NoticeSubType
|
subType: UInt
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = time,
|
this.type = NoticeType.GROUP_ESSENCE_CHANGED
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Notice,
|
this.groupEssenceChanged = essenceMessageNotice {
|
||||||
type = NoticeType.Essence,
|
this.groupId = groupId
|
||||||
senderId = senderUin,
|
this.messageId = msgId
|
||||||
groupId = groupId,
|
this.sender = senderUin
|
||||||
operatorId = operatorUin,
|
this.operator = operatorUin
|
||||||
msgId = msgId,
|
this.subType = subType.toInt()
|
||||||
subType = subType
|
}
|
||||||
))
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,37 +451,31 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
* 私聊通知 通知器
|
* 私聊通知 通知器
|
||||||
*/
|
*/
|
||||||
object PrivateNoticeTransmitter {
|
object PrivateNoticeTransmitter {
|
||||||
suspend fun transPrivatePoke(msgTime: Long, operation: Long, target: Long, action: String?, suffix: String?, actionImg: String?): Boolean {
|
suspend fun transPrivatePoke(msgTime: Long, operator: Long, target: Long, action: String?, suffix: String?, actionImg: String?): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = msgTime,
|
this.type = NoticeType.FRIEND_POKE
|
||||||
selfId = app.longAccountUin,
|
this.time = msgTime.toInt()
|
||||||
postType = PostType.Notice,
|
this.friendPoke = friendPokeNotice {
|
||||||
type = NoticeType.Notify,
|
this.action = action ?: ""
|
||||||
subType = NoticeSubType.Poke,
|
this.target = target
|
||||||
operatorId = operation,
|
this.operator = operator
|
||||||
userId = operation,
|
this.suffix = suffix ?: ""
|
||||||
senderId = operation,
|
this.actionImage = actionImg ?: ""
|
||||||
target = target,
|
}
|
||||||
pokeDetail = PokeDetail(
|
})
|
||||||
actionImg = actionImg,
|
|
||||||
action = action,
|
|
||||||
suffix = suffix
|
|
||||||
)
|
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun transPrivateRecall(time: Long, operation: Long, msgHashId: Int, tipText: String): Boolean {
|
suspend fun transPrivateRecall(time: Long, operator: Long, msgId: Long, tipText: String): Boolean {
|
||||||
pushNotice(NoticeEvent(
|
pushNotice(noticeEvent {
|
||||||
time = time,
|
this.type = NoticeType.FRIEND_RECALL
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Notice,
|
this.friendRecall = friendRecallNotice {
|
||||||
type = NoticeType.FriendRecall,
|
this.operator = operator
|
||||||
operatorId = operation,
|
this.messageId = msgId
|
||||||
userId = operation,
|
this.tipText = tipText
|
||||||
msgId = msgHashId,
|
}
|
||||||
tip = tipText
|
})
|
||||||
))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,16 +485,16 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
* 请求 通知器
|
* 请求 通知器
|
||||||
*/
|
*/
|
||||||
object RequestTransmitter {
|
object RequestTransmitter {
|
||||||
suspend fun transFriendApp(time: Long, operation: Long, tipText: String, flag: String): Boolean {
|
suspend fun transFriendApp(time: Long, operator: Long, tipText: String, flag: String): Boolean {
|
||||||
pushRequest(RequestEvent(
|
pushRequest(requestsEvent {
|
||||||
time = time,
|
this.type = RequestType.FRIEND_APPLY
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Request,
|
this.friendApply = friendApplyRequest {
|
||||||
type = RequestType.Friend,
|
this.applierUin = operator
|
||||||
userId = operation,
|
this.message = tipText
|
||||||
comment = tipText,
|
this.flag = flag
|
||||||
flag = flag
|
}
|
||||||
))
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,23 +505,23 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
reason: String,
|
reason: String,
|
||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
flag: String,
|
flag: String,
|
||||||
subType: RequestSubType
|
type: GroupApplyType
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushRequest(RequestEvent(
|
pushRequest(requestsEvent {
|
||||||
time = time,
|
this.type = RequestType.GROUP_APPLY
|
||||||
selfId = app.longAccountUin,
|
this.time = time.toInt()
|
||||||
postType = PostType.Request,
|
this.groupApply = groupApplyRequest {
|
||||||
type = RequestType.Group,
|
this.applierUid = applierUid
|
||||||
userId = applier,
|
this.applierUin = applier
|
||||||
userUid = applierUid,
|
this.groupId = groupCode
|
||||||
comment = reason,
|
this.reason = reason
|
||||||
groupId = groupCode,
|
this.flag = flag
|
||||||
subType = subType,
|
this.type = type
|
||||||
flag = flag
|
}
|
||||||
))
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
suspend inline fun onMessageEvent(collector: FlowCollector<Pair<MsgRecord, MessageEvent>>) {
|
suspend inline fun onMessageEvent(collector: FlowCollector<Pair<MsgRecord, MessageEvent>>) {
|
||||||
messageEventFlow.collect {
|
messageEventFlow.collect {
|
||||||
@ -501,7 +531,6 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
suspend inline fun onNoticeEvent(collector: FlowCollector<NoticeEvent>) {
|
suspend inline fun onNoticeEvent(collector: FlowCollector<NoticeEvent>) {
|
||||||
noticeEventFlow.collect {
|
noticeEventFlow.collect {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
@ -510,11 +539,11 @@ internal object GlobalEventTransmitter: QQInterfaces() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun onRequestEvent(collector: FlowCollector<RequestEvent>) {
|
suspend inline fun onRequestEvent(collector: FlowCollector<RequestsEvent>) {
|
||||||
requestEventFlow.collect {
|
requestEventFlow.collect {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
collector.emit(it)
|
collector.emit(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
@ -3,11 +3,15 @@ package qq.service.friend
|
|||||||
import com.tencent.mobileqq.data.Friends
|
import com.tencent.mobileqq.data.Friends
|
||||||
import com.tencent.mobileqq.friend.api.IFriendDataService
|
import com.tencent.mobileqq.friend.api.IFriendDataService
|
||||||
import com.tencent.mobileqq.friend.api.IFriendHandlerService
|
import com.tencent.mobileqq.friend.api.IFriendHandlerService
|
||||||
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
|
import com.tencent.mobileqq.relation.api.IAddFriendTempApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
|
import tencent.mobileim.structmsg.structmsg
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal object FriendHelper: QQInterfaces() {
|
internal object FriendHelper: QQInterfaces() {
|
||||||
@ -21,6 +25,69 @@ internal object FriendHelper: QQInterfaces() {
|
|||||||
return Result.success(service.allFriends)
|
return Result.success(service.allFriends)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProfileService.Pb.ReqSystemMsgAction.Friend
|
||||||
|
fun requestFriendRequest(msgSeq: Long, uin: Long, remark: String = "", approve: Boolean? = true, notSee: Boolean? = false) {
|
||||||
|
val service = QRoute.api(IAddFriendTempApi::class.java)
|
||||||
|
val action = structmsg.SystemMsgActionInfo()
|
||||||
|
action.type.set(if (approve != false) 2 else 3)
|
||||||
|
action.group_id.set(0)
|
||||||
|
action.remark.set(remark)
|
||||||
|
val snInfo = structmsg.AddFrdSNInfo()
|
||||||
|
snInfo.uint32_not_see_dynamic.set(if (notSee != false) 1 else 0)
|
||||||
|
snInfo.uint32_set_sn.set(0)
|
||||||
|
action.addFrdSNInfo.set(snInfo)
|
||||||
|
service.sendFriendSystemMsgAction(1, msgSeq, uin, 1, 2004, 11, 0, action, 0, structmsg.StructMsg(), false, app)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun requestFriendSystemMsgNew(msgNum: Int, latestFriendSeq: Long = 0, latestGroupSeq: Long = 0, retryCnt: Int = 3): List<structmsg.StructMsg>? {
|
||||||
|
if (retryCnt < 0) {
|
||||||
|
return ArrayList()
|
||||||
|
}
|
||||||
|
val req = structmsg.ReqSystemMsgNew()
|
||||||
|
req.msg_num.set(msgNum)
|
||||||
|
req.latest_friend_seq.set(latestFriendSeq)
|
||||||
|
req.latest_group_seq.set(latestGroupSeq)
|
||||||
|
req.version.set(1000)
|
||||||
|
req.checktype.set(2)
|
||||||
|
val flag = structmsg.FlagInfo()
|
||||||
|
// flag.GrpMsg_Kick_Admin.set(1)
|
||||||
|
// flag.GrpMsg_HiddenGrp.set(1)
|
||||||
|
// flag.GrpMsg_WordingDown.set(1)
|
||||||
|
flag.FrdMsg_GetBusiCard.set(1)
|
||||||
|
// flag.GrpMsg_GetOfficialAccount.set(1)
|
||||||
|
// flag.GrpMsg_GetPayInGroup.set(1)
|
||||||
|
flag.FrdMsg_Discuss2ManyChat.set(1)
|
||||||
|
// flag.GrpMsg_NotAllowJoinGrp_InviteNotFrd.set(1)
|
||||||
|
flag.FrdMsg_NeedWaitingMsg.set(1)
|
||||||
|
flag.FrdMsg_uint32_need_all_unread_msg.set(1)
|
||||||
|
// flag.GrpMsg_NeedAutoAdminWording.set(1)
|
||||||
|
// flag.GrpMsg_get_transfer_group_msg_flag.set(1)
|
||||||
|
// flag.GrpMsg_get_quit_pay_group_msg_flag.set(1)
|
||||||
|
// flag.GrpMsg_support_invite_auto_join.set(1)
|
||||||
|
// flag.GrpMsg_mask_invite_auto_join.set(1)
|
||||||
|
// flag.GrpMsg_GetDisbandedByAdmin.set(1)
|
||||||
|
flag.GrpMsg_GetC2cInviteJoinGroup.set(1)
|
||||||
|
req.flag.set(flag)
|
||||||
|
req.is_get_frd_ribbon.set(false)
|
||||||
|
req.is_get_grp_ribbon.set(false)
|
||||||
|
req.friend_msg_type_flag.set(1)
|
||||||
|
req.uint32_req_msg_type.set(1)
|
||||||
|
req.uint32_need_uid.set(1)
|
||||||
|
val fromServiceMsg = sendBufferAW("ProfileService.Pb.ReqSystemMsgNew.Friend", true, req.toByteArray())
|
||||||
|
return if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
||||||
|
ArrayList()
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
val msg = structmsg.RspSystemMsgNew()
|
||||||
|
msg.mergeFrom(fromServiceMsg.wupBuffer.slice(4))
|
||||||
|
return msg.friendmsgs.get()
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
requestFriendSystemMsgNew(msgNum, latestFriendSeq, latestGroupSeq, retryCnt - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun requestFriendList(dataService: IFriendDataService): Boolean {
|
private suspend fun requestFriendList(dataService: IFriendDataService): Boolean {
|
||||||
val service = app.getRuntimeService(IFriendHandlerService::class.java, "all")
|
val service = app.getRuntimeService(IFriendHandlerService::class.java, "all")
|
||||||
service.requestFriendList(true, 0)
|
service.requestFriendList(true, 0)
|
||||||
|
@ -37,6 +37,7 @@ import tencent.im.oidb.cmd0x8fc.Oidb_0x8fc
|
|||||||
import tencent.im.oidb.cmd0xed3.oidb_cmd0xed3
|
import tencent.im.oidb.cmd0xed3.oidb_cmd0xed3
|
||||||
import tencent.im.oidb.oidb_sso
|
import tencent.im.oidb.oidb_sso
|
||||||
import tencent.im.troop.honor.troop_honor
|
import tencent.im.troop.honor.troop_honor
|
||||||
|
import tencent.mobileim.structmsg.structmsg
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
@ -217,6 +218,106 @@ internal object GroupHelper: QQInterfaces() {
|
|||||||
sendOidb("OidbSvc.0x55c_1", 1372, 1, array)
|
sendOidb("OidbSvc.0x55c_1", 1372, 1, array)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProfileService.Pb.ReqSystemMsgAction.Group
|
||||||
|
suspend fun requestGroupRequest(
|
||||||
|
msgSeq: Long,
|
||||||
|
uin: Long,
|
||||||
|
gid: Long,
|
||||||
|
msg: String? = "",
|
||||||
|
approve: Boolean? = true,
|
||||||
|
notSee: Boolean? = false,
|
||||||
|
subType: String
|
||||||
|
): Result<String>{
|
||||||
|
val req = structmsg.ReqSystemMsgAction().apply {
|
||||||
|
if (subType == "invite") {
|
||||||
|
msg_type.set(1)
|
||||||
|
src_id.set(3)
|
||||||
|
sub_src_id.set(10016)
|
||||||
|
group_msg_type.set(2)
|
||||||
|
} else {
|
||||||
|
msg_type.set(2)
|
||||||
|
src_id.set(2)
|
||||||
|
sub_src_id.set(30024)
|
||||||
|
group_msg_type.set(1)
|
||||||
|
}
|
||||||
|
msg_seq.set(msgSeq)
|
||||||
|
req_uin.set(uin)
|
||||||
|
sub_type.set(1)
|
||||||
|
action_info.set(structmsg.SystemMsgActionInfo().apply {
|
||||||
|
type.set(if (approve != false) 11 else 12)
|
||||||
|
group_code.set(gid)
|
||||||
|
if (subType == "add") {
|
||||||
|
this.msg.set(msg)
|
||||||
|
this.blacklist.set(notSee != false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
language.set(1000)
|
||||||
|
}
|
||||||
|
val fromServiceMsg = sendBufferAW("ProfileService.Pb.ReqSystemMsgAction.Group", true, req.toByteArray())
|
||||||
|
?: return Result.failure(Exception("ReqSystemMsgAction.Group: No Response"))
|
||||||
|
if (fromServiceMsg.wupBuffer == null) {
|
||||||
|
return Result.failure(Exception("ReqSystemMsgAction.Group: No WupBuffer"))
|
||||||
|
}
|
||||||
|
val rsp = structmsg.RspSystemMsgAction().mergeFrom(fromServiceMsg.wupBuffer.slice(4))
|
||||||
|
return if (rsp.head.result.has()) {
|
||||||
|
if (rsp.head.result.get() == 0) {
|
||||||
|
Result.success(rsp.msg_detail.get())
|
||||||
|
} else {
|
||||||
|
Result.failure(Exception(rsp.head.msg_fail.get()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Result.failure(Exception("操作失败"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun requestGroupSystemMsgNew(msgNum: Int, reqMsgType: Int = 1, latestFriendSeq: Long = 0, latestGroupSeq: Long = 0, retryCnt: Int = 5): List<structmsg.StructMsg> {
|
||||||
|
if (retryCnt < 0) {
|
||||||
|
return ArrayList()
|
||||||
|
}
|
||||||
|
val req = structmsg.ReqSystemMsgNew()
|
||||||
|
req.msg_num.set(msgNum)
|
||||||
|
req.latest_friend_seq.set(latestFriendSeq)
|
||||||
|
req.latest_group_seq.set(latestGroupSeq)
|
||||||
|
req.version.set(1000)
|
||||||
|
req.checktype.set(3)
|
||||||
|
val flag = structmsg.FlagInfo()
|
||||||
|
flag.GrpMsg_Kick_Admin.set(1)
|
||||||
|
flag.GrpMsg_HiddenGrp.set(1)
|
||||||
|
flag.GrpMsg_WordingDown.set(1)
|
||||||
|
// flag.FrdMsg_GetBusiCard.set(1)
|
||||||
|
flag.GrpMsg_GetOfficialAccount.set(1)
|
||||||
|
flag.GrpMsg_GetPayInGroup.set(1)
|
||||||
|
flag.FrdMsg_Discuss2ManyChat.set(1)
|
||||||
|
flag.GrpMsg_NotAllowJoinGrp_InviteNotFrd.set(1)
|
||||||
|
flag.FrdMsg_NeedWaitingMsg.set(1)
|
||||||
|
// flag.FrdMsg_uint32_need_all_unread_msg.set(1)
|
||||||
|
flag.GrpMsg_NeedAutoAdminWording.set(1)
|
||||||
|
flag.GrpMsg_get_transfer_group_msg_flag.set(1)
|
||||||
|
flag.GrpMsg_get_quit_pay_group_msg_flag.set(1)
|
||||||
|
flag.GrpMsg_support_invite_auto_join.set(1)
|
||||||
|
flag.GrpMsg_mask_invite_auto_join.set(1)
|
||||||
|
flag.GrpMsg_GetDisbandedByAdmin.set(1)
|
||||||
|
flag.GrpMsg_GetC2cInviteJoinGroup.set(1)
|
||||||
|
req.flag.set(flag)
|
||||||
|
req.is_get_frd_ribbon.set(false)
|
||||||
|
req.is_get_grp_ribbon.set(false)
|
||||||
|
req.friend_msg_type_flag.set(1)
|
||||||
|
req.uint32_req_msg_type.set(reqMsgType)
|
||||||
|
req.uint32_need_uid.set(1)
|
||||||
|
val fromServiceMsg = sendBufferAW("ProfileService.Pb.ReqSystemMsgNew.Group", true, req.toByteArray())
|
||||||
|
return if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
||||||
|
ArrayList()
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
val msg = structmsg.RspSystemMsgNew()
|
||||||
|
msg.mergeFrom(fromServiceMsg.wupBuffer.slice(4))
|
||||||
|
return msg.groupmsgs.get().orEmpty()
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
requestGroupSystemMsgNew(msgNum, reqMsgType, latestFriendSeq, latestGroupSeq, retryCnt - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun setGroupUniqueTitle(groupId: Long, userId: Long, title: String) {
|
suspend fun setGroupUniqueTitle(groupId: Long, userId: Long, title: String) {
|
||||||
val localMemberInfo = getTroopMemberInfoByUin(groupId, userId, true).getOrThrow()
|
val localMemberInfo = getTroopMemberInfoByUin(groupId, userId, true).getOrThrow()
|
||||||
val req = Oidb_0x8fc.ReqBody()
|
val req = Oidb_0x8fc.ReqBody()
|
||||||
|
@ -10,6 +10,7 @@ import kotlinx.coroutines.launch
|
|||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter
|
import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter
|
||||||
|
import qq.service.bdh.RichProtoSvc
|
||||||
import qq.service.kernel.SimpleKernelMsgListener
|
import qq.service.kernel.SimpleKernelMsgListener
|
||||||
import qq.service.msg.MessageHelper
|
import qq.service.msg.MessageHelper
|
||||||
|
|
||||||
@ -29,6 +30,8 @@ object AioListener: SimpleKernelMsgListener() {
|
|||||||
private suspend fun onMsg(record: MsgRecord) {
|
private suspend fun onMsg(record: MsgRecord) {
|
||||||
when (record.chatType) {
|
when (record.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> {
|
MsgConstant.KCHATTYPEGROUP -> {
|
||||||
|
if (record.senderUin == 0L) return
|
||||||
|
|
||||||
LogCenter.log("群消息(group = ${record.peerName}(${record.peerUin}), uin = ${record.senderUin}, id = ${record.msgId})")
|
LogCenter.log("群消息(group = ${record.peerName}(${record.peerUin}), uin = ${record.senderUin}, id = ${record.msgId})")
|
||||||
|
|
||||||
if (!GlobalEventTransmitter.MessageTransmitter.transGroupMessage(record, record.elements)) {
|
if (!GlobalEventTransmitter.MessageTransmitter.transGroupMessage(record, record.elements)) {
|
||||||
@ -75,4 +78,63 @@ object AioListener: SimpleKernelMsgListener() {
|
|||||||
else -> LogCenter.log("不支持PUSH事件: ${record.chatType}")
|
else -> LogCenter.log("不支持PUSH事件: ${record.chatType}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onFileMsgCome(arrayList: ArrayList<MsgRecord>?) {
|
||||||
|
arrayList?.forEach { record ->
|
||||||
|
GlobalScope.launch {
|
||||||
|
when (record.chatType) {
|
||||||
|
MsgConstant.KCHATTYPEGROUP -> onGroupFileMsg(record)
|
||||||
|
MsgConstant.KCHATTYPEC2C -> onC2CFileMsg(record)
|
||||||
|
else -> LogCenter.log("不支持该来源的文件上传事件:${record}", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onC2CFileMsg(record: MsgRecord) {
|
||||||
|
val userId = record.senderUin
|
||||||
|
val fileMsg = record.elements.firstOrNull {
|
||||||
|
it.elementType == MsgConstant.KELEMTYPEFILE
|
||||||
|
}?.fileElement ?: kotlin.run {
|
||||||
|
LogCenter.log("消息为私聊文件消息但不包含文件消息,来自:${record.peerUin}", Level.WARN)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val fileName = fileMsg.fileName
|
||||||
|
val fileSize = fileMsg.fileSize
|
||||||
|
val expireTime = fileMsg.expireTime ?: 0
|
||||||
|
val fileId = fileMsg.fileUuid
|
||||||
|
val fileSubId = fileMsg.fileSubId ?: ""
|
||||||
|
val url = RichProtoSvc.getC2CFileDownUrl(fileId, fileSubId)
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.FileNoticeTransmitter
|
||||||
|
.transPrivateFileEvent(record.msgTime, userId, fileId, fileSubId, fileName, fileSize, expireTime, url)
|
||||||
|
) {
|
||||||
|
LogCenter.log("私聊文件消息推送失败 -> FileNoticeTransmitter", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onGroupFileMsg(record: MsgRecord) {
|
||||||
|
val groupId = record.peerUin
|
||||||
|
val userId = record.senderUin
|
||||||
|
val fileMsg = record.elements.firstOrNull {
|
||||||
|
it.elementType == MsgConstant.KELEMTYPEFILE
|
||||||
|
}?.fileElement ?: kotlin.run {
|
||||||
|
LogCenter.log("消息为群聊文件消息但不包含文件消息,来自:${record.peerUin}", Level.WARN)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//val fileMd5 = fileMsg.fileMd5
|
||||||
|
val fileName = fileMsg.fileName
|
||||||
|
val fileSize = fileMsg.fileSize
|
||||||
|
val uuid = fileMsg.fileUuid
|
||||||
|
val bizId = fileMsg.fileBizId
|
||||||
|
|
||||||
|
val url = RichProtoSvc.getGroupFileDownUrl(record.peerUin, uuid, bizId)
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.FileNoticeTransmitter
|
||||||
|
.transGroupFileEvent(record.msgTime, userId, groupId, uuid, fileName, fileSize, bizId, url)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群聊文件消息推送失败 -> FileNoticeTransmitter", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -52,8 +52,12 @@ internal object MSFHandler {
|
|||||||
|
|
||||||
fun onPush(fromServiceMsg: FromServiceMsg) {
|
fun onPush(fromServiceMsg: FromServiceMsg) {
|
||||||
val cmd = fromServiceMsg.serviceCmd
|
val cmd = fromServiceMsg.serviceCmd
|
||||||
val push = mPushHandlers[cmd]
|
if (cmd == "trpc.msg.olpush.OlPushService.MsgPush") {
|
||||||
push?.invoke(fromServiceMsg)
|
PrimitiveListener.onPush(fromServiceMsg)
|
||||||
|
} else {
|
||||||
|
val push = mPushHandlers[cmd]
|
||||||
|
push?.invoke(fromServiceMsg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onResp(toServiceMsg: ToServiceMsg, fromServiceMsg: FromServiceMsg) {
|
fun onResp(toServiceMsg: ToServiceMsg, fromServiceMsg: FromServiceMsg) {
|
||||||
|
668
xposed/src/main/java/qq/service/internals/PrimitiveListener.kt
Normal file
668
xposed/src/main/java/qq/service/internals/PrimitiveListener.kt
Normal file
@ -0,0 +1,668 @@
|
|||||||
|
@file:OptIn(DelicateCoroutinesApi::class)
|
||||||
|
package qq.service.internals
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
|
import com.tencent.qphone.base.remote.FromServiceMsg
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
|
import io.kritor.event.GroupApplyType
|
||||||
|
import io.kritor.event.GroupMemberDecreasedType
|
||||||
|
import io.kritor.event.GroupMemberIncreasedType
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import kotlinx.io.core.ByteReadPacket
|
||||||
|
import kotlinx.io.core.discardExact
|
||||||
|
import kotlinx.io.core.readBytes
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter
|
||||||
|
import moe.fuqiuluo.shamrock.tools.asJsonObject
|
||||||
|
import moe.fuqiuluo.shamrock.tools.asString
|
||||||
|
import moe.fuqiuluo.shamrock.tools.readBuf32Long
|
||||||
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
|
import protobuf.message.ContentHead
|
||||||
|
import protobuf.message.MsgBody
|
||||||
|
import protobuf.message.ResponseHead
|
||||||
|
import protobuf.push.C2CCommonTipsEvent
|
||||||
|
import protobuf.push.C2CRecallEvent
|
||||||
|
import protobuf.push.FriendApplyEvent
|
||||||
|
import protobuf.push.GroupAdminChangeEvent
|
||||||
|
import protobuf.push.GroupApplyEvent
|
||||||
|
import protobuf.push.GroupBanEvent
|
||||||
|
import protobuf.push.GroupCommonTipsEvent
|
||||||
|
import protobuf.push.GroupInviteEvent
|
||||||
|
import protobuf.push.GroupInvitedApplyEvent
|
||||||
|
import protobuf.push.GroupListChangeEvent
|
||||||
|
import protobuf.push.MessagePush
|
||||||
|
import protobuf.push.MessagePushClientInfo
|
||||||
|
import qq.service.QQInterfaces
|
||||||
|
import qq.service.contact.ContactHelper
|
||||||
|
import qq.service.friend.FriendHelper.requestFriendSystemMsgNew
|
||||||
|
import qq.service.group.GroupHelper
|
||||||
|
import qq.service.group.GroupHelper.requestGroupSystemMsgNew
|
||||||
|
import qq.service.msg.MessageHelper
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
|
internal object PrimitiveListener {
|
||||||
|
|
||||||
|
fun onPush(fromServiceMsg: FromServiceMsg) {
|
||||||
|
if (fromServiceMsg.wupBuffer == null) return
|
||||||
|
try {
|
||||||
|
val push = fromServiceMsg.wupBuffer.slice(4)
|
||||||
|
.decodeProtobuf<MessagePush>()
|
||||||
|
GlobalScope.launch {
|
||||||
|
onMsgPush(push)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LogCenter.log(e.stackTraceToString(), Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onMsgPush(push: MessagePush) {
|
||||||
|
if (
|
||||||
|
push.msgBody == null ||
|
||||||
|
push.msgBody!!.contentHead == null ||
|
||||||
|
push.msgBody!!.body == null ||
|
||||||
|
push.msgBody!!.contentHead!!.msgTime == null
|
||||||
|
) return
|
||||||
|
val msgBody = push.msgBody!!
|
||||||
|
val contentHead = msgBody.contentHead!!
|
||||||
|
val msgType = contentHead.msgType
|
||||||
|
val subType = contentHead.msgSubType
|
||||||
|
val msgTime = contentHead.msgTime!!
|
||||||
|
val body = msgBody.body!!
|
||||||
|
try {
|
||||||
|
when (msgType) {
|
||||||
|
33 -> onGroupMemIncreased(msgTime, body)
|
||||||
|
34 -> onGroupMemberDecreased(msgTime, body)
|
||||||
|
44 -> onGroupAdminChange(msgTime, body)
|
||||||
|
82 -> onGroupMessage(msgTime, body)
|
||||||
|
84 -> onGroupApply(msgTime, contentHead, body)
|
||||||
|
87 -> onInviteGroup(msgTime, msgBody.msgHead!!, body)
|
||||||
|
528 -> when (subType) {
|
||||||
|
35 -> onFriendApply(msgTime, push.clientInfo!!, body)
|
||||||
|
39 -> onCardChange(msgTime, body)
|
||||||
|
68 -> onGroupApply(msgTime, contentHead, body)
|
||||||
|
138 -> onC2CRecall(msgTime, body)
|
||||||
|
290 -> onC2CPoke(msgTime, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
732 -> when (subType) {
|
||||||
|
12 -> onGroupBan(msgTime, body)
|
||||||
|
16 -> onGroupUniqueTitleChange(msgTime, body)
|
||||||
|
17 -> onGroupRecall(msgTime, body)
|
||||||
|
20 -> onGroupCommonTips(msgTime, body)
|
||||||
|
21 -> onEssenceMessage(msgTime, push.clientInfo, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LogCenter.log("onMsgPush(msgType: $msgType, subType: $subType): " + e.stackTraceToString(), Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onGroupMessage(msgTime: Long, body: MsgBody) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onC2CPoke(msgTime: Long, body: MsgBody) {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<C2CCommonTipsEvent>()
|
||||||
|
if (event.params == null) return
|
||||||
|
|
||||||
|
val params = event.params!!.associate {
|
||||||
|
it.key to it.value
|
||||||
|
}
|
||||||
|
|
||||||
|
val target = params["uin_str2"] ?: return
|
||||||
|
val operation = params["uin_str1"] ?: return
|
||||||
|
val suffix = params["suffix_str"] ?: ""
|
||||||
|
val actionImg = params["action_img_url"] ?: ""
|
||||||
|
val action = params["alt_str1"] ?: ""
|
||||||
|
|
||||||
|
LogCenter.log("私聊戳一戳: $operation $action $target $suffix")
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.PrivateNoticeTransmitter
|
||||||
|
.transPrivatePoke(msgTime, operation.toLong(), target.toLong(), action, suffix, actionImg)
|
||||||
|
) {
|
||||||
|
LogCenter.log("私聊戳一戳推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onFriendApply(
|
||||||
|
msgTime: Long,
|
||||||
|
clientInfo: MessagePushClientInfo,
|
||||||
|
body: MsgBody
|
||||||
|
) {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<FriendApplyEvent>()
|
||||||
|
if (event.head == null) return
|
||||||
|
val head = event.head!!
|
||||||
|
val applierUid = head.applierUid
|
||||||
|
val msg = head.applyMsg ?: ""
|
||||||
|
val source = head.source ?: ""
|
||||||
|
var applier = ContactHelper.getUinByUidAsync(applierUid).toLong()
|
||||||
|
if (applier == 0L) {
|
||||||
|
applier = clientInfo.liteHead?.sender?.toLong() ?: 0
|
||||||
|
}
|
||||||
|
val src = head.srcId
|
||||||
|
val subSrc = head.subSrc
|
||||||
|
val flag: String = try {
|
||||||
|
val reqs = requestFriendSystemMsgNew(20, 0, 0)
|
||||||
|
val req = reqs?.first {
|
||||||
|
it.msg_time.get() == msgTime
|
||||||
|
}
|
||||||
|
val seq = req?.msg_seq?.get()
|
||||||
|
"$seq;$src;$subSrc;$applier"
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
"$msgTime;$src;$subSrc;$applier"
|
||||||
|
}
|
||||||
|
LogCenter.log("来自$applier 的好友申请:$msg ($source)")
|
||||||
|
if (!GlobalEventTransmitter.RequestTransmitter
|
||||||
|
.transFriendApp(msgTime, applier, msg, flag)
|
||||||
|
) {
|
||||||
|
LogCenter.log("好友申请推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private suspend fun onCardChange(msgTime: Long, body: MsgBody) {
|
||||||
|
// val event = runCatching {
|
||||||
|
// body.msgContent!!.decodeProtobuf<GroupCardChangeEvent>()
|
||||||
|
// }.getOrElse {
|
||||||
|
// val readPacket = ByteReadPacket(body.msgContent!!)
|
||||||
|
// readPacket.readBuf32Long()
|
||||||
|
// readPacket.discardExact(1)
|
||||||
|
//
|
||||||
|
// readPacket.readBytes(readPacket.readShort().toInt()).also {
|
||||||
|
// readPacket.release()
|
||||||
|
// }.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val targetId = detail[1, 13, 2].asUtf8String
|
||||||
|
// val newCardList = detail[1, 13, 3].asList
|
||||||
|
// var newCard = ""
|
||||||
|
// newCardList
|
||||||
|
// .value
|
||||||
|
// .forEach {
|
||||||
|
// if (it[1].asInt == 1) {
|
||||||
|
// newCard = it[2].asUtf8String
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// val groupId = detail[1, 13, 4].asLong
|
||||||
|
// var oldCard = ""
|
||||||
|
// val targetQQ = ContactHelper.getUinByUidAsync(targetId).toLong()
|
||||||
|
// LogCenter.log("群组[$groupId]成员$targetQQ 群名片变动 -> $newCard")
|
||||||
|
// // oldCard暂时获取不到
|
||||||
|
// if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
// .transCardChange(msgTime, targetQQ, oldCard, newCard, groupId)
|
||||||
|
// ) {
|
||||||
|
// LogCenter.log("群名片变动推送失败!", Level.WARN)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onGroupUniqueTitleChange(msgTime: Long, body: MsgBody) {
|
||||||
|
val event = runCatching {
|
||||||
|
body.msgContent!!.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
}.getOrElse {
|
||||||
|
val readPacket = ByteReadPacket(body.msgContent!!)
|
||||||
|
readPacket.readBuf32Long()
|
||||||
|
readPacket.discardExact(1)
|
||||||
|
|
||||||
|
readPacket.readBytes(readPacket.readShort().toInt()).also {
|
||||||
|
readPacket.release()
|
||||||
|
}.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
}
|
||||||
|
val groupId = event.groupCode.toLong()
|
||||||
|
val detail = event.uniqueTitleChangeDetail!!.first()
|
||||||
|
|
||||||
|
//detail = if (detail[5] is ProtoList) {
|
||||||
|
// (detail[5] as ProtoList).value[0]
|
||||||
|
//} else {
|
||||||
|
// detail[5]
|
||||||
|
// }
|
||||||
|
|
||||||
|
val targetUin = detail.targetUin.toLong()
|
||||||
|
|
||||||
|
// 恭喜<{\"cmd\":5,\"data\":\"qq\",\"text}\":\"nickname\"}>获得群主授予的<{\"cmd\":1,\"data\":\"https://qun.qq.com/qqweb/m/qun/medal/detail.html?_wv=16777223&bid=2504&gc=gid&isnew=1&medal=302&uin=uin\",\"text\":\"title\",\"url\":\"https://qun.qq.com/qqweb/m/qun/medal/detail.html?_wv=16777223&bid=2504&gc=gid&isnew=1&medal=302&uin=uin\"}>头衔
|
||||||
|
val titleChangeInfo = detail.wording
|
||||||
|
if (titleChangeInfo.indexOf("群主授予") == -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val titleJson = titleChangeInfo.split("获得群主授予的<")[1].replace(">头衔", "")
|
||||||
|
val titleJsonObj = Json.decodeFromString<JsonElement>(titleJson).asJsonObject
|
||||||
|
val title = titleJsonObj["text"].asString
|
||||||
|
|
||||||
|
LogCenter.log("群组[$groupId]成员$targetUin 获得群头衔 -> $title")
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transTitleChange(msgTime, targetUin, title, groupId)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群头衔变动推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onEssenceMessage(
|
||||||
|
msgTime: Long,
|
||||||
|
clientInfo: MessagePushClientInfo?,
|
||||||
|
body: MsgBody
|
||||||
|
) {
|
||||||
|
if (clientInfo == null) return
|
||||||
|
val event = runCatching {
|
||||||
|
body.msgContent!!.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
}.getOrElse {
|
||||||
|
val readPacket = ByteReadPacket(body.msgContent!!)
|
||||||
|
readPacket.readBuf32Long()
|
||||||
|
readPacket.discardExact(1)
|
||||||
|
|
||||||
|
readPacket.readBytes(readPacket.readShort().toInt()).also {
|
||||||
|
readPacket.release()
|
||||||
|
}.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
}
|
||||||
|
val groupId = event.groupCode.toLong()
|
||||||
|
val detail = event.essenceMsgInfo!!.first()
|
||||||
|
|
||||||
|
val msgSeq = event.msgSeq.toLong()
|
||||||
|
val senderUin = detail.sender.toLong()
|
||||||
|
val operatorUin = detail.operator.toLong()
|
||||||
|
|
||||||
|
when (val type = detail.type) {
|
||||||
|
1u -> {
|
||||||
|
LogCenter.log("群设精消息(groupId=$groupId, sender=$senderUin, msgSeq=$msgSeq, operator=$operatorUin)")
|
||||||
|
}
|
||||||
|
2u -> {
|
||||||
|
LogCenter.log("群撤精消息(groupId=$groupId, sender=$senderUin, msgId=$msgSeq, operator=$operatorUin)")
|
||||||
|
}
|
||||||
|
else -> error("onEssenceMessage unknown type: $type")
|
||||||
|
}
|
||||||
|
|
||||||
|
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupId.toString())
|
||||||
|
val sourceRecord = withTimeoutOrNull(3000) {
|
||||||
|
suspendCancellableCoroutine {
|
||||||
|
QRoute.api(IMsgService::class.java).getMsgsBySeqAndCount(contact, msgSeq, 1, true) { _, _, records ->
|
||||||
|
it.resume(records)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}?.firstOrNull()
|
||||||
|
|
||||||
|
if (sourceRecord == null) {
|
||||||
|
LogCenter.log("无法获取源消息记录,无法推送精华消息变动!", Level.WARN)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val msgId = sourceRecord.msgId
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transEssenceChange(msgTime, senderUin, operatorUin, msgId, groupId, detail.type)
|
||||||
|
) {
|
||||||
|
LogCenter.log("精华消息变动推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private suspend fun onGroupCommonTips(time: Long, body: MsgBody) {
|
||||||
|
val event = runCatching {
|
||||||
|
body.msgContent!!.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
}.getOrElse {
|
||||||
|
val readPacket = ByteReadPacket(body.msgContent!!)
|
||||||
|
readPacket.discardExact(4)
|
||||||
|
readPacket.discardExact(1)
|
||||||
|
|
||||||
|
readPacket.readBytes(readPacket.readShort().toInt()).also {
|
||||||
|
readPacket.release()
|
||||||
|
}.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
}
|
||||||
|
val groupId = event.groupCode.toLong()
|
||||||
|
val detail = event.baseTips!!.first()
|
||||||
|
|
||||||
|
val params = detail.params!!.associate {
|
||||||
|
it.key to it.value
|
||||||
|
}
|
||||||
|
|
||||||
|
val target = params["uin_str2"] ?: params["mqq_uin"] ?: return
|
||||||
|
val operation = params["uin_str1"] ?: return
|
||||||
|
val suffix = params["suffix_str"] ?: ""
|
||||||
|
val actionImg = params["action_img_url"] ?: ""
|
||||||
|
val action = params["alt_str1"]
|
||||||
|
?: params["action_str"]
|
||||||
|
?: params["user_sign"]
|
||||||
|
?: ""
|
||||||
|
val rankImg = params["rank_img"] ?: ""
|
||||||
|
|
||||||
|
when (detail.type) {
|
||||||
|
1061u -> {
|
||||||
|
LogCenter.log("群戳一戳($groupId): $operation $action $target $suffix")
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transGroupPoke(time, operation.toLong(), target.toLong(), action, suffix, actionImg, groupId)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群戳一戳推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
1068u -> {
|
||||||
|
LogCenter.log("群打卡($groupId): $action $target")
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transGroupSign(time, target.toLong(), action, rankImg, groupId)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群打卡推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
LogCenter.log("onGroupPokeAndGroupSign unknown type ${detail.type}", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onC2CRecall(time: Long, body: MsgBody) {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<C2CRecallEvent>()
|
||||||
|
val head = event.head!!
|
||||||
|
|
||||||
|
val operationUid = head.operator!!
|
||||||
|
val operator = ContactHelper.getUinByUidAsync(operationUid).toLong()
|
||||||
|
|
||||||
|
val msgSeq = head.msgSeq
|
||||||
|
val tipText = head.wording?.wording ?: ""
|
||||||
|
|
||||||
|
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, operationUid)
|
||||||
|
val sourceRecord = withTimeoutOrNull(3000) {
|
||||||
|
suspendCancellableCoroutine {
|
||||||
|
QRoute.api(IMsgService::class.java).getMsgsBySeqAndCount(contact, msgSeq, 1, true) { _, _, records ->
|
||||||
|
it.resume(records)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}?.firstOrNull()
|
||||||
|
|
||||||
|
if (sourceRecord == null) {
|
||||||
|
LogCenter.log("无法获取源消息记录,无法推送撤回消息!", Level.WARN)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val msgId = sourceRecord.msgId
|
||||||
|
|
||||||
|
LogCenter.log("私聊消息撤回: $operator, seq = $msgSeq, msgId = ${msgId}, tip = $tipText")
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.PrivateNoticeTransmitter
|
||||||
|
.transPrivateRecall(time, operator, msgId, tipText)
|
||||||
|
) {
|
||||||
|
LogCenter.log("私聊消息撤回推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onGroupMemIncreased(time: Long, body: MsgBody) {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<GroupListChangeEvent>()
|
||||||
|
val groupCode = event.groupCode
|
||||||
|
val targetUid = event.memberUid
|
||||||
|
val type = event.type
|
||||||
|
|
||||||
|
GroupHelper.getGroupMemberList(groupCode.toString(), true).onFailure {
|
||||||
|
LogCenter.log("新成员加入刷新群成员列表失败: $groupCode", Level.WARN)
|
||||||
|
}.onSuccess {
|
||||||
|
LogCenter.log("新成员加入刷新群成员列表成功,群成员数量: ${it.size}", Level.INFO)
|
||||||
|
}
|
||||||
|
|
||||||
|
val operatorUid = event.operatorUid
|
||||||
|
val operator = ContactHelper.getUinByUidAsync(operatorUid).toLong()
|
||||||
|
val target = ContactHelper.getUinByUidAsync(targetUid).toLong()
|
||||||
|
LogCenter.log("群成员增加($groupCode): $target, type = $type")
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transGroupMemberNumIncreased(
|
||||||
|
time,
|
||||||
|
target,
|
||||||
|
targetUid,
|
||||||
|
groupCode,
|
||||||
|
operator,
|
||||||
|
operatorUid,
|
||||||
|
when (type) {
|
||||||
|
130 -> GroupMemberIncreasedType.APPROVE
|
||||||
|
131 -> GroupMemberIncreasedType.INVITE
|
||||||
|
else -> GroupMemberIncreasedType.APPROVE
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群成员增加推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onGroupMemberDecreased(time: Long, body: MsgBody) {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<GroupListChangeEvent>()
|
||||||
|
val groupCode = event.groupCode
|
||||||
|
val targetUid = event.memberUid
|
||||||
|
val type = event.type
|
||||||
|
val operatorUid = event.operatorUid
|
||||||
|
|
||||||
|
GroupHelper.getGroupMemberList(groupCode.toString(), true).onFailure {
|
||||||
|
LogCenter.log("新成员加入刷新群成员列表失败: $groupCode", Level.WARN)
|
||||||
|
}.onSuccess {
|
||||||
|
LogCenter.log("新成员加入刷新群成员列表成功,群成员数量: ${it.size}", Level.INFO)
|
||||||
|
}
|
||||||
|
|
||||||
|
val operator = ContactHelper.getUinByUidAsync(operatorUid).toLong()
|
||||||
|
val target = ContactHelper.getUinByUidAsync(targetUid).toLong()
|
||||||
|
val subtype = when (type) {
|
||||||
|
130 -> GroupMemberDecreasedType.LEAVE
|
||||||
|
131 -> GroupMemberDecreasedType.KICK
|
||||||
|
3 -> GroupMemberDecreasedType.KICK_ME
|
||||||
|
else -> GroupMemberDecreasedType.KICK
|
||||||
|
}
|
||||||
|
|
||||||
|
LogCenter.log("群成员减少($groupCode): $target, type = $subtype ($type)")
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transGroupMemberNumDecreased(
|
||||||
|
time,
|
||||||
|
target,
|
||||||
|
targetUid,
|
||||||
|
groupCode,
|
||||||
|
operator,
|
||||||
|
operatorUid,
|
||||||
|
subtype
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群成员减少推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onGroupAdminChange(msgTime: Long, body: MsgBody) {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<GroupAdminChangeEvent>()
|
||||||
|
val groupCode = event.groupCode
|
||||||
|
if (event.operation == null) return
|
||||||
|
val operation = event.operation!!
|
||||||
|
if (operation.setInfo == null && operation.unsetInfo == null) return
|
||||||
|
|
||||||
|
val isSetAdmin: Boolean
|
||||||
|
val targetUid: String
|
||||||
|
if (operation.setInfo == null) {
|
||||||
|
isSetAdmin = false
|
||||||
|
targetUid = operation.unsetInfo!!.targetUid!!
|
||||||
|
} else {
|
||||||
|
isSetAdmin = true
|
||||||
|
targetUid = operation.setInfo!!.targetUid!!
|
||||||
|
}
|
||||||
|
|
||||||
|
val target = ContactHelper.getUinByUidAsync(targetUid).toLong()
|
||||||
|
LogCenter.log("群管理员变动($groupCode): $target, isSetAdmin = $isSetAdmin")
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transGroupAdminChanged(msgTime, target, targetUid, groupCode, isSetAdmin)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群管理员变动推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onGroupBan(msgTime: Long, body: MsgBody) {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<GroupBanEvent>()
|
||||||
|
val groupCode = event.groupCode.toLong()
|
||||||
|
val operatorUid = event.operatorUid
|
||||||
|
val wholeBan = event.target?.target?.targetUid == null
|
||||||
|
val targetUid = event.target?.target?.targetUid ?: ""
|
||||||
|
val rawDuration = event.target?.target?.rawDuration?.toInt() ?: 0
|
||||||
|
val operator = ContactHelper.getUinByUidAsync(operatorUid).toLong()
|
||||||
|
val duration = if (wholeBan) -1 else rawDuration
|
||||||
|
val target = if (wholeBan) 0 else ContactHelper.getUinByUidAsync(targetUid).toLong()
|
||||||
|
|
||||||
|
if (wholeBan) {
|
||||||
|
LogCenter.log("群全员禁言($groupCode): $operator -> ${if (rawDuration != 0) "开启" else "关闭"}")
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transGroupWholeBan(msgTime, groupCode, operator, rawDuration != 0)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群禁言推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LogCenter.log("群禁言($groupCode): $operator -> $target, 时长 = ${duration}s")
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transGroupBan(msgTime, operator, operatorUid, target, targetUid, groupCode, duration)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群禁言推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onGroupRecall(time: Long, body: MsgBody) {
|
||||||
|
val event = runCatching {
|
||||||
|
body.msgContent!!.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
}.getOrElse {
|
||||||
|
val readPacket = ByteReadPacket(body.msgContent!!)
|
||||||
|
readPacket.discardExact(4)
|
||||||
|
readPacket.discardExact(1)
|
||||||
|
readPacket.readBytes(readPacket.readShort().toInt()).also {
|
||||||
|
readPacket.release()
|
||||||
|
}.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
|
}
|
||||||
|
val groupCode = event.groupCode.toLong()
|
||||||
|
val detail = event.recallDetails!!
|
||||||
|
val operatorUid = detail.operatorUid
|
||||||
|
val targetUid = detail.msgInfo!!.senderUid
|
||||||
|
val msgSeq = detail.msgInfo!!.msgSeq.toLong()
|
||||||
|
val tipText = detail.wording?.wording ?: ""
|
||||||
|
|
||||||
|
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupCode.toString())
|
||||||
|
val sourceRecord = withTimeoutOrNull(3000) {
|
||||||
|
suspendCancellableCoroutine {
|
||||||
|
QRoute.api(IMsgService::class.java).getMsgsBySeqAndCount(contact, msgSeq, 1, true) { _, _, records ->
|
||||||
|
it.resume(records)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}?.firstOrNull()
|
||||||
|
|
||||||
|
if (sourceRecord == null) {
|
||||||
|
LogCenter.log("无法获取源消息记录,无法推送撤回消息!", Level.WARN)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val msgId = sourceRecord.msgId
|
||||||
|
|
||||||
|
val operator = ContactHelper.getUinByUidAsync(operatorUid).toLong()
|
||||||
|
val target = ContactHelper.getUinByUidAsync(targetUid).toLong()
|
||||||
|
LogCenter.log("群消息撤回($groupCode): $operator -> $target, seq = $msgSeq, id = $msgId, tip = $tipText")
|
||||||
|
|
||||||
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
|
.transGroupMsgRecall(time, operator, operatorUid, target, targetUid, groupCode, msgId, tipText)
|
||||||
|
) {
|
||||||
|
LogCenter.log("群消息撤回推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onGroupApply(time: Long, contentHead: ContentHead, body: MsgBody) {
|
||||||
|
when (contentHead.msgType) {
|
||||||
|
84 -> {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<GroupApplyEvent>()
|
||||||
|
val groupCode = event.groupCode
|
||||||
|
val applierUid = event.applierUid
|
||||||
|
val reason = event.applyMsg ?: ""
|
||||||
|
var applier = ContactHelper.getUinByUidAsync(applierUid).toLong()
|
||||||
|
if (applier == QQInterfaces.app.longAccountUin) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val msgSeq = contentHead.msgSeq
|
||||||
|
val flag = try {
|
||||||
|
var reqs = requestGroupSystemMsgNew(10, 1)
|
||||||
|
val riskReqs = requestGroupSystemMsgNew(5, 2)
|
||||||
|
reqs = reqs + riskReqs
|
||||||
|
val req = reqs.firstOrNull {
|
||||||
|
it.msg_time.get() == time && it.msg?.group_code?.get() == groupCode
|
||||||
|
}
|
||||||
|
val seq = req?.msg_seq?.get() ?: time
|
||||||
|
if (applier == 0L) {
|
||||||
|
applier = req?.req_uin?.get() ?: 0L
|
||||||
|
}
|
||||||
|
"$seq;$groupCode;$applier"
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
"$time;$groupCode;$applier"
|
||||||
|
}
|
||||||
|
LogCenter.log("入群申请($groupCode) $applier: \"$reason\", seq: $msgSeq")
|
||||||
|
if (!GlobalEventTransmitter.RequestTransmitter
|
||||||
|
.transGroupApply(time, applier, applierUid, reason, groupCode, flag, GroupApplyType.GROUP_APPLY_ADD)
|
||||||
|
) {
|
||||||
|
LogCenter.log("入群申请推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
528 -> {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<GroupInvitedApplyEvent>()
|
||||||
|
val groupCode = event.applyInfo?.groupCode ?: return
|
||||||
|
val applierUid = event.applyInfo?.applierUid ?: return
|
||||||
|
var applier = ContactHelper.getUinByUidAsync(applierUid).toLong()
|
||||||
|
if (applier == QQInterfaces.app.longAccountUin) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ((event.applyInfo?.type ?: return) < 3) {
|
||||||
|
// todo
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val flag = try {
|
||||||
|
var reqs = requestGroupSystemMsgNew(10, 1)
|
||||||
|
val riskReqs = requestGroupSystemMsgNew(5, 2)
|
||||||
|
reqs = reqs + riskReqs
|
||||||
|
val req = reqs.firstOrNull() {
|
||||||
|
it.msg_time.get() == time
|
||||||
|
}
|
||||||
|
val seq = req?.msg_seq?.get() ?: time
|
||||||
|
if (applier == 0L) {
|
||||||
|
applier = req?.req_uin?.get() ?: 0L
|
||||||
|
}
|
||||||
|
"$seq;$groupCode;$applier"
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
"$time;$groupCode;$applier"
|
||||||
|
}
|
||||||
|
LogCenter.log("邀请入群申请($groupCode): $applier")
|
||||||
|
if (!GlobalEventTransmitter.RequestTransmitter
|
||||||
|
.transGroupApply(time, applier, applierUid, "", groupCode, flag, GroupApplyType.GROUP_APPLY_ADD)
|
||||||
|
) {
|
||||||
|
LogCenter.log("邀请入群申请推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onInviteGroup(time: Long, msgHead: ResponseHead, body: MsgBody) {
|
||||||
|
val event = body.msgContent!!.decodeProtobuf<GroupInviteEvent>()
|
||||||
|
val groupCode = event.groupCode
|
||||||
|
val invitorUid = event.inviterUid
|
||||||
|
val invitor = ContactHelper.getUinByUidAsync(invitorUid).toLong()
|
||||||
|
val uin = msgHead.receiver
|
||||||
|
LogCenter.log("邀请入群: $groupCode, 邀请者: \"$invitor\"")
|
||||||
|
val flag = try {
|
||||||
|
var reqs = requestGroupSystemMsgNew(10, 1)
|
||||||
|
val riskReqs = requestGroupSystemMsgNew(10, 2)
|
||||||
|
reqs = reqs + riskReqs
|
||||||
|
val req = reqs.firstOrNull {
|
||||||
|
it.msg_time.get() == time
|
||||||
|
}
|
||||||
|
val seq = req?.msg_seq?.get() ?: time
|
||||||
|
"$seq;$groupCode;$uin"
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
"$time;$groupCode;$uin"
|
||||||
|
}
|
||||||
|
if (!GlobalEventTransmitter.RequestTransmitter
|
||||||
|
.transGroupApply(time, invitor, invitorUid, "", groupCode, flag, GroupApplyType.GROUP_APPLY_INVITE)
|
||||||
|
) {
|
||||||
|
LogCenter.log("邀请入群推送失败!", Level.WARN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -195,7 +195,7 @@ abstract class SimpleKernelMsgListener: IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMsgRecall(i2: Int, str: String?, j2: Long) {
|
override fun onMsgRecall(chatType: Int, tips: String?, msgId: Long) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package qq.service.msg
|
|||||||
import com.tencent.qqnt.kernel.api.IKernelService
|
import com.tencent.qqnt.kernel.api.IKernelService
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.TempChatInfo
|
import com.tencent.qqnt.kernel.nativeinterface.TempChatInfo
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
@ -32,12 +33,28 @@ internal object MessageHelper: QQInterfaces() {
|
|||||||
return Result.success(info)
|
return Result.success(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun generateContact(record: MsgRecord): Contact {
|
||||||
|
val peerId = when (record.chatType) {
|
||||||
|
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> record.senderUid
|
||||||
|
MsgConstant.KCHATTYPEGUILD -> record.channelId
|
||||||
|
else -> record.peerUin.toString()
|
||||||
|
}
|
||||||
|
return Contact(record.chatType, peerId, if (record.chatType == MsgConstant.KCHATTYPEGUILD) {
|
||||||
|
record.guildId
|
||||||
|
} else if(record.chatType == MsgConstant.KCHATTYPETEMPC2CFROMGROUP) {
|
||||||
|
val tempInfo = getTempChatInfo(record.chatType, peerId).getOrThrow()
|
||||||
|
tempInfo.groupCode
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun generateContact(chatType: Int, id: String, subId: String = ""): Contact {
|
suspend fun generateContact(chatType: Int, id: String, subId: String = ""): Contact {
|
||||||
val peerId = when (chatType) {
|
val peerId = when (chatType) {
|
||||||
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
|
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
|
||||||
ContactHelper.getUidByUinAsync(id.toLong())
|
if (id.startsWith("u_")) id
|
||||||
|
else ContactHelper.getUidByUinAsync(id.toLong())
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> id
|
else -> id
|
||||||
}
|
}
|
||||||
return if (chatType == MsgConstant.KCHATTYPEGUILD) {
|
return if (chatType == MsgConstant.KCHATTYPEGUILD) {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package qq.service.msg
|
package qq.service.msg
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import io.kritor.event.AtElement
|
import io.kritor.event.AtElement
|
||||||
import io.kritor.event.Element
|
import io.kritor.event.Element
|
||||||
import io.kritor.event.ElementKt
|
import io.kritor.event.ElementKt
|
||||||
@ -21,10 +23,13 @@ import io.kritor.event.imageElement
|
|||||||
import io.kritor.event.jsonElement
|
import io.kritor.event.jsonElement
|
||||||
import io.kritor.event.locationElement
|
import io.kritor.event.locationElement
|
||||||
import io.kritor.event.pokeElement
|
import io.kritor.event.pokeElement
|
||||||
|
import io.kritor.event.replyElement
|
||||||
import io.kritor.event.rpsElement
|
import io.kritor.event.rpsElement
|
||||||
import io.kritor.event.textElement
|
import io.kritor.event.textElement
|
||||||
import io.kritor.event.videoElement
|
import io.kritor.event.videoElement
|
||||||
import io.kritor.event.voiceElement
|
import io.kritor.event.voiceElement
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
@ -40,6 +45,7 @@ import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
|||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_8_VER
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_8_VER
|
||||||
import qq.service.bdh.RichProtoSvc
|
import qq.service.bdh.RichProtoSvc
|
||||||
import qq.service.contact.ContactHelper
|
import qq.service.contact.ContactHelper
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
typealias NtMessages = ArrayList<MsgElement>
|
typealias NtMessages = ArrayList<MsgElement>
|
||||||
typealias Convertor = suspend (MsgRecord, MsgElement) -> Result<Element>
|
typealias Convertor = suspend (MsgRecord, MsgElement) -> Result<Element>
|
||||||
@ -308,8 +314,22 @@ private object MsgConvertor {
|
|||||||
suspend fun convertReply(record: MsgRecord, element: MsgElement): Result<Element> {
|
suspend fun convertReply(record: MsgRecord, element: MsgElement): Result<Element> {
|
||||||
val reply = element.replyElement
|
val reply = element.replyElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
elem.setReply(io.kritor.event.replyElement {
|
elem.setReply(replyElement {
|
||||||
this.messageId = reply.replayMsgId
|
val msgSeq = reply.replayMsgSeq
|
||||||
|
val contact = MessageHelper.generateContact(record)
|
||||||
|
val sourceRecords = withTimeoutOrNull(3000) {
|
||||||
|
suspendCancellableCoroutine {
|
||||||
|
QRoute.api(IMsgService::class.java).getMsgsBySeqAndCount(contact, msgSeq, 1, true) { _, _, records ->
|
||||||
|
it.resume(records)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceRecords.isNullOrEmpty()) {
|
||||||
|
LogCenter.log("无法查询到回复的消息ID: seq = $msgSeq", Level.WARN)
|
||||||
|
this.messageId = reply.replayMsgId
|
||||||
|
} else {
|
||||||
|
this.messageId = sourceRecords.first().msgId
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return Result.success(elem.build())
|
return Result.success(elem.build())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user