diff --git a/wechaty-puppet-hostie/src/main/scala/wechaty/hostie/support/MessageRawSupport.scala b/wechaty-puppet-hostie/src/main/scala/wechaty/hostie/support/MessageRawSupport.scala index 2e6db53d..90530c10 100644 --- a/wechaty-puppet-hostie/src/main/scala/wechaty/hostie/support/MessageRawSupport.scala +++ b/wechaty-puppet-hostie/src/main/scala/wechaty/hostie/support/MessageRawSupport.scala @@ -1,6 +1,7 @@ package wechaty.hostie.support import com.typesafe.scalalogging.LazyLogging +import io.github.wechaty.grpc.PuppetGrpc import io.github.wechaty.grpc.puppet.Base.DingRequest import io.github.wechaty.grpc.puppet.Message import io.github.wechaty.grpc.puppet.Message.MessagePayloadRequest @@ -9,10 +10,12 @@ import wechaty.puppet.schemas.Image.ImageType.Type import wechaty.puppet.schemas.Message.{MessagePayload, MessageType} import wechaty.puppet.schemas.MiniProgram.MiniProgramPayload import wechaty.puppet.schemas.Puppet -import wechaty.puppet.schemas.Puppet.objectMapper +import wechaty.puppet.schemas.Puppet._ import wechaty.puppet.schemas.UrlLink.UrlLinkPayload import wechaty.puppet.support.MessageSupport +import scala.concurrent.Future + /** * * @author Jun Tsai @@ -94,7 +97,7 @@ trait MessageRawSupport { response.getId.getValue } - override def messageSendText(conversationId: String, text: String, mentionIdList: Array[String]): String = { + override def messageSendText(conversationId: String, text: String, mentionIdList: Array[String]): Future[String] = { import scala.collection.JavaConverters._ val request = Message.MessageSendTextRequest.newBuilder() .setConversationId(conversationId) @@ -102,8 +105,8 @@ trait MessageRawSupport { .addAllMentonalIds(asJavaIterable(mentionIdList.toIterable)) .build() - val response = grpcClient.messageSendText(request) - response.getId.getValue + asyncCall(PuppetGrpc.getMessageSendTextMethod,request) + .map(response=>response.getId.getValue) } override def messageSendUrl(conversationId: String, urlLinkPayload: UrlLinkPayload): String = { diff --git a/wechaty-puppet-hostie/src/main/scala/wechaty/hostie/support/RoomMemberRawSupport.scala b/wechaty-puppet-hostie/src/main/scala/wechaty/hostie/support/RoomMemberRawSupport.scala index 0c573db3..4b799414 100644 --- a/wechaty-puppet-hostie/src/main/scala/wechaty/hostie/support/RoomMemberRawSupport.scala +++ b/wechaty-puppet-hostie/src/main/scala/wechaty/hostie/support/RoomMemberRawSupport.scala @@ -1,10 +1,13 @@ package wechaty.hostie.support import com.google.protobuf.StringValue +import io.github.wechaty.grpc.PuppetGrpc import io.github.wechaty.grpc.puppet.{Room, RoomMember} import wechaty.puppet.schemas.Room.RoomMemberPayload import wechaty.puppet.{Puppet, schemas} +import scala.concurrent.Future + /** * * @author Jun Tsai @@ -46,20 +49,21 @@ trait RoomMemberRawSupport { response.getMemberIdsList.toArray(Array[String]()) } - override protected def roomMemberRawPayload(roomId: String, contactId: String): schemas.Room.RoomMemberPayload = { + override protected def roomMemberRawPayload(roomId: String, contactId: String): Future[schemas.Room.RoomMemberPayload] = { val request = RoomMember.RoomMemberPayloadRequest.newBuilder() .setId(roomId) .setMemberId(contactId) .build() - val response = grpcClient.roomMemberPayload(request) - val payload = new RoomMemberPayload() + asyncCallback(PuppetGrpc.getRoomMemberPayloadMethod, request) { response => - payload.avatar = response.getAvatar - payload.id = response.getId - payload.inviterId = response.getInviterId - payload.name = response.getName - payload.roomAlias = response.getRoomAlias - payload + val payload = new RoomMemberPayload() + payload.avatar = response.getAvatar + payload.id = response.getId + payload.inviterId = response.getInviterId + payload.name = response.getName + payload.roomAlias = response.getRoomAlias + payload + } } } diff --git a/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/PuppetPadplus.scala b/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/PuppetPadplus.scala index 614d0aa2..0ae1a7f0 100644 --- a/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/PuppetPadplus.scala +++ b/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/PuppetPadplus.scala @@ -9,6 +9,8 @@ import wechaty.puppet.schemas.Puppet.{PuppetEventName, PuppetOptions} import wechaty.puppet.schemas._ import wechaty.puppet.support.ContactSupport +import scala.concurrent.Future + /** * * @author Jun Tsai @@ -92,9 +94,8 @@ class PuppetPadplus(val option:PuppetOptions,val storePath:String="/tmp/padplus" override def roomMemberList(roomId: String): Array[String] = ??? - override protected def roomMemberRawPayload(roomId: String, contactId: String): Room.RoomMemberPayload = { - //TODO - null + override protected def roomMemberRawPayload(roomId: String, contactId: String): Future[Room.RoomMemberPayload] = { + ??? } diff --git a/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/GrpcSupport.scala b/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/GrpcSupport.scala index a1394522..20564ff7 100644 --- a/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/GrpcSupport.scala +++ b/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/GrpcSupport.scala @@ -118,10 +118,10 @@ trait GrpcSupport { //do nothing } - protected def syncRequest[T: TypeTag](apiType: ApiType, data: Option[Any] = None)(implicit classTag: ClassTag[T]): T = { - val future = asyncRequest[T](apiType, data) - Await.result(future, 10 seconds) - } +// protected def syncRequest[T: TypeTag](apiType: ApiType, data: Option[Any] = None)(implicit classTag: ClassTag[T]): T = { +// val future = asyncRequest[T](apiType, data) +// Await.result(future, 10 seconds) +// } protected def generateTraceId(apiType: ApiType): String = { UUID.randomUUID().toString diff --git a/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/MessageRawSupport.scala b/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/MessageRawSupport.scala index 7d9f62b8..94b47d29 100644 --- a/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/MessageRawSupport.scala +++ b/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/MessageRawSupport.scala @@ -15,6 +15,9 @@ import wechaty.puppet.schemas.Puppet.{PuppetEventName, isBlank, objectMapper} import wechaty.puppet.schemas.{Message, MiniProgram, Puppet, UrlLink} import wechaty.puppet.support.MessageSupport +import scala.concurrent.Future +import scala.language.implicitConversions + /** * * @author Jun Tsai @@ -62,14 +65,16 @@ trait MessageRawSupport { override def messageSendMiniProgram(conversationId: String, miniProgramPayload: MiniProgram.MiniProgramPayload): String = ??? - override def messageSendText(conversationId: String, text: String, mentionIdList: Array[String]): String = { + override def messageSendText(conversationId: String, text: String, mentionIdList: Array[String]): Future[String] = { val json = Puppet.objectMapper.createObjectNode() json.put("content",text) json.put("messageType",PadplusMessageType.Text.id) json.put("fromUserName",selfId.get) json.put("toUserName",conversationId) - val payload = syncRequest[GrpcMessagePayload](ApiType.SEND_MESSAGE,Some(json.toString)) - payload.MsgId + asyncRequest[GrpcMessagePayload](ApiType.SEND_MESSAGE,Some(json.toString)).map { payload => + savePadplusMessagePayload(payload) + payload.MsgId + } } override def messageSendUrl(conversationId: String, urlLinkPayload: UrlLink.UrlLinkPayload): String = ??? diff --git a/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/RoomMemberRawSupport.scala b/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/RoomMemberRawSupport.scala index 4f609b0d..08634e12 100644 --- a/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/RoomMemberRawSupport.scala +++ b/wechaty-puppet-padplus/src/main/scala/wechaty/padplus/support/RoomMemberRawSupport.scala @@ -8,6 +8,7 @@ import wechaty.puppet.schemas.Room import wechaty.puppet.schemas.Room.RoomMemberPayload import wechaty.puppet.support.RoomMemberSupport +import scala.concurrent.{Future, Promise} import scala.util.Try /** @@ -29,18 +30,20 @@ trait RoomMemberRawSupport { override def roomMemberList(roomId: String): Array[String] = ??? - override protected def roomMemberRawPayload(roomId: String, contactId: String): Room.RoomMemberPayload = { + override protected def roomMemberRawPayload(roomId: String, contactId: String): Future[Room.RoomMemberPayload] = { getPadplusRoomMembers(roomId) match{ case Some(padplusRoomMembers) => - padplusRoomMembers.members.get(contactId).map(convertToPuppetRoomMember).orNull + val value = padplusRoomMembers.members.get(contactId).map(convertToPuppetRoomMember).orNull + Promise[Room.RoomMemberPayload].success(value).future case _ => val json = objectMapper.createObjectNode() json.put("OpType", "UPDATE") json.put("type", "GET_MEMBER") json.put("roomId", roomId) - val map = syncRequest[PadplusRoomMemberMap](ApiType.ROOM_OPERATION, Some(json.toString)) - savePadplusRoomMembers(roomId,map) - map.members.get(contactId).map(convertToPuppetRoomMember).orNull + asyncRequest[PadplusRoomMemberMap](ApiType.ROOM_OPERATION, Some(json.toString)).map{payload=> + savePadplusRoomMembers(roomId,payload) + payload.members.get(contactId).map(convertToPuppetRoomMember).orNull + } } } private def convertToPuppetRoomMember(input: PadplusRoomMemberPayload): RoomMemberPayload = { diff --git a/wechaty-puppet-padplus/src/test/scala/wechaty/padplus/PadplusTestEventBase.scala b/wechaty-puppet-padplus/src/test/scala/wechaty/padplus/PadplusTestEventBase.scala index 222bb190..23deae1d 100644 --- a/wechaty-puppet-padplus/src/test/scala/wechaty/padplus/PadplusTestEventBase.scala +++ b/wechaty-puppet-padplus/src/test/scala/wechaty/padplus/PadplusTestEventBase.scala @@ -44,6 +44,7 @@ class PadplusTestEventBase extends LazyLogging{ options.token=Some("token") instance = new PuppetPadplus(options,storePath){ + this.selfId = Some(uin) override protected def generateTraceId(apiType: ApiType): String = { NEED_CALLBACK_API_LIST.values.find( _ == apiType) match{ case Some(v) => @@ -122,7 +123,7 @@ val requestBuilder2 = RequestObject.newBuilder() } private val NEED_CALLBACK_API_LIST=Map( // ApiType.INIT, -// ApiType.SEND_MESSAGE, + ResponseType.REQUEST_RESPONSE->ApiType.SEND_MESSAGE, // ApiType.SEND_FILE, // ApiType.GET_MESSAGE_MEDIA, // ApiType.SEARCH_CONTACT, diff --git a/wechaty-puppet-padplus/src/test/scala/wechaty/padplus/support/MessageRawSupportTest.scala b/wechaty-puppet-padplus/src/test/scala/wechaty/padplus/support/MessageRawSupportTest.scala new file mode 100644 index 00000000..d2e65ece --- /dev/null +++ b/wechaty-puppet-padplus/src/test/scala/wechaty/padplus/support/MessageRawSupportTest.scala @@ -0,0 +1,38 @@ +package wechaty.padplus.support + +import org.grpcmock.GrpcMock.{stubFor, unaryMethod} +import org.junit.jupiter.api.{Assertions, Test} +import wechaty.padplus.PadplusTestEventBase +import wechaty.padplus.grpc.PadPlusServerGrpc +import wechaty.padplus.grpc.PadPlusServerOuterClass.{ResponseObject, ResponseType} +import wechaty.padplus.schemas.GrpcSchemas.GrpcMessagePayload +import wechaty.padplus.schemas.PadplusEnums.PadplusMessageType + +import scala.concurrent.Await +import scala.concurrent.duration._ + +/** + * + * @author Jun Tsai + * @since 2020-07-02 + */ +class MessageRawSupportTest extends PadplusTestEventBase { + @Test + def test_sendMessage: Unit ={ + val responseBuilder = ResponseObject.newBuilder.setResult("success") + stubFor(unaryMethod(PadPlusServerGrpc.getRequestMethod) + .willReturn(responseBuilder.build())) + + val future = instance.messageSendText("roomId","test",Array()) + + val grpcContact = new GrpcMessagePayload + grpcContact.MsgId= "msgId" + grpcContact.MsgType = PadplusMessageType.Text.id + mockEvent(ResponseType.REQUEST_RESPONSE -> grpcContact) + + val payload = Await.result(future, 10 seconds) + Assertions.assertEquals("msgId", payload) + + + } +} diff --git a/wechaty-puppet/src/main/scala/wechaty/puppet/support/MessageSupport.scala b/wechaty-puppet/src/main/scala/wechaty/puppet/support/MessageSupport.scala index d4561b2e..7cccc703 100644 --- a/wechaty-puppet/src/main/scala/wechaty/puppet/support/MessageSupport.scala +++ b/wechaty-puppet/src/main/scala/wechaty/puppet/support/MessageSupport.scala @@ -9,6 +9,8 @@ import wechaty.puppet.schemas.Puppet import wechaty.puppet.schemas.UrlLink.UrlLinkPayload import wechaty.puppet.{Puppet, ResourceBox} +import scala.concurrent.{Future, Promise} + /** * * @author Jun Tsai @@ -35,7 +37,7 @@ trait MessageSupport { def messageSendMiniProgram(conversationId: String, miniProgramPayload: MiniProgramPayload): String - def messageSendText(conversationId: String, text: String, mentionIdList: Array[String]=Array()): String + def messageSendText(conversationId: String, text: String, mentionIdList: Array[String]=Array()): Future[String] def messageSendUrl(conversationId: String, urlLinkPayload: UrlLinkPayload): String @@ -67,14 +69,15 @@ trait MessageSupport { payload } - def messageForward (conversationId: String, messageId: String): String= { + def messageForward (conversationId: String, messageId: String): Future[String]= { val payload = this.messagePayload(messageId) payload.`type` match{ case MessageType.Attachment | MessageType.Audio | MessageType.Video => - messageSendFile(conversationId,messageFile(messageId)) + val id = messageSendFile(conversationId,messageFile(messageId)) + Promise[String].success(id).future case MessageType.Image => - messageSendFile(conversationId,messageFile(messageId)) -// messageSendFile(conversationId,messageImage(messageId,ImageType.Thumbnail)) + val id = messageSendFile(conversationId,messageFile(messageId)) + Promise[String].success(id).future case MessageType.Text => if(!Puppet.isBlank(payload.text)){ this.messageSendText( @@ -86,22 +89,24 @@ trait MessageSupport { throw new IllegalStateException("Puppet messageForward() payload.text is undefined.") } case MessageType.MiniProgram => - this.messageSendMiniProgram( + val id = this.messageSendMiniProgram( conversationId, this.messageMiniProgram(messageId) ) + Promise[String].success(id).future case MessageType.Url => - this.messageSendUrl( + val id = this.messageSendUrl( conversationId, this.messageUrl(messageId) ) + Promise[String].success(id).future case MessageType.Contact => - this.messageSendContact( + val id = this.messageSendContact( conversationId, this.messageContact(messageId) ) - + Promise[String].success(id).future case MessageType.ChatHistory | MessageType.Location | MessageType.Emoticon | MessageType.Transfer | MessageType.RedEnvelope| MessageType.Recalled => @@ -109,7 +114,6 @@ trait MessageSupport { case MessageType.Unknown => throw new Error("Unsupported forward message type:" + payload.`type`) } - } protected def messageRawPayload(messageId: String): MessagePayload diff --git a/wechaty-puppet/src/main/scala/wechaty/puppet/support/RoomMemberSupport.scala b/wechaty-puppet/src/main/scala/wechaty/puppet/support/RoomMemberSupport.scala index 5858eb34..3200e71e 100644 --- a/wechaty-puppet/src/main/scala/wechaty/puppet/support/RoomMemberSupport.scala +++ b/wechaty-puppet/src/main/scala/wechaty/puppet/support/RoomMemberSupport.scala @@ -5,6 +5,8 @@ import wechaty.puppet.Puppet import wechaty.puppet.schemas.Puppet.isBlank import wechaty.puppet.schemas.Room.RoomMemberPayload +import scala.concurrent.{Future, Promise} + /** * * @author Jun Tsai @@ -25,7 +27,7 @@ trait RoomMemberSupport { def roomMemberList(roomId: String): Array[String] - protected def roomMemberRawPayload(roomId: String, contactId: String): RoomMemberPayload + protected def roomMemberRawPayload(roomId: String, contactId: String): Future[RoomMemberPayload] /** * Concat roomId & contactId to one string @@ -42,7 +44,7 @@ trait RoomMemberSupport { }) } - def roomMemberPayload ( roomId : String, memberId : String): RoomMemberPayload = { + def roomMemberPayload ( roomId : String, memberId : String): Future[RoomMemberPayload] = { if (isBlank(roomId)|| isBlank(memberId)) { throw new Error("roomId or memberId is blank") @@ -55,17 +57,16 @@ trait RoomMemberSupport { val cachedPayload = this.cacheRoomMemberPayload.getIfPresent(CACHE_KEY) if (cachedPayload != null) { - return cachedPayload + return Promise[RoomMemberPayload].success(cachedPayload).future } /** * 2. Cache not found */ - val rawPayload = this.roomMemberRawPayload(roomId, memberId) - if (rawPayload == null) { - throw new Error("contact(" + memberId + ") is not in the Room(" + roomId + ")") + import wechaty.puppet.schemas.Puppet.executionContext + roomMemberRawPayload(roomId, memberId).map{ rawPayload=> + this.cacheRoomMemberPayload.put(CACHE_KEY, rawPayload) + rawPayload } - this.cacheRoomMemberPayload.put(CACHE_KEY, rawPayload) - rawPayload } } diff --git a/wechaty/src/main/scala/wechaty/helper/ImplicitHelper.scala b/wechaty/src/main/scala/wechaty/helper/ImplicitHelper.scala index 0b9edafc..12d8881e 100644 --- a/wechaty/src/main/scala/wechaty/helper/ImplicitHelper.scala +++ b/wechaty/src/main/scala/wechaty/helper/ImplicitHelper.scala @@ -5,7 +5,9 @@ import java.util.function.Consumer import wechaty.Wechaty.PuppetResolver import wechaty.puppet.schemas.Event.{EventFriendshipPayload, EventLoginPayload, EventLogoutPayload, EventMessagePayload, EventRoomInvitePayload, EventRoomJoinPayload, EventScanPayload} import wechaty.user.{Contact, ContactSelf, Friendship, Message, Room, RoomInvitation} +import wechaty.puppet.schemas.Puppet._ +import scala.concurrent.Future import scala.language.implicitConversions /** @@ -26,6 +28,7 @@ object ImplicitHelper { } private [wechaty] implicit def toMessage(messageId: String)(implicit puppetResolver: PuppetResolver) = new Message(messageId) + private [wechaty] implicit def toMessage(messageId: Future[String])(implicit puppetResolver: PuppetResolver):Future[Message] = messageId.map(toMessage) private[wechaty] implicit def toContactSelf(contactListener: Consumer[ContactSelf])(implicit puppet: PuppetResolver): EventLoginPayload => Unit = { payload: EventLoginPayload => { contactListener.accept(new ContactSelf(payload.contactId)) } diff --git a/wechaty/src/main/scala/wechaty/user/Conversation.scala b/wechaty/src/main/scala/wechaty/user/Conversation.scala index 5e9eb8e7..634da3be 100644 --- a/wechaty/src/main/scala/wechaty/user/Conversation.scala +++ b/wechaty/src/main/scala/wechaty/user/Conversation.scala @@ -3,6 +3,9 @@ package wechaty.user import wechaty.helper.ImplicitHelper._ import wechaty.Wechaty.PuppetResolver import wechaty.puppet.ResourceBox +import wechaty.puppet.schemas.Puppet.executionContext + +import scala.concurrent.Future /** @@ -11,7 +14,7 @@ import wechaty.puppet.ResourceBox * @since 2020-06-08 */ class Conversation(val id:String)(implicit resolver:PuppetResolver) { - def say(something: String): Message = { + def say(something: String): Future[Message] = { resolver.puppet.messageSendText(this.id, something) } diff --git a/wechaty/src/main/scala/wechaty/user/Message.scala b/wechaty/src/main/scala/wechaty/user/Message.scala index bce5316a..4c316533 100644 --- a/wechaty/src/main/scala/wechaty/user/Message.scala +++ b/wechaty/src/main/scala/wechaty/user/Message.scala @@ -10,6 +10,8 @@ import wechaty.puppet.schemas.Puppet._ import wechaty.puppet.schemas.Puppet import wechaty.puppet.{ResourceBox, schemas} +import scala.concurrent.Future + /** * wrap MessagePayload @@ -88,7 +90,7 @@ class Message(messageId:String)(implicit resolver: PuppetResolver) extends LazyL new Message(originalMessageId) } - def say(text:String): Message = { + def say(text:String): Future[Message] = { resolver.puppet.messageSendText(sayId,text) } def say(contact: Contact): Message = { diff --git a/wechaty/src/main/scala/wechaty/user/Room.scala b/wechaty/src/main/scala/wechaty/user/Room.scala index e12889e9..8e0efb6a 100644 --- a/wechaty/src/main/scala/wechaty/user/Room.scala +++ b/wechaty/src/main/scala/wechaty/user/Room.scala @@ -11,6 +11,9 @@ import wechaty.puppet.schemas.Puppet._ import wechaty.puppet.schemas.Room.{RoomPayload, RoomQueryFilter} import wechaty.user.Room.{RoomJoinEvent, RoomLeaveEvent, RoomTopicEvent} +import scala.concurrent.{Await, Future} +import scala.concurrent.duration._ + /** * * @author Jun Tsai @@ -100,11 +103,13 @@ class Room private(roomId: String)(implicit resolver: PuppetResolver) extends Co } def alias(contact: Contact): Option[String] = { - val memberPayload = resolver.puppet.roomMemberPayload(this.id, contact.id) - - if (memberPayload != null && !isBlank(memberPayload.roomAlias)) { - Some(memberPayload.roomAlias) - } else None +// val memberPayload = + val future = resolver.puppet.roomMemberPayload(this.id, contact.id).map{memberPayload=> + if (memberPayload != null && !isBlank(memberPayload.roomAlias)) { + Some(memberPayload.roomAlias) + } else None + } + Await.result(future,10 seconds) } def memberList(): Array[Contact] = { @@ -116,7 +121,7 @@ class Room private(roomId: String)(implicit resolver: PuppetResolver) extends Co resolver.puppet.roomPayloadDirty(this.roomId) } - def say(something: String, mentionList: Array[Contact]): Message = { + def say(something: String, mentionList: Array[Contact]): Future[Message] = { val mentionText = mentionList.map(x => { val aliasOpt = this.alias(x) aliasOpt match {