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

passing lint!

上级 e107f5c6
...@@ -21,6 +21,7 @@ import * as path from 'path' ...@@ -21,6 +21,7 @@ import * as path from 'path'
/* tslint:disable:variable-name */ /* tslint:disable:variable-name */
import * as QrcodeTerminal from 'qrcode-terminal' import * as QrcodeTerminal from 'qrcode-terminal'
import finis from 'finis' import finis from 'finis'
import { FileBox } from 'file-box'
/** /**
* Change `import { ... } from '../'` * Change `import { ... } from '../'`
...@@ -103,9 +104,10 @@ bot ...@@ -103,9 +104,10 @@ bot
/** /**
* 2. reply qrcode image * 2. reply qrcode image
*/ */
const imageMessage = bot.Message.create(BOT_QR_CODE_IMAGE_FILE) const fileBox = FileBox.fromLocal(BOT_QR_CODE_IMAGE_FILE)
log.info('Bot', 'REPLY: %s', imageMessage)
await m.say(imageMessage) log.info('Bot', 'REPLY: %s', fileBox)
await m.say(fileBox)
/** /**
* 3. reply 'scan now!' * 3. reply 'scan now!'
......
...@@ -50,8 +50,8 @@ bot ...@@ -50,8 +50,8 @@ bot
console.log(`${url}\n[${code}] Scan QR Code in above url to login: `) console.log(`${url}\n[${code}] Scan QR Code in above url to login: `)
}) })
.on('login' , user => console.log(`${user} logined`)) .on('login' , user => console.log(`${user} logined`))
.on('message', m => { .on('message', msg => {
console.log(`RECV: ${m}`) console.log(`RECV: ${msg}`)
// console.log(inspect(m)) // console.log(inspect(m))
// saveRawObj(m.rawObj) // saveRawObj(m.rawObj)
...@@ -64,8 +64,8 @@ bot ...@@ -64,8 +64,8 @@ bot
// || m.type() === MsgType.APP // || m.type() === MsgType.APP
// || (m.type() === MsgType.TEXT && m.typeSub() === MsgType.LOCATION) // LOCATION // || (m.type() === MsgType.TEXT && m.typeSub() === MsgType.LOCATION) // LOCATION
// ) { // ) {
if (m.type() !== Message.Type.TEXT) { if (msg.type() !== Message.Type.Text) {
saveMediaFile(m) saveMediaFile(msg)
} }
// } // }
}) })
...@@ -73,7 +73,9 @@ bot ...@@ -73,7 +73,9 @@ bot
.catch(e => console.error('bot.start() error: ' + e)) .catch(e => console.error('bot.start() error: ' + e))
async function saveMediaFile(message: Message) { async function saveMediaFile(message: Message) {
const filename = message.filename() const fileBox = message.file()
const filename = fileBox.name
console.log('IMAGE local filename: ' + filename) console.log('IMAGE local filename: ' + filename)
if (!filename) { if (!filename) {
...@@ -84,8 +86,7 @@ async function saveMediaFile(message: Message) { ...@@ -84,8 +86,7 @@ async function saveMediaFile(message: Message) {
console.log('start to readyStream()') console.log('start to readyStream()')
try { try {
const netStream = await message.readyStream() fileBox
netStream
.pipe(fileStream) .pipe(fileStream)
.on('close', () => { .on('close', () => {
const stat = statSync(filename) const stat = statSync(filename)
......
...@@ -25,6 +25,7 @@ import { ...@@ -25,6 +25,7 @@ import {
import { import {
Message, Message,
MessagePayload, MessagePayload,
MessageDirection,
} from '../puppet/message' } from '../puppet/message'
import { import {
Contact, Contact,
...@@ -49,28 +50,16 @@ import { ...@@ -49,28 +50,16 @@ import {
import { import {
log, log,
} from '../config' } from '../config'
// import Profile from '../profile'
// import Wechaty from '../wechaty'
export type PuppetFoodType = 'scan' | 'ding' export type PuppetFoodType = 'scan' | 'ding'
export type ScanFoodType = 'scan' | 'login' | 'logout' export type ScanFoodType = 'scan' | 'login' | 'logout'
export class PuppetMock extends Puppet { export class PuppetMock extends Puppet {
private user?: Contact
constructor( constructor(
public options: PuppetOptions, public options: PuppetOptions,
) { ) {
super( super(options)
options,
// {
// Contact: Contact,
// FriendRequest: FriendRequest,
// Message: Message,
// Room: Room,
// },
)
} }
public toString() { public toString() {
...@@ -115,66 +104,6 @@ export class PuppetMock extends Puppet { ...@@ -115,66 +104,6 @@ export class PuppetMock extends Puppet {
this.state.off(true) this.state.off(true)
} }
public logonoff(): boolean {
if (this.user) {
return true
} else {
return false
}
}
public userSelf(): Contact {
log.verbose('PuppetMock', 'self()')
if (!this.user) {
throw new Error('not logged in, no userSelf yet.')
}
return this.user
}
public async messagePayload(message: Message): Promise<MessagePayload> {
log.verbose('PuppetMock', 'messagePayload(%s)', message)
const payload: MessagePayload = {
type : Message.Type.Text,
from : Contact.load('xxx'),
text : 'mock message text',
date : new Date(),
to: this.userSelf(),
}
return payload
}
public async messageSend(message: Message): Promise<void> {
log.verbose('PuppetMock', 'messageSend(%s)', message)
}
public async messageForward(message: Message, to: Contact | Room): Promise<void> {
log.verbose('PuppetMock', 'messageForward(%s, %s)',
message,
to,
)
}
public async send(message: Message): Promise<void> {
log.verbose('PuppetMock', 'send(%s)', message)
// TODO
}
public async say(text: string): Promise<void> {
if (!this.logonoff()) {
throw new Error('can not say before login')
}
const msg = Message.createMO({
text,
to: this.userSelf(),
})
msg.puppet = this
await this.send(msg)
}
public async logout(): Promise<void> { public async logout(): Promise<void> {
log.verbose('PuppetMock', 'logout()') log.verbose('PuppetMock', 'logout()')
...@@ -184,8 +113,15 @@ export class PuppetMock extends Puppet { ...@@ -184,8 +113,15 @@ export class PuppetMock extends Puppet {
this.emit('logout', this.user!) // becore we will throw above by logonoff() when this.user===undefined this.emit('logout', this.user!) // becore we will throw above by logonoff() when this.user===undefined
this.user = undefined this.user = undefined
// TODO: do the logout job
} }
/**
*
* Contact
*
*/
public contactAlias(contact: Contact) : Promise<string> public contactAlias(contact: Contact) : Promise<string>
public contactAlias(contact: Contact, alias: string | null): Promise<void> public contactAlias(contact: Contact, alias: string | null): Promise<void>
...@@ -211,8 +147,8 @@ export class PuppetMock extends Puppet { ...@@ -211,8 +147,8 @@ export class PuppetMock extends Puppet {
return FileBox.fromLocal(WECHATY_ICON_PNG) return FileBox.fromLocal(WECHATY_ICON_PNG)
} }
public async contactPayload(contact: Contact): Promise<ContactPayload> { public async contactPayload(id: string): Promise<ContactPayload> {
log.verbose('PuppetMock', 'contactPayload(%s)', contact) log.verbose('PuppetMock', 'contactPayload(%s)', id)
return { return {
gender: Gender.Unknown, gender: Gender.Unknown,
...@@ -221,8 +157,42 @@ export class PuppetMock extends Puppet { ...@@ -221,8 +157,42 @@ export class PuppetMock extends Puppet {
} }
public async roomPayload(room: Room): Promise<RoomPayload> { /**
log.verbose('PuppetMock', 'roomPayload(%s)', room) *
* Message
*
*/
public async messagePayload(id: string): Promise<MessagePayload> {
log.verbose('PuppetMock', 'messagePayload(%s)', id)
const payload: MessagePayload = {
date : new Date(),
direction : MessageDirection.MT,
from : Contact.load('xxx'),
text : 'mock message text',
to : this.userSelf(),
type : Message.Type.Text,
}
return payload
}
public async messageSend(message: Message): Promise<void> {
log.verbose('PuppetMock', 'messageSend(%s)', message)
}
public async messageForward(message: Message, to: Contact | Room): Promise<void> {
log.verbose('PuppetMock', 'messageForward(%s, %s)',
message,
to,
)
}
/**
*
* Room
*
*/
public async roomPayload(id: string): Promise<RoomPayload> {
log.verbose('PuppetMock', 'roomPayload(%s)', id)
return { return {
topic : 'mock topic', topic : 'mock topic',
...@@ -279,6 +249,12 @@ export class PuppetMock extends Puppet { ...@@ -279,6 +249,12 @@ export class PuppetMock extends Puppet {
log.verbose('PuppetMock', 'roomQuit(%s)', room) log.verbose('PuppetMock', 'roomQuit(%s)', room)
} }
/**
*
*
* FriendRequest
*
*/
public async friendRequestSend(contact: Contact, hello: string): Promise<void> { public async friendRequestSend(contact: Contact, hello: string): Promise<void> {
log.verbose('PuppetMock', 'friendRequestSend(%s, %s)', contact, hello) log.verbose('PuppetMock', 'friendRequestSend(%s, %s)', contact, hello)
} }
......
...@@ -27,15 +27,15 @@ import { ...@@ -27,15 +27,15 @@ import {
ScanData, ScanData,
} from '../puppet/' } from '../puppet/'
import PuppeteerContact from './puppeteer-contact' import Contact from '../puppet/contact'
import PuppeteerMessage from './puppeteer-message' import Message from '../puppet/message'
import Firer from './firer' import Firer from './firer'
import PuppetPuppeteer from './puppet-puppeteer' import PuppetPuppeteer from './puppet-puppeteer'
import { import {
WebMsgType, WebMsgType,
WebMessageRawPayload, WebMessageRawPayload,
} from '../puppet/schemas/' } from './web-schemas'
/* tslint:disable:variable-name */ /* tslint:disable:variable-name */
export const Event = { export const Event = {
...@@ -141,7 +141,7 @@ async function onLogin( ...@@ -141,7 +141,7 @@ async function onLogin(
log.silly('PuppetPuppeteerEvent', 'bridge.getUserName: %s', userId) log.silly('PuppetPuppeteerEvent', 'bridge.getUserName: %s', userId)
const user = PuppeteerContact.load(userId) const user = Contact.load(userId)
user.puppet = this user.puppet = this
await user.ready() await user.ready()
...@@ -188,35 +188,35 @@ async function onLogout( ...@@ -188,35 +188,35 @@ async function onLogout(
} }
async function onMessage( async function onMessage(
this: PuppetPuppeteer, this : PuppetPuppeteer,
obj: WebMessageRawPayload, rawPayload : WebMessageRawPayload,
): Promise<void> { ): Promise<void> {
let m = new PuppeteerMessage(obj) let msg = Message.createMT(rawPayload.MsgId)
m.puppet = this msg.puppet = this
try { try {
await m.ready() await msg.ready()
/** /**
* Fire Events if match message type & content * Fire Events if match message type & content
*/ */
switch (m.type()) { switch (rawPayload.MsgType) {
case WebMsgType.VERIFYMSG: case WebMsgType.VERIFYMSG:
Firer.checkFriendRequest.call(this, m) Firer.checkFriendRequest.call(this, msg)
break break
case WebMsgType.SYS: case WebMsgType.SYS:
if (m.room()) { if (msg.room()) {
const joinResult = await Firer.checkRoomJoin.call(this , m) const joinResult = await Firer.checkRoomJoin.call(this , msg)
const leaveResult = await Firer.checkRoomLeave.call(this , m) const leaveResult = await Firer.checkRoomLeave.call(this , msg)
const topicRestul = await Firer.checkRoomTopic.call(this , m) const topicRestul = await Firer.checkRoomTopic.call(this , msg)
if (!joinResult && !leaveResult && !topicRestul) { if (!joinResult && !leaveResult && !topicRestul) {
log.warn('PuppetPuppeteerEvent', `checkRoomSystem message: <${m.text()}> not found`) log.warn('PuppetPuppeteerEvent', `checkRoomSystem message: <${msg.text()}> not found`)
} }
} else { } else {
Firer.checkFriendConfirm.call(this, m) Firer.checkFriendConfirm.call(this, msg)
} }
break break
} }
...@@ -226,7 +226,7 @@ async function onMessage( ...@@ -226,7 +226,7 @@ async function onMessage(
* reload if needed * reload if needed
*/ */
switch (m.type()) { switch (rawPayload.MsgType) {
case WebMsgType.EMOTICON: case WebMsgType.EMOTICON:
case WebMsgType.IMAGE: case WebMsgType.IMAGE:
case WebMsgType.VIDEO: case WebMsgType.VIDEO:
...@@ -234,20 +234,20 @@ async function onMessage( ...@@ -234,20 +234,20 @@ async function onMessage(
case WebMsgType.MICROVIDEO: case WebMsgType.MICROVIDEO:
case WebMsgType.APP: case WebMsgType.APP:
log.verbose('PuppetPuppeteerEvent', 'onMessage() EMOTICON/IMAGE/VIDEO/VOICE/MICROVIDEO message') log.verbose('PuppetPuppeteerEvent', 'onMessage() EMOTICON/IMAGE/VIDEO/VOICE/MICROVIDEO message')
m = new PuppeteerMessage(obj) msg = Message.createMT(rawPayload.MsgId)
m.puppet = this msg.puppet = this
break break
case WebMsgType.TEXT: case WebMsgType.TEXT:
if (m.typeSub() === WebMsgType.LOCATION) { if (rawPayload.SubMsgType === WebMsgType.LOCATION) {
log.verbose('PuppetPuppeteerEvent', 'onMessage() (TEXT&LOCATION) message') log.verbose('PuppetPuppeteerEvent', 'onMessage() (TEXT&LOCATION) message')
m = new PuppeteerMessage(obj) msg = Message.createMT(rawPayload.MsgId)
} }
break break
} }
await m.ready() await msg.ready()
this.emit('message', m) this.emit('message', msg)
} catch (e) { } catch (e) {
log.error('PuppetPuppeteerEvent', 'onMessage() exception: %s', e.stack) log.error('PuppetPuppeteerEvent', 'onMessage() exception: %s', e.stack)
......
...@@ -26,15 +26,18 @@ import { ...@@ -26,15 +26,18 @@ import {
import { import {
WebRecomendInfo, WebRecomendInfo,
FriendRequest, WebMessageRawPayload,
} from '../puppet/' // FriendRequest,
} from './web-schemas'
import PuppetPuppeteer from './puppet-puppeteer' import PuppetPuppeteer from './puppet-puppeteer'
import PuppeteerContact from './puppeteer-contact' import PuppeteerContact from '../puppet/contact'
import {
FriendRequest,
} from '../puppet/friend-request'
import { import {
PuppeteerFriendRequest, Message,
} from './puppeteer-friend-request' } from '../puppet/message'
import PuppeteerMessage from './puppeteer-message'
/* tslint:disable:variable-name */ /* tslint:disable:variable-name */
export const Firer = { export const Firer = {
...@@ -109,26 +112,24 @@ const regexConfig = { ...@@ -109,26 +112,24 @@ const regexConfig = {
} }
async function checkFriendRequest( async function checkFriendRequest(
this: PuppetPuppeteer, this : PuppetPuppeteer,
msg: PuppeteerMessage, rawPayload : WebMessageRawPayload,
): Promise<void> { ): Promise<void> {
if (!msg.rawObj) { if (!rawPayload.RecommendInfo) {
throw new Error('no rawPayload')
} else if (!msg.rawObj.RecommendInfo) {
throw new Error('no RecommendInfo') throw new Error('no RecommendInfo')
} }
const rawPayload: WebRecomendInfo = msg.rawObj.RecommendInfo const recommendInfo: WebRecomendInfo = rawPayload.RecommendInfo
log.verbose('PuppetPuppeteerFirer', 'fireFriendRequest(%s)', rawPayload) log.verbose('PuppetPuppeteerFirer', 'fireFriendRequest(%s)', recommendInfo)
if (!rawPayload) { if (!recommendInfo) {
throw new Error('no rawPayload') throw new Error('no recommendInfo')
} }
const contact = PuppeteerContact.load(rawPayload.UserName) const contact = PuppeteerContact.load(recommendInfo.UserName)
contact.puppet = msg.puppet contact.puppet = this
const hello = rawPayload.Content const hello = recommendInfo.Content
const ticket = rawPayload.Ticket const ticket = recommendInfo.Ticket
await contact.ready() await contact.ready()
if (!contact.isReady()) { if (!contact.isReady()) {
...@@ -140,7 +141,7 @@ async function checkFriendRequest( ...@@ -140,7 +141,7 @@ async function checkFriendRequest(
hello, hello,
ticket, ticket,
) )
receivedRequest.puppet = msg.puppet receivedRequest.puppet = this
this.emit('friend', receivedRequest) this.emit('friend', receivedRequest)
} }
...@@ -165,7 +166,7 @@ function parseFriendConfirm( ...@@ -165,7 +166,7 @@ function parseFriendConfirm(
async function checkFriendConfirm( async function checkFriendConfirm(
this: PuppetPuppeteer, this: PuppetPuppeteer,
m: PuppeteerMessage, m: Message,
) { ) {
const content = m.text() const content = m.text()
log.silly('PuppetPuppeteerFirer', 'fireFriendConfirm(%s)', content) log.silly('PuppetPuppeteerFirer', 'fireFriendConfirm(%s)', content)
...@@ -176,7 +177,7 @@ async function checkFriendConfirm( ...@@ -176,7 +177,7 @@ async function checkFriendConfirm(
const contact = m.from() const contact = m.from()
const confirmedRequest = PuppeteerFriendRequest.createConfirm( const confirmedRequest = FriendRequest.createConfirm(
contact, contact,
) )
confirmedRequest.puppet = m.puppet confirmedRequest.puppet = m.puppet
...@@ -227,7 +228,7 @@ function parseRoomJoin( ...@@ -227,7 +228,7 @@ function parseRoomJoin(
async function checkRoomJoin( async function checkRoomJoin(
this: PuppetPuppeteer, this: PuppetPuppeteer,
msg: PuppeteerMessage, msg: Message,
): Promise<boolean> { ): Promise<boolean> {
const room = msg.room() const room = msg.room()
...@@ -379,7 +380,7 @@ function parseRoomLeave( ...@@ -379,7 +380,7 @@ function parseRoomLeave(
*/ */
async function checkRoomLeave( async function checkRoomLeave(
this: PuppetPuppeteer, this: PuppetPuppeteer,
m: PuppeteerMessage, m: Message,
): Promise<boolean> { ): Promise<boolean> {
log.verbose('PuppetPuppeteerFirer', 'fireRoomLeave(%s)', m.text()) log.verbose('PuppetPuppeteerFirer', 'fireRoomLeave(%s)', m.text())
...@@ -461,7 +462,7 @@ function parseRoomTopic( ...@@ -461,7 +462,7 @@ function parseRoomTopic(
async function checkRoomTopic( async function checkRoomTopic(
this: PuppetPuppeteer, this: PuppetPuppeteer,
m: PuppeteerMessage): Promise<boolean> { m: Message): Promise<boolean> {
let topic, changer let topic, changer
try { try {
[topic, changer] = parseRoomTopic.call(this, m.text()) [topic, changer] = parseRoomTopic.call(this, m.text())
......
...@@ -70,7 +70,6 @@ import { ...@@ -70,7 +70,6 @@ import {
MessagePayload, MessagePayload,
MessageType, MessageType,
} from '../puppet/message' } from '../puppet/message'
import PuppeteerMessage from './puppeteer-message'
import { import {
Room, Room,
RoomMemberQueryFilter, RoomMemberQueryFilter,
...@@ -106,19 +105,11 @@ export class PuppetPuppeteer extends Puppet { ...@@ -106,19 +105,11 @@ export class PuppetPuppeteer extends Puppet {
public scanWatchdog: Watchdog<ScanFoodType> public scanWatchdog: Watchdog<ScanFoodType>
// private fileId: number // private fileId: number
private user? : Contact
constructor( constructor(
public options: PuppetOptions, public options: PuppetOptions,
) { ) {
super(options, super(options)
// {
// Contact: Contact,
// FriendRequest: FriendRequest,
// Message: PuppeteerMessage,
// Room: Room,
// }
)
// this.fileId = 0 // this.fileId = 0
...@@ -126,10 +117,6 @@ export class PuppetPuppeteer extends Puppet { ...@@ -126,10 +117,6 @@ export class PuppetPuppeteer extends Puppet {
this.scanWatchdog = new Watchdog<ScanFoodType>(SCAN_TIMEOUT, 'Scan') this.scanWatchdog = new Watchdog<ScanFoodType>(SCAN_TIMEOUT, 'Scan')
} }
public toString() {
return `PuppetPuppeteer<${this.options.profile.name}>`
}
public async start(): Promise<void> { public async start(): Promise<void> {
log.verbose('PuppetPuppeteer', `start() with ${this.options.profile}`) log.verbose('PuppetPuppeteer', `start() with ${this.options.profile}`)
...@@ -326,32 +313,17 @@ export class PuppetPuppeteer extends Puppet { ...@@ -326,32 +313,17 @@ export class PuppetPuppeteer extends Puppet {
return this.bridge return this.bridge
} }
/** public async messagePayload(id: string): Promise<MessagePayload> {
* get self contact log.verbose('PuppetPuppeteer', 'messagePayload(%s)', id)
*/
public userSelf(): Contact {
log.verbose('PuppetPuppeteer', 'userSelf()')
if (!this.user) { const rawPayload = await this.messageRawPayload(id)
throw new Error('not logged in, no userSelf yet.')
}
return this.user
}
public async messagePayload(
message: Message,
): Promise<MessagePayload> {
log.verbose('PuppetPuppeteer', 'messagePayload(%s)', message)
const rawPayload = await this.messageRawPayload(message)
const payload = this.messageParseRawPayload(rawPayload) const payload = this.messageParseRawPayload(rawPayload)
return payload return payload
} }
private messageRawPayload(message: Message) { private messageRawPayload(id: string) {
return this.bridge.getMessage(message.id) return this.bridge.getMessage(id)
} }
private messageParseRawPayload( private messageParseRawPayload(
...@@ -446,7 +418,7 @@ export class PuppetPuppeteer extends Puppet { ...@@ -446,7 +418,7 @@ export class PuppetPuppeteer extends Puppet {
*/ */
// public async forward(baseData: MsgRawObj, patchData: MsgRawObj): Promise<boolean> { // public async forward(baseData: MsgRawObj, patchData: MsgRawObj): Promise<boolean> {
public async messageForward( public async messageForward(
message : PuppeteerMessage, message : Message,
to : Contact | Room, to : Contact | Room,
): Promise<void> { ): Promise<void> {
...@@ -455,7 +427,7 @@ export class PuppetPuppeteer extends Puppet { ...@@ -455,7 +427,7 @@ export class PuppetPuppeteer extends Puppet {
to, to,
) )
let rawPayload = await this.messageRawPayload(message) let rawPayload = await this.messageRawPayload(message.id)
// rawPayload = Object.assign({}, rawPayload) // rawPayload = Object.assign({}, rawPayload)
...@@ -513,7 +485,7 @@ export class PuppetPuppeteer extends Puppet { ...@@ -513,7 +485,7 @@ export class PuppetPuppeteer extends Puppet {
} }
} }
public async messageSend(message: PuppeteerMessage): Promise<void> { public async messageSend(message: Message): Promise<void> {
log.verbose('PuppetPuppeteer', 'send(%s)', message) log.verbose('PuppetPuppeteer', 'send(%s)', message)
const to = message.to() const to = message.to()
...@@ -557,29 +529,6 @@ export class PuppetPuppeteer extends Puppet { ...@@ -557,29 +529,6 @@ export class PuppetPuppeteer extends Puppet {
} }
} }
/**
* Bot say...
* send to `self` for notice / log
*/
public async say(text: string): Promise<void> {
if (!this.logonoff()) {
throw new Error('can not say before login')
}
if (!text) {
log.warn('PuppetPuppeteer', 'say(%s) can not say nothing', text)
return
}
if (!this.user) {
log.warn('PuppetPuppeteer', 'say(%s) can not say because no user', text)
this.emit('error', new Error('no this.user for PuppetPuppeteer'))
return
}
return await this.user.say(text)
}
public async login(user: Contact): Promise<void> { public async login(user: Contact): Promise<void> {
log.warn('PuppetPuppeteer', 'login(%s)', user) log.warn('PuppetPuppeteer', 'login(%s)', user)
this.user = user this.user = user
...@@ -664,22 +613,22 @@ export class PuppetPuppeteer extends Puppet { ...@@ -664,22 +613,22 @@ export class PuppetPuppeteer extends Puppet {
} }
} }
private async contactRawPayload(contact: Contact): Promise<WebContactRawPayload> { private async contactRawPayload(id: string): Promise<WebContactRawPayload> {
log.verbose('PuppetPuppeteer', 'contactRawPayload(%s)', contact) log.verbose('PuppetPuppeteer', 'contactRawPayload(%s)', id)
try { try {
const rawPayload = await this.bridge.getContact(contact.id) as WebContactRawPayload const rawPayload = await this.bridge.getContact(id) as WebContactRawPayload
return rawPayload return rawPayload
} catch (e) { } catch (e) {
log.error('PuppetPuppeteer', 'contactRawPayload(%d) exception: %s', contact, e.message) log.error('PuppetPuppeteer', 'contactRawPayload(%d) exception: %s', id, e.message)
Raven.captureException(e) Raven.captureException(e)
throw e throw e
} }
} }
public async contactPayload(contact: Contact): Promise<ContactPayload> { public async contactPayload(id: string): Promise<ContactPayload> {
log.verbose('PuppetPuppeteer', 'contactPayload(%s)', contact) log.verbose('PuppetPuppeteer', 'contactPayload(%s)', id)
const rawPayload = await this.contactRawPayload(contact) const rawPayload = await this.contactRawPayload(id)
const payload = this.contactParseRawPayload(rawPayload) const payload = this.contactParseRawPayload(rawPayload)
return payload return payload
} }
...@@ -695,7 +644,7 @@ export class PuppetPuppeteer extends Puppet { ...@@ -695,7 +644,7 @@ export class PuppetPuppeteer extends Puppet {
} }
public async contactAvatar(contact: Contact): Promise<FileBox> { public async contactAvatar(contact: Contact): Promise<FileBox> {
const payload = await this.contactPayload(contact) const payload = await this.contactPayload(contact.id)
if (!payload.avatar) { if (!payload.avatar) {
throw new Error('Can not get avatar: no payload.avatar!') throw new Error('Can not get avatar: no payload.avatar!')
} }
...@@ -819,8 +768,8 @@ export class PuppetPuppeteer extends Puppet { ...@@ -819,8 +768,8 @@ export class PuppetPuppeteer extends Puppet {
} }
} }
private async roomRawPayload(room: Room): Promise<PuppeteerRoomRawPayload> { private async roomRawPayload(id: string): Promise<PuppeteerRoomRawPayload> {
log.verbose('PuppetPuppeteer', 'roomRawPayload(%s)', room) log.verbose('PuppetPuppeteer', 'roomRawPayload(%s)', id)
try { try {
let rawPayload: PuppeteerRoomRawPayload | undefined // = await this.bridge.getContact(room.id) as PuppeteerRoomRawPayload let rawPayload: PuppeteerRoomRawPayload | undefined // = await this.bridge.getContact(room.id) as PuppeteerRoomRawPayload
...@@ -828,27 +777,27 @@ export class PuppetPuppeteer extends Puppet { ...@@ -828,27 +777,27 @@ export class PuppetPuppeteer extends Puppet {
// let currNum = rawPayload.MemberList && rawPayload.MemberList.length || 0 // let currNum = rawPayload.MemberList && rawPayload.MemberList.length || 0
// let prevNum = room.memberList().length // rawPayload && rawPayload.MemberList && this.rawObj.MemberList.length || 0 // let prevNum = room.memberList().length // rawPayload && rawPayload.MemberList && this.rawObj.MemberList.length || 0
let prevNum = 0
let ttl = 7 let ttl = 7
while (ttl--/* && currNum !== prevNum */) { while (ttl--/* && currNum !== prevNum */) {
rawPayload = await this.bridge.getContact(room.id) as PuppeteerRoomRawPayload rawPayload = await this.bridge.getContact(id) as PuppeteerRoomRawPayload
const currNum = rawPayload.MemberList && rawPayload.MemberList.length || 0 const currNum = rawPayload.MemberList && rawPayload.MemberList.length || 0
const prevNum = room.memberList().length // rawPayload && rawPayload.MemberList && this.rawObj.MemberList.length || 0
log.silly('PuppetPuppeteer', `roomPayload() this.bridge.getContact(%s) MemberList.length:%d at ttl:%d`, log.silly('PuppetPuppeteer', `roomPayload() this.bridge.getContact(%s) MemberList.length:%d at ttl:%d`,
room.id, id,
currNum, currNum,
ttl, ttl,
) )
if (currNum) { if (currNum > 0 && prevNum === currNum) {
if (prevNum === currNum) { log.silly('PuppetPuppeteer', `roomPayload() puppet.getContact(${id}) done at ttl:%d`, ttl)
log.silly('PuppetPuppeteer', `roomPayload() puppet.getContact(${room.id}) done at ttl:%d`, ttl) break
break
}
} }
prevNum = currNum
log.silly('PuppetPuppeteer', `roomPayload() puppet.getContact(${room.id}) retry at ttl:%d`, ttl) log.silly('PuppetPuppeteer', `roomPayload() puppet.getContact(${id}) retry at ttl:%d`, ttl)
await new Promise(r => setTimeout(r, 1000)) // wait for 1 second await new Promise(r => setTimeout(r, 1000)) // wait for 1 second
} }
...@@ -859,16 +808,16 @@ export class PuppetPuppeteer extends Puppet { ...@@ -859,16 +808,16 @@ export class PuppetPuppeteer extends Puppet {
return rawPayload return rawPayload
} catch (e) { } catch (e) {
log.error('PuppetPuppeteer', 'roomRawPayload(%s) exception: %s', room.id, e.message) log.error('PuppetPuppeteer', 'roomRawPayload(%s) exception: %s', id, e.message)
Raven.captureException(e) Raven.captureException(e)
throw e throw e
} }
} }
public async roomPayload(room: Room): Promise<RoomPayload> { public async roomPayload(id: string): Promise<RoomPayload> {
log.verbose('PuppetPuppeteer', 'roomPayload(%s)', room) log.verbose('PuppetPuppeteer', 'roomPayload(%s)', id)
const rawPayload = await this.roomRawPayload(room) const rawPayload = await this.roomRawPayload(id)
const payload = await this.roomParseRawPayload(rawPayload) const payload = await this.roomParseRawPayload(rawPayload)
return payload return payload
......
...@@ -31,21 +31,21 @@ import { ...@@ -31,21 +31,21 @@ import {
// Puppet, // Puppet,
// FriendRequest, // FriendRequest,
WebRecomendInfo, WebRecomendInfo,
} from '../puppet/' } from './web-schemas'
// import { // import {
// PuppetMock, // PuppetMock,
// } from '../puppet-mock/' // } from '../puppet-mock/'
import PuppeteerContact from './puppeteer-contact' import Contact from '../puppet/contact'
import PuppeteerMessage from './puppeteer-message' import Message from '../puppet/message'
import PuppeteerFriendRequest from './puppeteer-friend-request' import FriendRequest from '../puppet/friend-request'
import { PuppetPuppeteer } from './puppet-puppeteer' import { PuppetPuppeteer } from './puppet-puppeteer'
test('PuppetPuppeteerFriendRequest.receive smoke testing', async t => { test('PuppetPuppeteerFriendRequest.receive smoke testing', async t => {
// tslint:disable-next-line:variable-name // tslint:disable-next-line:variable-name
const MyFriendRequest = cloneClass(PuppeteerFriendRequest) const MyFriendRequest = cloneClass(FriendRequest)
// tslint:disable-next-line:variable-name // tslint:disable-next-line:variable-name
const MyContact = cloneClass(PuppeteerContact) const MyContact = cloneClass(Contact)
const puppet = new PuppetPuppeteer({ const puppet = new PuppetPuppeteer({
profile: new Profile(), profile: new Profile(),
...@@ -73,17 +73,17 @@ test('PuppetPuppeteerFriendRequest.receive smoke testing', async t => { ...@@ -73,17 +73,17 @@ test('PuppetPuppeteerFriendRequest.receive smoke testing', async t => {
) )
t.is(fr.hello(), '我是群聊"Wechaty"的李卓桓.PreAngel', 'should has right request message') t.is(fr.hello(), '我是群聊"Wechaty"的李卓桓.PreAngel', 'should has right request message')
t.true(fr.contact() instanceof PuppeteerContact, 'should have a Contact instance') t.true(fr.contact() instanceof Contact, 'should have a Contact instance')
t.is(fr.type(), MyFriendRequest.Type.Receive, 'should be receive type') t.is(fr.type(), MyFriendRequest.Type.Receive, 'should be receive type')
}) })
test('PuppetPuppeteerFriendRequest.confirm smoke testing', async t => { test('PuppetPuppeteerFriendRequest.confirm smoke testing', async t => {
// tslint:disable-next-line:variable-name // tslint:disable-next-line:variable-name
const MyFriendRequest = cloneClass(PuppeteerFriendRequest) const MyFriendRequest = cloneClass(FriendRequest)
// tslint:disable-next-line:variable-name // tslint:disable-next-line:variable-name
const MyContact = cloneClass(PuppeteerContact) const MyContact = cloneClass(Contact)
// tslint:disable-next-line:variable-name // tslint:disable-next-line:variable-name
const MyMessage = cloneClass(PuppeteerMessage) const MyMessage = cloneClass(Message)
const puppet = new PuppetPuppeteer({ const puppet = new PuppetPuppeteer({
profile: new Profile(), profile: new Profile(),
...@@ -105,6 +105,6 @@ test('PuppetPuppeteerFriendRequest.confirm smoke testing', async t => { ...@@ -105,6 +105,6 @@ test('PuppetPuppeteerFriendRequest.confirm smoke testing', async t => {
const contact = m.from() const contact = m.from()
const fr = MyFriendRequest.createConfirm(contact || new MyContact('xx')) const fr = MyFriendRequest.createConfirm(contact || new MyContact('xx'))
t.true(fr.contact() instanceof PuppeteerContact, 'should have a Contact instance') t.true(fr.contact() instanceof Contact, 'should have a Contact instance')
t.is(fr.type(), MyFriendRequest.Type.Confirm, 'should be confirm type') t.is(fr.type(), MyFriendRequest.Type.Confirm, 'should be confirm type')
}) })
...@@ -33,9 +33,16 @@ import Wechaty from '../wechaty' ...@@ -33,9 +33,16 @@ import Wechaty from '../wechaty'
// import { PuppetMock } from '../puppet-mock/' // import { PuppetMock } from '../puppet-mock/'
import Contact from '../puppet/contact' import {
import Message from '../puppet/message' Contact,
import Room from '../puppet/room' } from '../puppet/contact'
import {
Message,
MessagePayload,
} from '../puppet/message'
import {
Room,
} from '../puppet/room'
import PuppetPuppeteer from './puppet-puppeteer' import PuppetPuppeteer from './puppet-puppeteer'
...@@ -167,15 +174,29 @@ test('findAll()', async t => { ...@@ -167,15 +174,29 @@ test('findAll()', async t => {
test('self()', async t => { test('self()', async t => {
MyRoom.puppet = MyContact.puppet = MyMessage.puppet = puppet MyRoom.puppet = MyContact.puppet = MyMessage.puppet = puppet
const selfMsg = MyMessage.createMO({ const MOCK_CONTACT = Contact.load(MOCK_USER_ID)
from: Contact.load(MOCK_USER_ID),
const sandbox = sinon.createSandbox()
sandbox.stub(puppet, 'messagePayload').callsFake(() => {
const payload: MessagePayload = {
from : MOCK_CONTACT,
to : {} as any,
type : {} as any,
direction : {} as any,
date : {} as any,
}
return payload
}) })
sandbox.stub((puppet as any as { 'user': Contact }), 'user').value(MOCK_CONTACT)
const selfMsg = MyMessage.createMT('xxx')
t.true(selfMsg.self(), 'should identify self message true where message from userId') t.true(selfMsg.self(), 'should identify self message true where message from userId')
const otherMsg = MyMessage.createMO({ sandbox.stub((puppet as any as { 'user': Contact }), 'user').value(
from: Contact.load('fdsafasfsfa'), Contact.load('fsadfjas;dlkdjfl;asjflk;sjfl;as'),
}) )
const otherMsg = MyMessage.createMT('xxx')
t.false(otherMsg.self(), 'should identify self message false when from a different fromId') t.false(otherMsg.self(), 'should identify self message false when from a different fromId')
}) })
......
// import * as fs from 'fs'
// import * as path from 'path'
// import * as mime from 'mime'
// import {
// Readable,
// } from 'stream'
// import {
// Raven,
// log,
// } from '../config'
// import Misc from '../misc'
import {
Message,
} from '../puppet/'
// import PuppetPuppeteer from './puppet-puppeteer'
// import PuppeteerContact from './puppeteer-contact'
// import PuppeteerRoom from './puppeteer-room'
// import {
// WebAppMsgType,
// WebMessageRawPayload,
// WebMsgType,
// } from '../puppet/schemas/'
// export interface WebMsgPayload {
// id: string,
// type: WebMsgType,
// from: string,
// to?: string, // if to is not set, then room must be set
// room?: string,
// content: string,
// status: string,
// digest: string,
// date: number,
// url?: string, // for MessageMedia class
// }
export class PuppeteerMessage extends Message {}
export default PuppeteerMessage
...@@ -16,17 +16,13 @@ ...@@ -16,17 +16,13 @@
* limitations under the License. * limitations under the License.
* *
*/ */
import {
Gender,
} from '../contact'
export interface WebContactRawPayload { export interface WebContactRawPayload {
Alias: string, Alias: string,
City: string, City: string,
NickName: string, NickName: string,
Province: string, Province: string,
RemarkName: string, RemarkName: string,
Sex: Gender, Sex: number,
Signature: string, Signature: string,
StarFriend: string, StarFriend: string,
Uin: string, Uin: string,
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* *
* @ignore * @ignore
*/ */
import { FileBox } from 'file-box'
import { import {
log, log,
Raven, Raven,
...@@ -26,8 +28,6 @@ import PuppetAccessory from '../puppet-accessory' ...@@ -26,8 +28,6 @@ import PuppetAccessory from '../puppet-accessory'
import Message from './message' import Message from './message'
import PuppeteerMessage from '../puppet-puppeteer/puppeteer-message'
/** /**
* Enum for Gender values. * Enum for Gender values.
* *
...@@ -235,29 +235,34 @@ export class Contact extends PuppetAccessory implements Sayable { ...@@ -235,29 +235,34 @@ export class Contact extends PuppetAccessory implements Sayable {
* console.error(e) * console.error(e)
* } * }
*/ */
public async say(message: Message): Promise<void> public async say(file: FileBox): Promise<void>
public async say(textOrMessage: string | Message): Promise<void> { public async say(textOrFile: string | FileBox): Promise<void> {
log.verbose('Contact', 'say(%s)', textOrMessage) log.verbose('Contact', 'say(%s)', textOrFile)
let msg let msg: Message
if (textOrMessage instanceof Message) { if (typeof textOrFile === 'string') {
msg = textOrMessage msg = Message.createMO({
text : textOrFile,
to : this,
})
} else if (textOrFile instanceof FileBox) {
msg = Message.createMO({
to : this,
file : textOrFile,
})
} else { } else {
msg = new PuppeteerMessage() throw new Error('unsupported')
msg.puppet = this.puppet
msg.text(textOrMessage)
} }
msg.from(this.puppet.userSelf()) msg.puppet = this.puppet
msg.to(this)
log.silly('Contact', 'say() from: %s to: %s content: %s', log.silly('Contact', 'say() from: %s to: %s content: %s',
this.puppet.userSelf(), this.puppet.userSelf(),
this, this,
msg, msg,
) )
await this.puppet.send(msg) await this.puppet.messageSend(msg)
} }
/** /**
...@@ -454,16 +459,16 @@ export class Contact extends PuppetAccessory implements Sayable { ...@@ -454,16 +459,16 @@ export class Contact extends PuppetAccessory implements Sayable {
/** /**
* Get avatar picture file stream * Get avatar picture file stream
* *
* @returns {Promise<NodeJS.ReadableStream>} * @returns {Promise<FileBox>}
* @example * @example
* const avatarFileName = contact.name() + `.jpg` * const avatarFileName = contact.name() + `.jpg`
* const avatarReadStream = await contact.avatar() * const fileBox = await contact.avatar()
* const avatarWriteStream = createWriteStream(avatarFileName) * const avatarWriteStream = createWriteStream(avatarFileName)
* avatarReadStream.pipe(avatarWriteStream) * fileBox.pipe(avatarWriteStream)
* log.info('Bot', 'Contact: %s: %s with avatar file: %s', contact.weixin(), contact.name(), avatarFileName) * log.info('Bot', 'Contact: %s: %s with avatar file: %s', contact.weixin(), contact.name(), avatarFileName)
*/ */
// TODO: use File to replace ReadableStream // TODO: use File to replace ReadableStream
public async avatar(): Promise<NodeJS.ReadableStream> { public async avatar(): Promise<FileBox> {
log.verbose('Contact', 'avatar()') log.verbose('Contact', 'avatar()')
return this.puppet.contactAvatar(this) return this.puppet.contactAvatar(this)
...@@ -511,7 +516,7 @@ export class Contact extends PuppetAccessory implements Sayable { ...@@ -511,7 +516,7 @@ export class Contact extends PuppetAccessory implements Sayable {
} }
try { try {
this.payload = await this.puppet.contactPayload(this) this.payload = await this.puppet.contactPayload(this.id)
log.silly('Contact', `ready() this.puppet.contactPayload(%s) resolved`, this) log.silly('Contact', `ready() this.puppet.contactPayload(%s) resolved`, this)
// console.log(this.payload) // console.log(this.payload)
......
...@@ -26,5 +26,3 @@ export { ...@@ -26,5 +26,3 @@ export {
PuppetOptions, PuppetOptions,
ScanData, ScanData,
} from './puppet' } from './puppet'
export * from './schemas/'
...@@ -38,9 +38,6 @@ import { ...@@ -38,9 +38,6 @@ import {
MessageMOOptionsText, MessageMOOptionsText,
MessageMOOptionsFile, MessageMOOptionsFile,
MessagePayload, MessagePayload,
MessagePayloadText,
MessagePayloadFile,
MessagePayloadDirectionMT,
MessageType, MessageType,
} from './message.type' } from './message.type'
...@@ -85,11 +82,8 @@ export class Message extends PuppetAccessory implements Sayable { ...@@ -85,11 +82,8 @@ export class Message extends PuppetAccessory implements Sayable {
] ]
} }
public static create<T extends typeof Message>( public static create(options: MessageMOOptions): Message {
this: T, return this.createMO(options)
...args: any[]
): T['prototype'] {
return new (this as any)(...args)
} }
/** /**
...@@ -216,7 +210,7 @@ export class Message extends PuppetAccessory implements Sayable { ...@@ -216,7 +210,7 @@ export class Message extends PuppetAccessory implements Sayable {
if (!this.payload) { if (!this.payload) {
throw new Error('no payload') throw new Error('no payload')
} }
const file = (this.payload as MessagePayloadFile).file const file = this.payload.file
if (!file) { if (!file) {
throw new Error('no file') throw new Error('no file')
} }
...@@ -249,7 +243,7 @@ export class Message extends PuppetAccessory implements Sayable { ...@@ -249,7 +243,7 @@ export class Message extends PuppetAccessory implements Sayable {
// return // return
// } // }
const from = (<MessagePayloadDirectionMT>this.payload).from const from = this.payload.from
if (!from) { if (!from) {
throw new Error('no from') throw new Error('no from')
} }
...@@ -349,7 +343,7 @@ export class Message extends PuppetAccessory implements Sayable { ...@@ -349,7 +343,7 @@ export class Message extends PuppetAccessory implements Sayable {
// return // return
// } // }
return (<MessagePayloadText>this.payload).text || '' return this.payload.text || ''
} }
public async say(text: string, mention?: Contact | Contact[]): Promise<void> public async say(text: string, mention?: Contact | Contact[]): Promise<void>
...@@ -457,7 +451,7 @@ export class Message extends PuppetAccessory implements Sayable { ...@@ -457,7 +451,7 @@ export class Message extends PuppetAccessory implements Sayable {
if (!this.payload) { if (!this.payload) {
throw new Error('no payload') throw new Error('no payload')
} }
const file = (<MessagePayloadFile> this.payload).file const file = this.payload.file
if (!file) { if (!file) {
throw new Error('no file') throw new Error('no file')
} }
...@@ -645,7 +639,7 @@ export class Message extends PuppetAccessory implements Sayable { ...@@ -645,7 +639,7 @@ export class Message extends PuppetAccessory implements Sayable {
return return
} }
this.payload = await this.puppet.messagePayload(this) this.payload = await this.puppet.messagePayload(this.id)
// TODO ... the rest // TODO ... the rest
} }
......
...@@ -108,6 +108,8 @@ export abstract class Puppet extends EventEmitter implements Sayable { ...@@ -108,6 +108,8 @@ export abstract class Puppet extends EventEmitter implements Sayable {
protected readonly watchdog: Watchdog protected readonly watchdog: Watchdog
protected user?: Contact
/** /**
* childPkg stores the `package.json` that the NPM module who extends the `Puppet` * childPkg stores the `package.json` that the NPM module who extends the `Puppet`
*/ */
...@@ -159,6 +161,10 @@ export abstract class Puppet extends EventEmitter implements Sayable { ...@@ -159,6 +161,10 @@ export abstract class Puppet extends EventEmitter implements Sayable {
normalize(this.childPkg) normalize(this.childPkg)
} }
public toString() {
return `Puppet<${this.options.profile.name}>`
}
public emit(event: 'error', e: Error) : boolean public emit(event: 'error', e: Error) : boolean
public emit(event: 'friend', request: FriendRequest) : boolean public emit(event: 'friend', request: FriendRequest) : boolean
public emit(event: 'heartbeat', data: any) : boolean public emit(event: 'heartbeat', data: any) : boolean
...@@ -235,16 +241,52 @@ export abstract class Puppet extends EventEmitter implements Sayable { ...@@ -235,16 +241,52 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public abstract async start() : Promise<void> public abstract async start() : Promise<void>
public abstract async stop() : Promise<void> public abstract async stop() : Promise<void>
public abstract userSelf(): Contact public userSelf(): Contact {
log.verbose('Puppet', 'self()')
if (!this.user) {
throw new Error('not logged in, no userSelf yet.')
}
return this.user
}
// TODO: change Message to File public async say(textOrFile: string | FileBox) : Promise<void> {
public abstract async say(textOrFile: string | File) : Promise<void> if (!this.logonoff()) {
// public abstract async send(file: FileBox) : Promise<void> throw new Error('can not say before login')
}
let msg: Message
if (typeof textOrFile === 'string') {
msg = Message.createMO({
text : textOrFile,
to : this.userSelf(),
})
} else if (textOrFile instanceof FileBox) {
msg = Message.createMO({
file: textOrFile,
to: this.userSelf(),
})
} else {
throw new Error('say() arg unknown')
}
msg.puppet = this
await this.messageSend(msg)
}
/** /**
* Login / Logout * Login / Logout
*/ */
public abstract logonoff() : boolean public logonoff(): boolean {
if (this.user) {
return true
} else {
return false
}
}
// public abstract login(user: Contact): Promise<void> // public abstract login(user: Contact): Promise<void>
public abstract async logout(): Promise<void> public abstract async logout(): Promise<void>
...@@ -254,7 +296,7 @@ export abstract class Puppet extends EventEmitter implements Sayable { ...@@ -254,7 +296,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
* *
*/ */
public abstract async messageForward(message: Message, to: Contact | Room) : Promise<void> public abstract async messageForward(message: Message, to: Contact | Room) : Promise<void>
public abstract async messagePayload(message: Message) : Promise<MessagePayload> public abstract async messagePayload(id: string) : Promise<MessagePayload>
public abstract async messageSend(message: Message) : Promise<void> public abstract async messageSend(message: Message) : Promise<void>
/** /**
...@@ -274,7 +316,7 @@ export abstract class Puppet extends EventEmitter implements Sayable { ...@@ -274,7 +316,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public abstract async roomCreate(contactList: Contact[], topic?: string) : Promise<Room> public abstract async roomCreate(contactList: Contact[], topic?: string) : Promise<Room>
public abstract async roomDel(room: Room, contact: Contact) : Promise<void> public abstract async roomDel(room: Room, contact: Contact) : Promise<void>
public abstract async roomFindAll(query?: RoomQueryFilter) : Promise<Room[]> public abstract async roomFindAll(query?: RoomQueryFilter) : Promise<Room[]>
public abstract async roomPayload(room: Room) : Promise<RoomPayload> public abstract async roomPayload(id: string) : Promise<RoomPayload>
public abstract async roomQuit(room: Room) : Promise<void> public abstract async roomQuit(room: Room) : Promise<void>
public abstract async roomTopic(room: Room, topic?: string) : Promise<string | void> public abstract async roomTopic(room: Room, topic?: string) : Promise<string | void>
...@@ -289,7 +331,7 @@ export abstract class Puppet extends EventEmitter implements Sayable { ...@@ -289,7 +331,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
// TODO: change the return type from NodeJS.ReadableStream to File(vinyl) // TODO: change the return type from NodeJS.ReadableStream to File(vinyl)
public abstract async contactAvatar(contact: Contact) : Promise<FileBox> public abstract async contactAvatar(contact: Contact) : Promise<FileBox>
public abstract async contactPayload(contact: Contact) : Promise<ContactPayload> public abstract async contactPayload(id: string) : Promise<ContactPayload>
public abstract async contactFindAll(query?: ContactQueryFilter) : Promise<Contact[]> public abstract async contactFindAll(query?: ContactQueryFilter) : Promise<Contact[]>
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
*/ */
import * as util from 'util' import * as util from 'util'
import { FileBox } from 'file-box'
import { import {
// config, // config,
Raven, Raven,
...@@ -30,8 +32,6 @@ import PuppetAccessory from '../puppet-accessory' ...@@ -30,8 +32,6 @@ import PuppetAccessory from '../puppet-accessory'
import Contact from './contact' import Contact from './contact'
import Message from './message' import Message from './message'
import PuppeteerMessage from '../puppet-puppeteer/puppeteer-message'
export const ROOM_EVENT_DICT = { export const ROOM_EVENT_DICT = {
join: 'tbw', join: 'tbw',
leave: 'tbw', leave: 'tbw',
...@@ -224,7 +224,7 @@ export class Room extends PuppetAccessory implements Sayable { ...@@ -224,7 +224,7 @@ export class Room extends PuppetAccessory implements Sayable {
return return
} }
const payload = await this.puppet.roomPayload(this) const payload = await this.puppet.roomPayload(this.id)
await Promise.all( await Promise.all(
payload.memberList.map( payload.memberList.map(
contact => contact.ready(), contact => contact.ready(),
...@@ -247,13 +247,13 @@ export class Room extends PuppetAccessory implements Sayable { ...@@ -247,13 +247,13 @@ export class Room extends PuppetAccessory implements Sayable {
public say(text: string) : Promise<void> public say(text: string) : Promise<void>
public say(text: string, mention: Contact) : Promise<void> public say(text: string, mention: Contact) : Promise<void>
public say(text: string, mention: Contact[]) : Promise<void> public say(text: string, mention: Contact[]) : Promise<void>
public say(message: Message) : Promise<void> public say(file: FileBox) : Promise<void>
public say(text: never, ...args: never[]) : never public say(text: never, ...args: never[]) : never
/** /**
* Send message inside Room, if set [replyTo], wechaty will mention the contact as well. * Send message inside Room, if set [replyTo], wechaty will mention the contact as well.
* *
* @param {(string | MediaMessage)} textOrMessage - Send `text` or `media file` inside Room. * @param {(string | MediaMessage)} textOrFile - Send `text` or `media file` inside Room.
* @param {(Contact | Contact[])} [replyTo] - Optional parameter, send content inside Room, and mention @replyTo contact or contactList. * @param {(Contact | Contact[])} [replyTo] - Optional parameter, send content inside Room, and mention @replyTo contact or contactList.
* @returns {Promise<boolean>} * @returns {Promise<boolean>}
* If bot send message successfully, it will return true. If the bot failed to send for blocking or any other reason, it will return false * If bot send message successfully, it will return true. If the bot failed to send for blocking or any other reason, it will return false
...@@ -272,36 +272,46 @@ export class Room extends PuppetAccessory implements Sayable { ...@@ -272,36 +272,46 @@ export class Room extends PuppetAccessory implements Sayable {
* await room.say('Hello world!', contact) * await room.say('Hello world!', contact)
*/ */
public async say( public async say(
textOrMessage : string | Message, textOrFile : string | FileBox,
mention? : Contact | Contact[], mention? : Contact | Contact[],
): Promise<void> { ): Promise<void> {
log.verbose('Room', 'say(%s, %s)', log.verbose('Room', 'say(%s, %s)',
textOrMessage, textOrFile,
Array.isArray(mention) Array.isArray(mention)
? mention.map(c => c.name()).join(', ') ? mention.map(c => c.name()).join(', ')
: mention ? mention.name() : '', : mention ? mention.name() : '',
) )
let msg: Message let msg: Message
if (textOrMessage instanceof Message) { let text: string
msg = textOrMessage
} else { const replyToList: Contact[] = [].concat(mention as any || [])
msg = new PuppeteerMessage() // FIXME
msg.puppet = this.puppet
const replyToList: Contact[] = [].concat(mention as any || []) if (typeof textOrFile === 'string') {
if (replyToList.length > 0) { if (replyToList.length > 0) {
const AT_SEPRATOR = String.fromCharCode(8197) const AT_SEPRATOR = String.fromCharCode(8197)
const mentionList = replyToList.map(c => '@' + c.name()).join(AT_SEPRATOR) const mentionList = replyToList.map(c => '@' + c.name()).join(AT_SEPRATOR)
msg.text(mentionList + ' ' + textOrMessage) text = mentionList + ' ' + textOrFile
} else { } else {
msg.text(textOrMessage) text = textOrFile
} }
// m.to(replyToList[0]) msg = Message.createMO({
room : this,
to : replyToList[0], // FIXME: is this right?
text,
})
} else if (textOrFile instanceof FileBox) {
msg = Message.createMO({
room: this,
to: replyToList[0],
file: textOrFile,
})
} else {
throw new Error('arg unsupported')
} }
msg.room(this)
await this.puppet.send(msg) msg.puppet = this.puppet
await this.puppet.messageSend(msg)
} }
public emit(event: 'leave', leaver: Contact[], remover?: Contact) : boolean public emit(event: 'leave', leaver: Contact[], remover?: Contact) : boolean
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册