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

passing lint!

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