Room.scala
package wechaty.user
import java.util.Date
import com.typesafe.scalalogging.LazyLogging
import wechaty.Wechaty.PuppetResolver
import wechaty.puppet.ResourceBox
import wechaty.puppet.events.EventEmitter
import wechaty.puppet.schemas.Event.{EventMessagePayload, EventRoomJoinPayload, EventRoomLeavePayload, EventRoomTopicPayload}
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 <a href="mailto:jcai@ganshane.com">Jun Tsai</a>
* @since 2020-06-08
*/
object Room {
type RoomJoinEvent = (Array[Contact],Contact,Date)
type RoomLeaveEvent=(Array[Contact],Contact,Date)
type RoomTopicEvent=(Contact,Date)
private var pool = Map[String,Room]()
def create(contactList: Array[Contact], topic: String)(implicit puppetResolver: PuppetResolver): Room = {
if (contactList.length < 2) {
throw new Error("contactList need at least 2 contact to create a new room")
}
val contactIdList = contactList.map(contact => contact.id)
val roomId = puppetResolver.puppet.roomCreate(contactIdList, topic)
new Room(roomId)
}
def load(roomId:String)(implicit puppetResolver: PuppetResolver): Option[Room]={
pool.get(roomId) match{
case Some(room) => Some(room)
case _ =>
// val payload = puppetResolver.puppet.roomPayload(roomId)
// val newRoom = new Room(payload.id)
val newRoom = new Room(roomId)
pool += (roomId-> newRoom)
Some(newRoom)
}
}
def clear(): Unit ={
pool=Map[String,Room]()
}
def messageEvent(messagePayload: EventMessagePayload)(implicit resolver: PuppetResolver):Unit = {
val message = new Message(messagePayload.messageId)
val roomOpt = message.room
roomOpt.foreach(_.emit(PuppetEventName.MESSAGE,message))
}
def roomJoinEvent(payload:EventRoomJoinPayload)(implicit resolver: PuppetResolver): Unit ={
val room = load(payload.roomId).get
val inviteeList = payload.inviteeIdList.map(id => new Contact(id))
val inviter = new Contact(payload.inviterId)
val date = timestampToDate(payload.timestamp)
room.emit(PuppetEventName.ROOM_JOIN,(inviteeList,inviter,date))
}
def roomLeaveEvent(payload:EventRoomLeavePayload)(implicit resolver: PuppetResolver): Unit ={
val room = load(payload.roomId).get
val leaverList = payload.removeeIdList.map(id => new Contact(id))
val remover = new Contact(payload.removerId)
val date = timestampToDate(payload.timestamp)
room.emit(PuppetEventName.ROOM_LEAVE,(leaverList,remover,date))
//invalid cache
val userIdOpt = resolver.puppet.selfIdOpt()
userIdOpt match{
case Some(userId) =>
if(leaverList.exists(_.id == userId)){
resolver.puppet.roomPayloadDirty(payload.roomId)
resolver.puppet.roomMemberPayloadDirty(payload.roomId)
}
case _ =>
}
}
def roomTopicEvent(payload:EventRoomTopicPayload)(implicit resolver: PuppetResolver): Unit ={
val room = load(payload.roomId).get
val changer = new Contact(payload.changerId)
val date = timestampToDate(payload.timestamp)
room.emit(PuppetEventName.ROOM_TOPIC,(changer,date))
}
def findAll(query : Option[RoomQueryFilter] = None)(implicit resolver: PuppetResolver): Array[Room]= {
val roomIdList = resolver.puppet.roomSearch(query)
roomIdList.flatMap(id => load(id))
}
def find(query : Option[RoomQueryFilter] = None)(implicit resolver: PuppetResolver): Option[Room] = {
findAll(query).headOption
}
def find(query : RoomQueryFilter)(implicit resolver: PuppetResolver): Option[Room] = {
find(Some(query))
}
}
class Room private(roomId: String)(implicit resolver: PuppetResolver) extends Conversation(roomId) with EventEmitter with LazyLogging {
def payload: RoomPayload = {
resolver.puppet.roomPayload(roomId)
}
def alias(contact: Contact): Option[String] = {
// 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] = {
val memberIdList = resolver.puppet.roomMemberList(this.roomId)
memberIdList.map(new Contact(_))
}
def sync(): Unit = {
resolver.puppet.roomPayloadDirty(this.roomId)
}
def say(something: String, mentionList: Array[Contact]): Future[Message] = {
val mentionText = mentionList.map(x => {
val aliasOpt = this.alias(x)
aliasOpt match {
case Some(alias) => '@' + alias
case _ => '@' + x.name
}
}).mkString("\u2005")
this.say( mentionText+"\u2005 "+something )
}
def add(contact: Contact): Unit = {
resolver.puppet.roomAdd(this.id, contact.id)
}
def del(contact: Contact): Unit = {
resolver.puppet.roomDel(this.id, contact.id)
}
def quit(): Unit = {
resolver.puppet.roomQuit(this.id)
}
def topic(newTopicOpt: Option[String] = None): String = {
newTopicOpt match {
case Some(newTopic) =>
resolver.puppet.roomTopic(this.id, newTopic)
newTopic
case _ =>
if (this.payload != null && !isBlank(this.payload.topic)) {
this.payload.topic
} else {
val memberIdList = resolver.puppet.roomMemberList(this.id)
val memberList = memberIdList
.filter(id => resolver.puppet.selfIdOpt() match {
case Some(userId) => id != userId
case _ => true
})
.map(id => new Contact(id))
memberList.take(3).map(_.name).mkString(",")
}
}
}
def onMessage(messageListener:Message=>Unit): Unit ={
this.addListener(PuppetEventName.MESSAGE,messageListener)
}
def onJoin(joinListener:RoomJoinEvent =>Unit): Unit ={
this.addListener(PuppetEventName.ROOM_JOIN,joinListener)
}
def onLeave(leaveListener:RoomLeaveEvent =>Unit): Unit ={
this.addListener(PuppetEventName.ROOM_LEAVE,leaveListener)
}
def onTopic(topicListener:RoomTopicEvent =>Unit): Unit ={
this.addListener(PuppetEventName.ROOM_TOPIC,topicListener)
}
def announce(textOpt: Option[String]): String = {
textOpt match {
case Some(text) =>
resolver.puppet.roomAnnounce(this.id, text)
text
case _ =>
resolver.puppet.roomAnnounce(this.id)
}
}
def qrCode(): String = {
resolver.puppet.roomQRCode(this.id)
}
def has(contact: Contact): Boolean = {
this.memberList().exists(_.id == contact.id)
}
def owner(): Option[Contact] = {
if (this.payload != null && !isBlank(this.payload.ownerId)) {
Some(new Contact(this.payload.ownerId))
} else None
}
def avatar(): ResourceBox = {
resolver.puppet.roomAvatar(this.id)
}
}