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

Merge branch 'master' of github.com:Chatie/wechaty

......@@ -55,6 +55,11 @@ WORKDIR /wechaty
COPY package.json .
RUN npm install \
&& npm install \
wechaty-puppet-ioscat \
wechaty-puppet-puppeteer \
wechaty-puppet-padchat \
wechaty-puppet-wechat4u \
&& sudo rm -fr /tmp/* ~/.npm
COPY . .
......
{
"name": "wechaty",
"version": "0.19.112",
"version": "0.19.114",
"description": "Wechaty is a Bot SDK for Wechat Personal Account",
"main": "dist/src/index.js",
"typings": "dist/src/index.d.ts",
......@@ -89,7 +89,7 @@
"read-pkg-up": "^4.0.0",
"state-switch": "^0.6.2",
"watchdog": "^0.8.1",
"wechaty-puppet": "^0.9.20",
"wechaty-puppet": "^0.9.22",
"ws": "^6.0.0"
},
"devDependencies": {
......
......@@ -10,5 +10,5 @@ else
echo "Generating docs ..."
npm run dist
echo -e '# Wechaty v'$(jq -r .version package.json)' Documentation\n\n* <https://blog.chatie.io>\n\n' > docs/index.md
jsdoc2md dist/src/wechaty.js dist/src/user/{room,contact,contact-self,friendship,message}.js >> docs/index.md
jsdoc2md dist/src/wechaty.js dist/src/user/{room,contact,contact-self,friendship,message,room-invitation}.js >> docs/index.md
fi
......@@ -35,6 +35,10 @@ import {
Contact,
} from './contact'
/**
*
* accept room invitation
*/
export class RoomInvitation extends Accessory implements Acceptable {
public static load<T extends typeof RoomInvitation> (
......@@ -46,7 +50,7 @@ export class RoomInvitation extends Accessory implements Acceptable {
}
/**
*
* @ignore
* Instance Properties
*
*/
......@@ -76,7 +80,7 @@ export class RoomInvitation extends Accessory implements Acceptable {
}
/**
* @hidden
* @ignore
*/
public async toStringAsync (): Promise<string> {
const payload = await this.puppet.roomInvitationPayload(this.id)
......@@ -179,6 +183,7 @@ export class RoomInvitation extends Accessory implements Acceptable {
/**
* List of Room Members that you known(is friend)
* @ignore
*/
public async roomMemberList (): Promise<Contact[]> {
log.verbose('RoomInvitation', 'roomMemberList()')
......@@ -198,6 +203,11 @@ export class RoomInvitation extends Accessory implements Acceptable {
return contactList
}
/**
* Get the invitation time
*
* @returns {Promise<Date>}
*/
public async date (): Promise<Date> {
log.verbose('RoomInvitation', 'date()')
......
......@@ -22,7 +22,6 @@
import test from 'blue-tape'
import sinon from 'sinon'
// import asyncHooks from 'async_hooks'
import { PuppetMock } from 'wechaty-puppet-mock'
import {
......@@ -181,3 +180,63 @@ test('Wechaty restart for many times', async t => {
}
})
test('@event ready', async t => {
const puppet = new PuppetMock()
const wechaty = new Wechaty({ puppet })
const sandbox = sinon.createSandbox()
const spy = sandbox.spy()
wechaty.on('ready', spy)
t.true(spy.notCalled, 'should no ready event with new wechaty instance')
await wechaty.start()
t.true(spy.notCalled, 'should no ready event right start wechaty started')
puppet.emit('ready')
t.true(spy.calledOnce, 'should fire ready event after puppet ready')
await wechaty.stop()
await wechaty.start()
puppet.emit('ready')
t.true(spy.calledTwice, 'should fire ready event second time after stop/start wechaty')
await wechaty.stop()
})
test('ready()', async t => {
const puppet = new PuppetMock()
const wechaty = new Wechaty({ puppet })
const sandbox = sinon.createSandbox()
const spy = sandbox.spy()
wechaty.ready()
.then(spy)
.catch(e => t.fail('rejection: ' + e))
t.true(spy.notCalled, 'should not ready with new wechaty instance')
await wechaty.start()
t.true(spy.notCalled, 'should not ready after right start wechaty')
puppet.emit('ready')
await new Promise(r => setImmediate(r))
t.true(spy.calledOnce, 'should ready after puppet ready')
await wechaty.stop()
await wechaty.start()
wechaty.ready()
.then(spy)
.catch(e => t.fail('rejection: ' + e))
puppet.emit('ready')
await new Promise(r => setImmediate(r))
t.true(spy.calledTwice, 'should ready again after stop/start wechaty')
await wechaty.stop()
})
......@@ -88,6 +88,7 @@ export const WECHATY_EVENT_DICT = {
dong : 'tbw',
error : 'tbw',
heartbeat : 'tbw',
ready : 'All underlined data source are ready for use.',
start : 'tbw',
stop : 'tbw',
}
......@@ -128,7 +129,8 @@ export class Wechaty extends Accessory implements Sayable {
public readonly VERSION = VERSION
public readonly state : StateSwitch
public readonly state : StateSwitch
private readonly readyState : StateSwitch
/**
* singleton globalInstance
......@@ -232,7 +234,9 @@ export class Wechaty extends Accessory implements Sayable {
this.id = cuid()
this.memory = new MemoryCard(options.profile || undefined)
this.state = new StateSwitch('Wechaty', log)
this.state = new StateSwitch('Wechaty', log)
this.readyState = new StateSwitch('WechatyReady', log)
/**
* @ignore
......@@ -273,6 +277,7 @@ export class Wechaty extends Accessory implements Sayable {
public emit (event: 'heartbeat' , data: any) : boolean
public emit (event: 'login' | 'logout', user: ContactSelf) : boolean
public emit (event: 'message' , message: Message) : boolean
public emit (event: 'ready') : boolean
public emit (event: 'room-invite', roomInvitation: RoomInvitation) : boolean
public emit (event: 'room-join' , room: Room, inviteeList : Contact[], inviter : Contact) : boolean
public emit (event: 'room-leave' , room: Room, leaverList : Contact[], remover? : Contact) : boolean
......@@ -296,6 +301,7 @@ export class Wechaty extends Accessory implements Sayable {
public on (event: 'heartbeat' , listener: string | ((this: Wechaty, data: any) => void)) : this
public on (event: 'login' | 'logout', listener: string | ((this: Wechaty, user: ContactSelf) => void)) : this
public on (event: 'message' , listener: string | ((this: Wechaty, message: Message) => void)) : this
public on (event: 'ready' , listener: string | ((this: Wechaty) => void)) : this
public on (event: 'room-invite', listener: string | ((this: Wechaty, roomInvitation: RoomInvitation) => void)) : this
public on (event: 'room-join' , listener: string | ((this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void)) : this
public on (event: 'room-leave' , listener: string | ((this: Wechaty, room: Room, leaverList: Contact[], remover?: Contact) => void)) : this
......@@ -318,6 +324,7 @@ export class Wechaty extends Accessory implements Sayable {
* @property {string} room-join - Emit when anyone join any room.
* @property {string} room-topic - Get topic event, emitted when someone change room topic.
* @property {string} room-leave - Emit when anyone leave the room.<br>
* @property {string} room-invite - Emit when there is a room invitation, see more in {@link RoomInvitation}
* If someone leaves the room by themselves, wechat will not notice other people in the room, so the bot will never get the "leave" event.
* @property {string} scan - A scan event will be emitted when the bot needs to show you a QR Code for scanning. </br>
* It is recommend to install qrcode-terminal(run `npm install qrcode-terminal`) in order to show qrcode in the terminal.
......@@ -346,6 +353,8 @@ export class Wechaty extends Accessory implements Sayable {
* @property {Function} room-join -(this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void
* @property {Function} room-topic -(this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact) => void
* @property {Function} room-leave -(this: Wechaty, room: Room, leaverList: Contact[]) => void
* @property {Function} room-invite -(this: Wechaty, room: Room, leaverList: Contact[]) => void <br>
* see more in {@link RoomInvitation}
*/
/**
......@@ -436,6 +445,18 @@ export class Wechaty extends Accessory implements Sayable {
* console.log(`Room ${room.topic()} topic changed from ${oldTopic} to ${topic} by ${changer.name()}`)
* })
*
* @example <caption>Event:room-invite, RoomInvitation has been encapsulated as a RoomInvitation Class. </caption>
* // room-invite Event will emit when there's an room invitation.
*
* bot.on('room-invite', async roomInvitation => {
* try {
* console.log(`received room-invite event.`)
* await roomInvitation.accept()
* } catch (e) {
* console.error(e)
* }
* }
*
* @example <caption>Event:error </caption>
* // error Event will emit when there's an error occurred.
*
......@@ -545,7 +566,9 @@ export class Wechaty extends Accessory implements Sayable {
}
protected initPuppetEventBridge (puppet: Puppet) {
const eventNameList: PuppetEventName[] = Object.keys(PUPPET_EVENT_DICT) as any
log.verbose('Wechaty', 'initPuppetEventBridge(%s)', puppet)
const eventNameList: PuppetEventName[] = Object.keys(PUPPET_EVENT_DICT) as PuppetEventName[]
for (const eventName of eventNameList) {
log.verbose('Wechaty', 'initPuppetEventBridge() puppet.on(%s) registered', eventName)
......@@ -609,6 +632,15 @@ export class Wechaty extends Accessory implements Sayable {
})
break
case 'ready':
puppet.on('ready', () => {
log.silly('Wechaty', 'initPuppetEventBridge() puppet.on(ready)')
this.emit('ready')
this.readyState.on(true)
})
break
case 'room-invite':
puppet.on('room-invite', async roomInvitationId => {
const roomInvitation = this.RoomInvitation.load(roomInvitationId)
......@@ -743,6 +775,8 @@ export class Wechaty extends Accessory implements Sayable {
return
}
this.readyState.off(true)
if (this.lifeTimer) {
throw new Error('start() lifeTimer exist')
}
......@@ -811,6 +845,8 @@ export class Wechaty extends Accessory implements Sayable {
return
}
this.readyState.off(true)
this.state.off('pending')
await this.memory.save()
......@@ -840,15 +876,16 @@ export class Wechaty extends Accessory implements Sayable {
this.state.off(true)
this.emit('stop')
/**
* MUST use setImmediate at here(the end of this function),
* because we need to run the micro task registered by the `emit` method
*/
setImmediate(() => this.puppet.removeAllListeners())
return
}
public async ready (): Promise<void> {
log.verbose('Wechaty', 'ready()')
return this.readyState.ready('on').then(() => {
log.silly('Wechaty', 'ready() this.readyState.ready(on) resolved')
})
}
/**
* Logout the bot
*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册