提交 460550a0 编写于 作者: Huan (李卓桓)'s avatar Huan (李卓桓)

refactoring the puppet design with easy to test id(instead of the instance)

上级 0b568d21
......@@ -25,9 +25,9 @@ import {
Raven,
Sayable,
} from './config'
import PuppetAccessory from './puppet-accessory'
import { PuppetAccessory } from './puppet-accessory'
import Message from './message'
// import Message from './message'
/**
* Enum for Gender values.
......@@ -202,7 +202,8 @@ export class Contact extends PuppetAccessory implements Sayable {
}
try {
const contactList: Contact[] = await this.puppet.contactFindAll(query)
const contactIdList: string[] = await this.puppet.contactFindAll(query)
const contactList = contactIdList.map(id => this.load(id))
await Promise.all(contactList.map(c => c.ready()))
return contactList
......@@ -286,27 +287,33 @@ export class Contact extends PuppetAccessory implements Sayable {
public async say(textOrFile: string | FileBox): Promise<void> {
log.verbose('Contact', 'say(%s)', textOrFile)
let msg: Message
// let msg: Message
if (typeof textOrFile === 'string') {
msg = Message.createMO({
text : textOrFile,
to : this,
})
await this.puppet.messageSendText({
contactId: this.id,
}, textOrFile)
// msg = Message.createMO({
// text : textOrFile,
// to : this,
// })
} else if (textOrFile instanceof FileBox) {
msg = Message.createMO({
to : this,
file : textOrFile,
})
await this.puppet.messageSendFile({
contactId: this.id,
}, textOrFile)
// msg = Message.createMO({
// to : this,
// file : textOrFile,
// })
} else {
throw new Error('unsupported')
}
log.silly('Contact', 'say() from: %s to: %s content: %s',
this.puppet.userSelf(),
this,
msg,
)
await this.puppet.messageSend(msg)
// log.silly('Contact', 'say() from: %s to: %s content: %s',
// this.puppet.userSelf(),
// this,
// msg,
// )
// await this.puppet.messageSend(msg)
}
/**
......@@ -366,7 +373,7 @@ export class Contact extends PuppetAccessory implements Sayable {
return this.payload && this.payload.alias || null
}
const future = this.puppet.contactAlias(this, newAlias)
const future = this.puppet.contactAlias(this.id, newAlias)
future
.then(() => this.payload!.alias = newAlias)
......@@ -515,7 +522,7 @@ export class Contact extends PuppetAccessory implements Sayable {
public async avatar(): Promise<FileBox> {
log.verbose('Contact', 'avatar()')
return this.puppet.contactAvatar(this)
return this.puppet.contactAvatar(this.id)
}
/**
......
......@@ -147,7 +147,7 @@ export class FriendRequest extends PuppetAccessory {
log.verbose('PuppeteerFriendRequest', 'send() to %s', this.payload.contact)
await this.puppet.friendRequestSend(
this.payload.contact,
this.payload.contact.id,
this.payload.hello,
)
}
......@@ -164,7 +164,7 @@ export class FriendRequest extends PuppetAccessory {
}
log.verbose('FriendRequest', 'accept() to %s', this.payload.contact)
await this.puppet.friendRequestAccept(this.payload.contact, this.payload.ticket)
await this.puppet.friendRequestAccept(this.payload.contact.id, this.payload.ticket)
const max = 20
const backoff = 300
......
......@@ -428,12 +428,10 @@ export class Message extends PuppetAccessory implements Sayable {
/**
* File Message
*/
const msg = this.puppet.Message.createMO({
file : textOrFile,
to : from,
room,
})
await this.puppet.messageSend(msg)
await this.puppet.messageSendFile({
roomId : room && room.id || undefined,
contactId : from.id,
}, textOrFile)
}
}
......@@ -443,43 +441,25 @@ export class Message extends PuppetAccessory implements Sayable {
room : Room | null,
mentionList : Contact[],
): Promise<void> {
let msg: Message
if (!room) {
if (room && mentionList.length > 0) {
/**
* 1. to Individual
* 1 had mentioned someone
*/
msg = this.puppet.Message.createMO({
to,
text,
})
const mentionContact = mentionList[0]
const textMentionList = mentionList.map(c => '@' + c.name()).join(' ')
await this.puppet.messageSendText({
contactId: mentionContact.id,
roomId: room.id,
}, textMentionList + ' ' + text)
} else {
/**
* 2. in Room
* 2 did not mention anyone
*/
if (mentionList.length > 0) {
/**
* 2.1 had mentioned someone
*/
const mentionContact = mentionList[0]
const textMentionList = mentionList.map(c => '@' + c.name()).join(' ')
msg = this.puppet.Message.createMO({
to: mentionContact,
room,
text: textMentionList + ' ' + text,
})
} else {
/**
* 2.2 did not mention anyone
*/
msg = this.puppet.Message.createMO({
to,
room,
text,
})
}
await this.puppet.messageSendText({
contactId : to.id,
roomId : room && room.id || undefined,
}, text)
}
await this.puppet.messageSend(msg)
}
public file(): FileBox {
......@@ -822,8 +802,22 @@ export class Message extends PuppetAccessory implements Sayable {
public async forward(to: Room | Contact): Promise<void> {
log.verbose('Message', 'forward(%s)', to)
let roomId, contactId
if (to instanceof Room) {
roomId = to.id
}
if (to instanceof Contact) {
contactId = to.id
}
try {
await this.puppet.messageForward(this, to)
await this.puppet.messageForward(
{
contactId,
roomId,
},
this.id,
)
} catch (e) {
log.error('Message', 'forward(%s) exception: %s', to, e)
throw e
......
......@@ -23,18 +23,18 @@ import {
} from 'file-box'
import {
Message,
// Message,
MessagePayload,
} from '../message'
import {
Contact,
// Contact,
ContactQueryFilter,
Gender,
ContactType,
ContactPayload,
} from '../contact'
import {
Room,
// Room,
RoomPayload,
RoomQueryFilter,
} from '../room'
......@@ -44,6 +44,7 @@ import {
import {
Puppet,
PuppetOptions,
Receiver,
} from '../puppet/'
import {
......@@ -134,11 +135,11 @@ export class PuppetMock extends Puppet {
* Contact
*
*/
public contactAlias(contact: Contact) : Promise<string>
public contactAlias(contact: Contact, alias: string | null): Promise<void>
public contactAlias(contactId: string) : Promise<string>
public contactAlias(contactId: string, alias: string | null): Promise<void>
public async contactAlias(contact: Contact, alias?: string|null): Promise<void | string> {
log.verbose('PuppetMock', 'contactAlias(%s, %s)', contact, alias)
public async contactAlias(contactId: string, alias?: string|null): Promise<void | string> {
log.verbose('PuppetMock', 'contactAlias(%s, %s)', contactId, alias)
if (typeof alias === 'undefined') {
return 'mock alias'
......@@ -146,14 +147,14 @@ export class PuppetMock extends Puppet {
return
}
public async contactFindAll(query: ContactQueryFilter): Promise<Contact[]> {
public async contactFindAll(query: ContactQueryFilter): Promise<string[]> {
log.verbose('PuppetMock', 'contactFindAll(%s)', query)
return []
}
public async contactAvatar(contact: Contact): Promise<FileBox> {
log.verbose('PuppetMock', 'contactAvatar(%s)', contact)
public async contactAvatar(contactId: string): Promise<FileBox> {
log.verbose('PuppetMock', 'contactAvatar(%s)', contactId)
const WECHATY_ICON_PNG = path.resolve('../../docs/images/wechaty-icon.png')
return FileBox.fromLocal(WECHATY_ICON_PNG)
......@@ -205,14 +206,27 @@ export class PuppetMock extends Puppet {
return payload
}
public async messageSend(message: Message): Promise<void> {
log.verbose('PuppetMock', 'messageSend(%s)', message)
public async messageSendText(
receiver : Receiver,
text : string,
): Promise<void> {
log.verbose('PuppetMock', 'messageSend(%s, %s)', receiver, text)
}
public async messageSendFile(
receiver : Receiver,
file : FileBox,
): Promise<void> {
log.verbose('PuppetMock', 'messageSend(%s, %s)', receiver, file)
}
public async messageForward(message: Message, to: Contact | Room): Promise<void> {
public async messageForward(
receiver : Receiver,
messageId : string,
): Promise<void> {
log.verbose('PuppetMock', 'messageForward(%s, %s)',
message,
to,
receiver,
messageId,
)
}
......@@ -252,28 +266,31 @@ export class PuppetMock extends Puppet {
public async roomFindAll(
query: RoomQueryFilter = { topic: /.*/ },
): Promise<Room[]> {
): Promise<string[]> {
log.verbose('PuppetMock', 'roomFindAll(%s)', query)
return []
}
public async roomDel(
room : Room,
contact : Contact,
roomId : string,
contactId : string,
): Promise<void> {
log.verbose('PuppetMock', 'roomDel(%s, %s)', room, contact)
log.verbose('PuppetMock', 'roomDel(%s, %s)', roomId, contactId)
}
public async roomAdd(
room : Room,
contact : Contact,
roomId : string,
contactId : string,
): Promise<void> {
log.verbose('PuppetMock', 'roomAdd(%s, %s)', room, contact)
log.verbose('PuppetMock', 'roomAdd(%s, %s)', roomId, contactId)
}
public async roomTopic(room: Room, topic?: string): Promise<void | string> {
log.verbose('PuppetMock', 'roomTopic(%s, %s)', room, topic)
public async roomTopic(
roomId: string,
topic?: string,
): Promise<void | string> {
log.verbose('PuppetMock', 'roomTopic(%s, %s)', roomId, topic)
if (typeof topic === 'undefined') {
return 'mock room topic'
......@@ -281,18 +298,17 @@ export class PuppetMock extends Puppet {
return
}
public async roomCreate(contactList: Contact[], topic: string): Promise<Room> {
log.verbose('PuppetMock', 'roomCreate(%s, %s)', contactList, topic)
public async roomCreate(
contactIdList : string[],
topic : string,
): Promise<string> {
log.verbose('PuppetMock', 'roomCreate(%s, %s)', contactIdList, topic)
if (!contactList || ! contactList.map) {
throw new Error('contactList not found')
}
const r = this.Room.load('mock room id') as Room
return r
return 'mock_room_id'
}
public async roomQuit(room: Room): Promise<void> {
log.verbose('PuppetMock', 'roomQuit(%s)', room)
public async roomQuit(roomId: string): Promise<void> {
log.verbose('PuppetMock', 'roomQuit(%s)', roomId)
}
/**
......@@ -301,12 +317,18 @@ export class PuppetMock extends Puppet {
* FriendRequest
*
*/
public async friendRequestSend(contact: Contact, hello: string): Promise<void> {
log.verbose('PuppetMock', 'friendRequestSend(%s, %s)', contact, hello)
public async friendRequestSend(
contactId : string,
hello : string,
): Promise<void> {
log.verbose('PuppetMock', 'friendRequestSend(%s, %s)', contactId, hello)
}
public async friendRequestAccept(contact: Contact, ticket: string): Promise<void> {
log.verbose('PuppetMock', 'friendRequestAccept(%s, %s)', contact, ticket)
public async friendRequestAccept(
contactId : string,
ticket : string,
): Promise<void> {
log.verbose('PuppetMock', 'friendRequestAccept(%s, %s)', contactId, ticket)
}
}
......
......@@ -34,6 +34,7 @@ import {
import {
Puppet,
PuppetOptions,
Receiver,
ScanData,
} from '../puppet/'
import {
......@@ -67,7 +68,6 @@ import {
Gender,
} from '../contact'
import {
Message,
MessageDirection,
MessagePayload,
MessageType,
......@@ -412,16 +412,16 @@ export class PuppetPuppeteer extends Puppet {
*/
// public async forward(baseData: MsgRawObj, patchData: MsgRawObj): Promise<boolean> {
public async messageForward(
message : Message,
to : Contact | Room,
receiver : Receiver,
messageId : string,
): Promise<void> {
log.silly('PuppetPuppeteer', 'forward(%s, %s)',
message,
to,
)
log.silly('PuppetPuppeteer', 'forward(receiver=%s, messageId=%s)',
receiver,
messageId,
)
let rawPayload = await this.messageRawPayload(message.id)
let rawPayload = await this.messageRawPayload(messageId)
// rawPayload = Object.assign({}, rawPayload)
......@@ -451,7 +451,7 @@ export class PuppetPuppeteer extends Puppet {
newMsg.MMSourceMsgId = rawPayload.MsgId
// In room msg, the content prefix sender:, need to be removed, otherwise the forwarded sender will display the source message sender, causing self () to determine the error
newMsg.Content = Misc.unescapeHtml(rawPayload.Content.replace(/^@\w+:<br\/>/, '')).replace(/^[\w\-]+:<br\/>/, '')
newMsg.MMIsChatRoom = to instanceof Room ? true : false
newMsg.MMIsChatRoom = receiver instanceof Room ? true : false
// The following parameters need to be overridden after calling createMessage()
......@@ -461,7 +461,7 @@ export class PuppetPuppeteer extends Puppet {
// // all call success return true
// ret = (i === 0 ? true : ret) && await config.puppetInstance().forward(m, newMsg)
// }
newMsg.ToUserName = to.id
newMsg.ToUserName = receiver.contactId || receiver.roomId as string
// ret = await config.puppetInstance().forward(m, newMsg)
// return ret
const baseData = rawPayload
......@@ -479,48 +479,58 @@ export class PuppetPuppeteer extends Puppet {
}
}
public async messageSend(message: Message): Promise<void> {
log.verbose('PuppetPuppeteer', 'send(%s)', message)
const to = message.to()
const room = message.room()
public async messageSendText(
receiver : Receiver,
text : string,
): Promise<void> {
log.verbose('PuppetPuppeteer', 'messageSendText(receiver=%s, text=%s)', receiver, text)
let destinationId
if (room) {
destinationId = room.id
} else if (to) {
destinationId = to.id
if (receiver.roomId) {
destinationId = receiver.roomId
} else if (receiver.contactId) {
destinationId = receiver.contactId
} else {
throw new Error('PuppetPuppeteer.send(): message with neither room nor to?')
throw new Error('PuppetPuppeteer.messageSendText(): message with neither room nor to?')
}
if (message.type() === MessageType.Text) {
log.silly('PuppetPuppeteer', 'send() TEXT message.')
const text = message.text()
log.silly('PuppetPuppeteer', 'messageSendText() destination: %s, text: %s)',
destinationId,
text,
)
log.silly('PuppetPuppeteer', 'send() destination: %s, text: %s)',
destinationId,
text,
)
try {
await this.bridge.send(destinationId, text)
} catch (e) {
log.error('PuppetPuppeteer', 'messageSendText() exception: %s', e.message)
Raven.captureException(e)
throw e
}
}
try {
await this.bridge.send(destinationId, text)
} catch (e) {
log.error('PuppetPuppeteer', 'send() exception: %s', e.message)
Raven.captureException(e)
throw e
}
public async messageSendFile(
receiver : Receiver,
file : FileBox,
): Promise<void> {
log.verbose('PuppetPuppeteer', 'messageSendFile(receiver=%s, file=%s)', receiver, file)
let destinationId
if (receiver.roomId) {
destinationId = receiver.roomId
} else if (receiver.contactId) {
destinationId = receiver.contactId
} else {
log.silly('PuppetPuppeteer', 'send() non-TEXT message.')
log.error('PuppetPuppeteer', 'messageSend() sendMedia un-implement yet!!!')
// TODO: implement this!
// const ret = await this.sendMedia(message)
// if (!ret) {
// throw new Error('sendMedia fail')
// }
throw new Error('PuppetPuppeteer.messageSendFile(): message with neither room nor to?')
}
log.error('PuppetPuppeteer', 'messageSend() sendMedia un-implement yet!!! id: %s', destinationId)
// TODO: implement this!
// const ret = await this.sendMedia(message)
// if (!ret) {
// throw new Error('sendMedia fail')
// }
}
public async login(user: Contact): Promise<void> {
......@@ -631,8 +641,8 @@ export class PuppetPuppeteer extends Puppet {
}
}
public async contactAvatar(contact: Contact): Promise<FileBox> {
const payload = await this.contactPayload(contact.id)
public async contactAvatar(contactId: string): Promise<FileBox> {
const payload = await this.contactPayload(contactId)
if (!payload.avatar) {
throw new Error('Can not get avatar: no payload.avatar!')
}
......@@ -651,6 +661,9 @@ export class PuppetPuppeteer extends Puppet {
}
// return Misc.urlStream(avatarUrl, cookies)
const contact = this.Contact.load(contactId)
await contact.ready()
return FileBox.fromRemote(
avatarUrl,
contact.name() || 'unknown' + '-avatar.jpg',
......@@ -664,27 +677,27 @@ export class PuppetPuppeteer extends Puppet {
}
}
public contactAlias(contact: Contact) : Promise<string>
public contactAlias(contact: Contact, alias: string | null): Promise<void>
public contactAlias(contactId: string) : Promise<string>
public contactAlias(contactId: string, alias: string | null): Promise<void>
public async contactAlias(
contact: Contact,
alias?: string | null,
contactId : string,
alias? : string | null,
): Promise<string | void> {
if (typeof alias === 'undefined') {
throw new Error('to be implement')
}
try {
const ret = await this.bridge.contactAlias(contact.id, alias)
const ret = await this.bridge.contactAlias(contactId, alias)
if (!ret) {
log.warn('PuppetPuppeteer', 'contactRemark(%s, %s) bridge.contactAlias() return false',
contact.id, alias,
contactId, alias,
)
throw new Error('bridge.contactAlias fail')
}
} catch (e) {
log.warn('PuppetPuppeteer', 'contactRemark(%s, %s) rejected: %s', contact.id, alias, e.message)
log.warn('PuppetPuppeteer', 'contactRemark(%s, %s) rejected: %s', contactId, alias, e.message)
Raven.captureException(e)
throw e
}
......@@ -738,16 +751,13 @@ export class PuppetPuppeteer extends Puppet {
return filterFunction
}
public async contactFindAll(query: ContactQueryFilter): Promise<Contact[]> {
public async contactFindAll(query: ContactQueryFilter): Promise<string[]> {
const filterFunc = this.contactQueryFilterToFunctionString(query)
try {
const idList = await this.bridge.contactFind(filterFunc)
return idList.map(id => {
const c = this.Contact.load(id)
return c
})
return idList
} catch (e) {
log.warn('PuppetPuppeteer', 'contactFind(%s) rejected: %s', filterFunc, e.message)
Raven.captureException(e)
......@@ -882,7 +892,7 @@ export class PuppetPuppeteer extends Puppet {
public async roomFindAll(
query: RoomQueryFilter = { topic: /.*/ },
): Promise<Room[]> {
): Promise<string[]> {
let topicFilter = query.topic
......@@ -903,10 +913,7 @@ export class PuppetPuppeteer extends Puppet {
try {
const idList = await this.bridge.roomFind(filterFunction)
return idList.map(id => {
const r = this.Room.load(id) as Room
return r
})
return idList
} catch (e) {
log.warn('PuppetPuppeteer', 'roomFind(%s) rejected: %s', filterFunction, e.message)
Raven.captureException(e)
......@@ -914,9 +921,10 @@ export class PuppetPuppeteer extends Puppet {
}
}
public async roomDel(room: Room, contact: Contact): Promise<void> {
const roomId = room.id
const contactId = contact.id
public async roomDel(
roomId : string,
contactId : string,
): Promise<void> {
try {
await this.bridge.roomDelMember(roomId, contactId)
} catch (e) {
......@@ -926,24 +934,23 @@ export class PuppetPuppeteer extends Puppet {
}
}
public async roomAdd(room: Room, contact: Contact): Promise<void> {
const roomId = room.id
const contactId = contact.id
public async roomAdd(
roomId : string,
contactId : string,
): Promise<void> {
try {
await this.bridge.roomAddMember(roomId, contactId)
} catch (e) {
log.warn('PuppetPuppeteer', 'roomAddMember(%s) rejected: %s', contact, e.message)
log.warn('PuppetPuppeteer', 'roomAddMember(%s) rejected: %s', contactId, e.message)
Raven.captureException(e)
throw e
}
}
public async roomTopic(room: Room, topic: string): Promise<string> {
if (!room || typeof topic === 'undefined') {
return Promise.reject(new Error('room or topic not found'))
}
const roomId = room.id
public async roomTopic(
roomId : string,
topic : string,
): Promise<string> {
try {
return await this.bridge.roomModTopic(roomId, topic)
} catch (e) {
......@@ -953,20 +960,16 @@ export class PuppetPuppeteer extends Puppet {
}
}
public async roomCreate(contactList: Contact[], topic: string): Promise<Room> {
if (!contactList || ! contactList.map) {
throw new Error('contactList not found')
}
const contactIdList = contactList.map(c => c.id)
public async roomCreate(
contactIdList : string[],
topic : string,
): Promise<string> {
try {
const roomId = await this.bridge.roomCreate(contactIdList, topic)
if (!roomId) {
throw new Error('PuppetPuppeteer.roomCreate() roomId "' + roomId + '" not found')
}
const r = this.Room.load(roomId) as Room
return r
return roomId
} catch (e) {
log.warn('PuppetPuppeteer', 'roomCreate(%s, %s) rejected: %s', contactIdList.join(','), topic, e.message)
......@@ -975,8 +978,8 @@ export class PuppetPuppeteer extends Puppet {
}
}
public async roomQuit(room: Room): Promise<void> {
log.warn('PuppetPuppeteer', 'roomQuit(%s) not supported by Web API', room)
public async roomQuit(roomId: string): Promise<void> {
log.warn('PuppetPuppeteer', 'roomQuit(%s) not supported by Web API', roomId)
}
/**
......@@ -984,29 +987,27 @@ export class PuppetPuppeteer extends Puppet {
* FriendRequest
*
*/
public async friendRequestSend(contact: Contact, hello: string): Promise<void> {
if (!contact) {
throw new Error('contact not found')
}
public async friendRequestSend(
contactId : string,
hello : string,
): Promise<void> {
try {
await this.bridge.verifyUserRequest(contact.id, hello)
await this.bridge.verifyUserRequest(contactId, hello)
} catch (e) {
log.warn('PuppetPuppeteer', 'bridge.verifyUserRequest(%s, %s) rejected: %s', contact.id, hello, e.message)
log.warn('PuppetPuppeteer', 'bridge.verifyUserRequest(%s, %s) rejected: %s', contactId, hello, e.message)
Raven.captureException(e)
throw e
}
}
public async friendRequestAccept(contact: Contact, ticket: string): Promise<void> {
if (!contact || !ticket) {
throw new Error('contact or ticket not found')
}
public async friendRequestAccept(
contactId : string,
ticket : string,
): Promise<void> {
try {
await this.bridge.verifyUserOk(contact.id, ticket)
await this.bridge.verifyUserOk(contactId, ticket)
} catch (e) {
log.warn('PuppetPuppeteer', 'bridge.verifyUserOk(%s, %s) rejected: %s', contact.id, ticket, e.message)
log.warn('PuppetPuppeteer', 'bridge.verifyUserOk(%s, %s) rejected: %s', contactId, ticket, e.message)
Raven.captureException(e)
throw e
}
......
......@@ -2,5 +2,6 @@ export {
Puppet,
PuppetEventName,
PuppetOptions,
Receiver,
ScanData,
} from './puppet'
......@@ -85,16 +85,20 @@ export interface PuppetOptions {
wechaty: Wechaty,
}
export interface Receiver {
contactId? : string,
roomId? : string,
}
let PUPPET_COUNTER = 0
/**
* Abstract Puppet Class
*/
export abstract class Puppet extends EventEmitter implements Sayable {
public readonly state : StateSwitch
// public readonly classes : PuppetClasses
protected readonly watchdog: Watchdog
protected readonly watchdog : Watchdog
protected readonly counter : number
protected userId?: string
......@@ -107,7 +111,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
/* tslint:disable:variable-name */
public readonly Room : typeof Room
public counter: number
public readonly state : StateSwitch
/**
* childPkg stores the `package.json` that the NPM module who extends the `Puppet`
......@@ -255,23 +259,17 @@ export abstract class Puppet extends EventEmitter implements Sayable {
throw new Error('can not say before login')
}
let msg: Message
if (typeof textOrFile === 'string') {
msg = this.Message.createMO({
text : textOrFile,
to : this.userSelf(),
})
await this.messageSendText({
contactId: this.userSelf().id,
}, textOrFile)
} else if (textOrFile instanceof FileBox) {
msg = this.Message.createMO({
file: textOrFile,
to: this.userSelf(),
})
await this.messageSendFile({
contactId: this.userSelf().id,
}, textOrFile)
} else {
throw new Error('say() arg unknown')
}
await this.messageSend(msg)
}
/**
......@@ -293,8 +291,9 @@ export abstract class Puppet extends EventEmitter implements Sayable {
* Message
*
*/
public abstract async messageForward(message: Message, to: Contact | Room) : Promise<void>
public abstract async messageSend(message: Message) : Promise<void>
public abstract async messageForward(to: Receiver, messageId: string) : Promise<void>
public abstract async messageSendText(to: Receiver, text: string) : Promise<void>
public abstract async messageSendFile(to: Receiver, file: FileBox) : Promise<void>
public abstract async messageRawPayload(id: string) : Promise<any>
public abstract async messageRawPayloadParser(rawPayload: any) : Promise<MessagePayload>
......@@ -327,20 +326,20 @@ export abstract class Puppet extends EventEmitter implements Sayable {
* FriendRequest
*
*/
public abstract async friendRequestSend(contact: Contact, hello?: string) : Promise<void>
public abstract async friendRequestAccept(contact: Contact, ticket: string) : Promise<void>
public abstract async friendRequestSend(contactId: string, hello?: string) : Promise<void>
public abstract async friendRequestAccept(contactId: string, ticket: string) : Promise<void>
/**
*
* Room
*
*/
public abstract async roomAdd(room: Room, contact: Contact) : Promise<void>
public abstract async roomCreate(contactList: Contact[], topic?: string) : Promise<Room>
public abstract async roomDel(room: Room, contact: Contact) : Promise<void>
public abstract async roomFindAll(query?: RoomQueryFilter) : Promise<Room[]>
public abstract async roomQuit(room: Room) : Promise<void>
public abstract async roomTopic(room: Room, topic?: string) : Promise<string | void>
public abstract async roomAdd(roomId: string, contactId: string) : Promise<void>
public abstract async roomCreate(contactIdList: string[], topic?: string) : Promise<string>
public abstract async roomDel(roomId: string, contactId: string) : Promise<void>
public abstract async roomFindAll(query?: RoomQueryFilter) : Promise<string[]>
public abstract async roomQuit(roomId: string) : Promise<void>
public abstract async roomTopic(roomId: string, topic?: string) : Promise<string | void>
public abstract async roomRawPayload(id: string) : Promise<any>
public abstract async roomRawPayloadParser(rawPayload: any) : Promise<RoomPayload>
......@@ -357,11 +356,11 @@ export abstract class Puppet extends EventEmitter implements Sayable {
* Contact
*
*/
public abstract async contactAlias(contact: Contact) : Promise<string>
public abstract async contactAlias(contact: Contact, alias: string | null) : Promise<void>
public abstract async contactAlias(contact: Contact, alias?: string|null) : Promise<string | void>
public abstract async contactAvatar(contact: Contact) : Promise<FileBox>
public abstract async contactFindAll(query?: ContactQueryFilter) : Promise<Contact[]>
public abstract async contactAlias(contactId: string) : Promise<string>
public abstract async contactAlias(contactId: string, alias: string | null) : Promise<void>
public abstract async contactAlias(contactId: string, alias?: string|null) : Promise<string | void>
public abstract async contactAvatar(contactId: string) : Promise<FileBox>
public abstract async contactFindAll(query?: ContactQueryFilter) : Promise<string[]>
public abstract async contactRawPayload(id: string) : Promise<any>
public abstract async contactRawPayloadParser(rawPayload: any) : Promise<ContactPayload>
......
......@@ -32,10 +32,10 @@ import {
Sayable,
log,
} from './config'
import PuppetAccessory from './puppet-accessory'
import { PuppetAccessory } from './puppet-accessory'
import Contact from './contact'
import Message from './message'
import { Contact } from './contact'
// import Message from './message'
export const ROOM_EVENT_DICT = {
join: 'tbw',
......@@ -102,7 +102,9 @@ export class Room extends PuppetAccessory implements Sayable {
}
try {
const room = await this.puppet.roomCreate(contactList, topic)
const contactIdList = contactList.map(contact => contact.id)
const roomId = await this.puppet.roomCreate(contactIdList, topic)
const room = this.load(roomId)
return room
} catch (e) {
log.error('Room', 'create() exception: %s', e && e.stack || e.message || e)
......@@ -132,7 +134,8 @@ export class Room extends PuppetAccessory implements Sayable {
}
try {
const roomList = await this.puppet.roomFindAll(query)
const roomIdList = await this.puppet.roomFindAll(query)
const roomList = roomIdList.map(id => this.load(id))
await Promise.all(roomList.map(room => room.ready()))
return roomList
......@@ -302,7 +305,6 @@ export class Room extends PuppetAccessory implements Sayable {
? mention.map(c => c.name()).join(', ')
: mention ? mention.name() : '',
)
let msg: Message
let text: string
const replyToList: Contact[] = [].concat(mention as any || [])
......@@ -316,22 +318,17 @@ export class Room extends PuppetAccessory implements Sayable {
} else {
text = textOrFile
}
msg = this.puppet.Message.createMO({
room : this,
to : replyToList[0], // FIXME: is this right?
text,
})
await this.puppet.messageSendText({
roomId: this.id,
contactId: replyToList[0].id,
}, text)
} else if (textOrFile instanceof FileBox) {
msg = this.puppet.Message.createMO({
room: this,
to: replyToList[0],
file: textOrFile,
})
await this.puppet.messageSendFile({
roomId: this.id,
}, textOrFile)
} else {
throw new Error('arg unsupported')
}
await this.puppet.messageSend(msg)
}
public emit(event: 'leave', leaver: Contact[], remover?: Contact) : boolean
......@@ -427,7 +424,7 @@ export class Room extends PuppetAccessory implements Sayable {
*/
public async add(contact: Contact): Promise<void> {
log.verbose('Room', 'add(%s)', contact)
await this.puppet.roomAdd(this, contact)
await this.puppet.roomAdd(this.id, contact.id)
}
/**
......@@ -449,7 +446,7 @@ export class Room extends PuppetAccessory implements Sayable {
*/
public async del(contact: Contact): Promise<void> {
log.verbose('Room', 'del(%s)', contact)
await this.puppet.roomDel(this, contact)
await this.puppet.roomDel(this.id, contact.id)
this.delLocal(contact)
}
......@@ -472,7 +469,7 @@ export class Room extends PuppetAccessory implements Sayable {
*/
public async quit(): Promise<void> {
log.verbose('Room', 'quit() %s', this)
await this.puppet.roomQuit(this)
await this.puppet.roomQuit(this.id)
}
public topic() : string
......@@ -518,7 +515,7 @@ export class Room extends PuppetAccessory implements Sayable {
}
const future = this.puppet
.roomTopic(this, newTopic)
.roomTopic(this.id, newTopic)
.then(() => {
this.payload = {
...this.payload || {} as RoomPayload,
......
......@@ -632,15 +632,15 @@ export class Wechaty extends PuppetAccessory implements Sayable {
/**
* @private
*/
public async send(message: Message): Promise<void> {
try {
await this.puppet.messageSend(message)
} catch (e) {
log.error('Wechaty', 'send() exception: %s', e.message)
Raven.captureException(e)
throw e
}
}
// public async send(message: Message): Promise<void> {
// try {
// await this.puppet.messageSend(message)
// } catch (e) {
// log.error('Wechaty', 'send() exception: %s', e.message)
// Raven.captureException(e)
// throw e
// }
// }
/**
* Send message to filehelper
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册