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

merge

......@@ -92,7 +92,7 @@ bot
* when request is set, we can get verify message from `request.hello`,
* and accept this request by `request.accept()`
*/
if (request.hello === 'ding') {
if (request.hello() === 'ding') {
logMsg = 'accepted because verify messsage is "ding"'
request.accept()
......
......@@ -53,7 +53,7 @@ export async function onFriend(
3000,
)
if (request.hello === 'ding') {
if (request.hello() === 'ding') {
const myRoom = await this.Room.find({ topic: 'ding' })
if (!myRoom) return
setTimeout(
......
{
"name": "wechaty",
"version": "0.15.27",
"version": "0.15.30",
"description": "Wechat for Bot(Personal Account)",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
......@@ -97,13 +97,14 @@
"node": ">= 8.5"
},
"dependencies": {
"@types/ws": "^4.0.1",
"@types/ws": "^5.1.0",
"bl": "^1.2.0",
"brolog": "^1.2.0",
"clone-class": "^0.6.1",
"clone-class": "^0.6.3",
"cuid": "^2.1.1",
"hot-import": "^0.1.0",
"mime": "^2.2.0",
"normalize-package-data": "^2.4.0",
"puppeteer": "^1.2.0",
"raven": "^2.2.0",
"read-pkg-up": "^3.0.0",
......@@ -125,13 +126,14 @@
"@types/fluent-ffmpeg": "^2.1.0",
"@types/glob": "^5.0.0p",
"@types/mime": "^2.0.0",
"@types/node": "^9.6.7",
"@types/node": "^10.0.3",
"@types/normalize-package-data": "^2.4.0",
"@types/puppeteer": "^1.0.0",
"@types/raven": "^2.1.0",
"@types/read-pkg-up": "^3.0.0",
"@types/request": "^2.0.0",
"@types/semver": "^5.5.0",
"@types/sinon": "^4.3.0",
"@types/sinon": "^4.3.1",
"@types/xml2js": "^0.4.0",
"apiai": "^4.0.0",
"babel-cli": "^6.26.0",
......@@ -156,7 +158,7 @@
"qrcode-terminal": "^0.12.0",
"semver": "^5.5.0",
"shx": "^0.2.0",
"sinon": "^5.0.0",
"sinon": "^5.0.2",
"sinon-test": "^2.1.2",
"sloc": "^0.2.0",
"ts-node": "^6.0.0",
......
......@@ -49,12 +49,17 @@ export abstract class PuppetAccessory extends EventEmitter {
private _puppet?: Puppet
public set puppet(puppet: Puppet) {
log.silly('PuppetAccessory', '<%s> set puppet(%s)', this[PUPPET_ACCESSORY_NAME], puppet.constructor.name)
log.silly('PuppetAccessory', '<%s> set puppet(%s)',
this[PUPPET_ACCESSORY_NAME],
puppet.constructor.name,
)
this._puppet = puppet
}
public get puppet(): Puppet {
log.silly('PuppetAccessory', '<%s> get puppet()', this[PUPPET_ACCESSORY_NAME])
log.silly('PuppetAccessory', '<%s> get puppet()',
this[PUPPET_ACCESSORY_NAME],
)
if (this._puppet) {
return this._puppet
......
# PUPPET-MOCK
```ts
import PuppetMock from 'wechaty-puppet-mock'
const puppet = new PuppetMock({
profile,
})
const wechaty = new Wechaty({
puppet,
})
```
## HELPER UTILITIES
### StateSwitch
```ts
this.state.on('pending')
this.state.on(true)
this.state.off('pending')
this.state.off(true)
await this.state.ready('on')
await this.state.ready('off')
```
### Watchdog
```ts
```
### Profile
```ts
this.profile.set('config', { id: 1, key: 'xxx' })
const config = await this.profile.get('config')
```
......@@ -22,23 +22,27 @@ import {
log,
} from '../config'
import { FriendRequest } from '../puppet/'
import { FriendRequest, FriendRequestType } from '../puppet/'
import MockContact from './mock-contact'
export class MockFriendRequest extends FriendRequest {
public info: any
public payload: any
private ticket: string
private _contact: MockContact
private _type: FriendRequestType
private _hello: string
constructor() {
log.verbose('MockFriendRequest', 'constructor()')
super()
}
public receive(info: any): void {
log.verbose('MockFriendRequest', 'receive(%s)', info)
public receive(payload: any): void {
log.verbose('MockFriendRequest', 'receive(%s)', payload)
this.payload = payload
}
public confirm(contact: MockContact): void {
......@@ -52,9 +56,24 @@ export class MockFriendRequest extends FriendRequest {
public async accept(): Promise<void> {
log.verbose('FriendRequest', 'accept() %s', this.contact)
await this.puppet.friendRequestAccept(this.contact, this.ticket)
await this.puppet.friendRequestAccept(this.contact(), this.ticket)
}
public contact(): MockContact {
return this._contact
}
public type(): FriendRequestType {
return this._type
}
public async reject(): Promise<void> {
log.verbose('MockFriendRequest', 'reject()')
}
public hello(): string {
return this._hello
}
}
export default MockFriendRequest
......@@ -91,6 +91,21 @@ export class MockMessage extends Message {
return loadedContact
}
public to(contact: MockContact): this
public to(id: string): this
public to(): MockContact | null // if to is not set, then room must had set
public to(contact?: MockContact | string): MockContact | null | this {
if (contact) {
return this
}
const to = MockContact.load('mockid') as MockContact
to.puppet = this.puppet
return to
}
public room(room: MockRoom): this
public room(): MockRoom | null
......@@ -112,12 +127,24 @@ export class MockMessage extends Message {
}
public async say(
textOrMessage: string | MockMessage,
replyTo?: MockContact | MockContact[],
textOrMessage: string | MockMessage,
replyTo?: MockContact | MockContact[],
): Promise<void> {
log.verbose('MockMessage', 'say(%s, %s)', textOrMessage, replyTo)
const m = new MockMessage()
await this.puppet.send(m)
const message = new MockMessage()
message.from(this.puppet.userSelf() as MockContact)
message.to(this.from())
const room = this.room()
if (room) {
message.room(room)
}
// TODO: implement the replyTo
await this.puppet.send(message)
}
public type(): MsgType {
......@@ -146,21 +173,6 @@ export class MockMessage extends Message {
return this
}
public to(contact: MockContact): this
public to(id: string): this
public to(): MockContact | null // if to is not set, then room must had set
public to(contact?: MockContact | string): MockContact | null | this {
if (contact) {
return this
}
const to = MockContact.load('mockid') as MockContact
to.puppet = this.puppet
return to
}
public async readyStream(): Promise<Readable> {
log.verbose('MockMessage', 'readyStream()')
throw new Error('to be mocked')
......@@ -178,7 +190,7 @@ export class MockMessage extends Message {
return 'text/plain'
}
public async forward(to: MockRoom|MockContact): Promise<void> {
public async forward(to: MockRoom | MockContact): Promise<void> {
/**
* 1. Text message
*/
......
......@@ -91,6 +91,7 @@ export class PuppetMock extends Puppet {
await this.state.ready('off')
return
}
this.state.off('pending')
// await some tasks...
this.state.off(true)
......@@ -139,12 +140,6 @@ export class PuppetMock extends Puppet {
return await this.userSelf().say(text)
}
public async login(user: MockContact): Promise<void> {
log.verbose('PuppetMock', 'login(%s)', user)
this.user = user
this.emit('login', user)
}
public async logout(): Promise<void> {
log.verbose('PuppetMock', 'logout()')
......
......@@ -59,7 +59,10 @@ function onDing(
this.emit('watchdog', { data })
}
async function onScan(this: PuppetPuppeteer, data: ScanData): Promise<void> {
async function onScan(
this: PuppetPuppeteer,
data: ScanData,
): Promise<void> {
log.verbose('PuppetPuppeteerEvent', 'onScan({code: %d, url: %s})', data.code, data.url)
if (this.state.off()) {
......@@ -93,7 +96,11 @@ function onLog(data: any): void {
log.silly('PuppetPuppeteerEvent', 'onLog(%s)', data)
}
async function onLogin(this: PuppetPuppeteer, note: string, ttl = 30): Promise<void> {
async function onLogin(
this: PuppetPuppeteer,
note: string,
ttl = 30,
): Promise<void> {
log.verbose('PuppetPuppeteerEvent', 'onLogin(%s, %d)', note, ttl)
const TTL_WAIT_MILLISECONDS = 1 * 1000
......
......@@ -27,11 +27,12 @@ import * as test from 'blue-tape'
// import * as sinon from 'sinon'
// const sinonTest = require('sinon-test')(sinon)
import { Firer } from './firer'
import { PuppetPuppeteer } from './puppet-puppeteer'
import { Firer } from './firer'
test('Firer smoke testing', async t => {
t.true(true, 'should be true')
})
const mockPuppetPuppeteer = {
userSelf: () => ({}),
} as any as PuppetPuppeteer
test('parseFriendConfirm()', async t => {
const contentList = [
......@@ -55,11 +56,11 @@ test('parseFriendConfirm()', async t => {
let result: boolean
contentList.forEach(([content]) => {
result = Firer.parseFriendConfirm(content)
result = Firer.parseFriendConfirm.call(mockPuppetPuppeteer, content)
t.true(result, 'should be truthy for confirm msg: ' + content)
})
result = Firer.parseFriendConfirm('fsdfsdfasdfasdfadsa')
result = Firer.parseFriendConfirm.call(mockPuppetPuppeteer, 'fsdfsdfasdfasdfadsa')
t.false(result, 'should be falsy for other msg')
})
......@@ -119,14 +120,14 @@ test('parseRoomJoin()', async t => {
let result
contentList.forEach(([content, inviter, inviteeList]) => {
result = Firer.parseRoomJoin(content)
result = Firer.parseRoomJoin.call(mockPuppetPuppeteer, content)
t.ok(result, 'should check room join message right for ' + content)
t.deepEqual(result[0], inviteeList, 'should get inviteeList right')
t.is(result[1], inviter, 'should get inviter right')
})
t.throws(() => {
Firer.parseRoomJoin('fsadfsadfsdfsdfs')
Firer.parseRoomJoin.call(mockPuppetPuppeteer, 'fsadfsadfsdfsdfs')
}, Error, 'should throws if message is not expected')
})
......@@ -154,19 +155,19 @@ test('parseRoomLeave()', async t => {
]
contentLeaverList.forEach(([content, leaver]) => {
const resultLeaver = Firer.parseRoomLeave(content)[0]
const resultLeaver = Firer.parseRoomLeave.call(mockPuppetPuppeteer, content)[0]
t.ok(resultLeaver, 'should get leaver for leave message: ' + content)
t.is(resultLeaver, leaver, 'should get leaver name right')
})
contentRemoverList.forEach(([content, remover]) => {
const resultRemover = Firer.parseRoomLeave(content)[1]
const resultRemover = Firer.parseRoomLeave.call(mockPuppetPuppeteer, content)[1]
t.ok(resultRemover, 'should get remover for leave message: ' + content)
t.is(resultRemover, remover, 'should get leaver name right')
})
t.throws(() => {
Firer.parseRoomLeave('fafdsfsdfafa')
Firer.parseRoomLeave.call(mockPuppetPuppeteer, 'fafdsfsdfafa')
}, Error, 'should throw if message is not expected')
})
......@@ -186,14 +187,14 @@ test('parseRoomTopic()', async t => {
let result
contentList.forEach(([content, changer, topic]) => {
result = Firer.parseRoomTopic(content)
result = Firer.parseRoomTopic.call(mockPuppetPuppeteer, content)
t.ok(result, 'should check topic right for content: ' + content)
t.is(topic , result[0], 'should get right topic')
t.is(changer, result[1], 'should get right changer')
})
t.throws(() => {
Firer.parseRoomTopic('fafdsfsdfafa')
Firer.parseRoomTopic.call(mockPuppetPuppeteer, 'fafdsfsdfafa')
}, Error, 'should throw if message is not expected')
})
......@@ -102,11 +102,14 @@ const regexConfig = {
],
}
async function checkFriendRequest(m: PuppeteerMessage) {
if (!m.rawObj) {
async function checkFriendRequest(
this: PuppetPuppeteer,
msg: PuppeteerMessage,
) {
if (!msg.rawObj) {
throw new Error('message empty')
}
const info = m.rawObj.RecommendInfo
const info = msg.rawObj.RecommendInfo
log.verbose('PuppetPuppeteerFirer', 'fireFriendRequest(%s)', info)
if (!info) {
......@@ -114,22 +117,25 @@ async function checkFriendRequest(m: PuppeteerMessage) {
}
const request = new PuppeteerFriendRequest()
request.puppet = m.puppet
request.puppet = msg.puppet
request.receive(info)
await request.contact.ready()
if (!request.contact.isReady()) {
await request.contact().ready()
if (!request.contact().isReady()) {
log.warn('PuppetPuppeteerFirer', 'fireFriendConfirm() contact still not ready after `ready()` call')
}
this.emit('friend', request.contact, request)
this.emit('friend', request.contact(), request)
}
/**
* try to find FriendRequest Confirmation Message
*/
function parseFriendConfirm(content: string): boolean {
function parseFriendConfirm(
this: PuppetPuppeteer,
content: string,
): boolean {
const reList = regexConfig.friendConfirm
let found = false
......@@ -141,11 +147,14 @@ function parseFriendConfirm(content: string): boolean {
}
}
async function checkFriendConfirm(m: PuppeteerMessage) {
async function checkFriendConfirm(
this: PuppetPuppeteer,
m: PuppeteerMessage,
) {
const content = m.text()
log.silly('PuppetPuppeteerFirer', 'fireFriendConfirm(%s)', content)
if (!parseFriendConfirm(content)) {
if (!parseFriendConfirm.call(this, content)) {
return
}
const request = new PuppeteerFriendRequest()
......@@ -171,7 +180,10 @@ async function checkFriendConfirm(m: PuppeteerMessage) {
* 管理员 invited 小桔建群助手 to the group chat
* 管理员 invited 庆次、小桔妹 to the group chat
*/
function parseRoomJoin(content: string): [string[], string] {
function parseRoomJoin(
this: PuppetPuppeteer,
content: string,
): [string[], string] {
log.verbose('PuppetPuppeteerFirer', 'checkRoomJoin(%s)', content)
const reListInvite = regexConfig.roomJoinInvite
......@@ -194,19 +206,22 @@ function parseRoomJoin(content: string): [string[], string] {
return [inviteeList, inviter] // put invitee at first place
}
async function checkRoomJoin(m: PuppeteerMessage): Promise<boolean> {
async function checkRoomJoin(
this: PuppetPuppeteer,
msg: PuppeteerMessage,
): Promise<boolean> {
const room = m.room()
const room = msg.room()
if (!room) {
log.warn('PuppetPuppeteerFirer', 'fireRoomJoin() `room` not found')
return false
}
const text = m.text()
const text = msg.text()
let inviteeList: string[], inviter: string
try {
[inviteeList, inviter] = parseRoomJoin(text)
[inviteeList, inviter] = parseRoomJoin.call(this, text)
} catch (e) {
log.silly('PuppetPuppeteerFirer', 'fireRoomJoin() "%s" is not a join message', text)
return false // not a room join message
......@@ -221,8 +236,7 @@ async function checkRoomJoin(m: PuppeteerMessage): Promise<boolean> {
try {
if (inviter === 'You' || inviter === '' || inviter === 'you') {
inviterContact = PuppeteerContact.load(this.userId) as PuppeteerContact
inviterContact.puppet = m.puppet
inviterContact = this.userSelf()
}
const max = 20
......@@ -321,7 +335,10 @@ async function checkRoomJoin(m: PuppeteerMessage): Promise<boolean> {
}
function parseRoomLeave(content: string): [string, string] {
function parseRoomLeave(
this: PuppetPuppeteer,
content: string,
): [string, string] {
const reListByBot = regexConfig.roomLeaveByBot
const reListByOther = regexConfig.roomLeaveByOther
let foundByBot: string[]|null = []
......@@ -331,7 +348,7 @@ function parseRoomLeave(content: string): [string, string] {
if ((!foundByBot || !foundByBot.length) && (!foundByOther || !foundByOther.length)) {
throw new Error('checkRoomLeave() no matched re for ' + content)
}
const [leaver, remover] = foundByBot ? [ foundByBot[1], this.userId ] : [ this.userId, foundByOther[1] ]
const [leaver, remover] = foundByBot ? [ foundByBot[1], this.userSelf().id ] : [ this.userSelf().id, foundByOther[1] ]
return [leaver, remover]
}
......@@ -346,7 +363,7 @@ async function checkRoomLeave(
let leaver: string, remover: string
try {
[leaver, remover] = parseRoomLeave(m.text())
[leaver, remover] = parseRoomLeave.call(this, m.text())
} catch (e) {
return false
}
......@@ -363,8 +380,7 @@ async function checkRoomLeave(
*/
let leaverContact: PuppeteerContact | null, removerContact: PuppeteerContact | null
if (leaver === this.userSelf().id) {
leaverContact = PuppeteerContact.load(this.userSelf().id)
leaverContact.puppet = m.puppet
leaverContact = this.userSelf()
// not sure which is better
// removerContact = room.member({contactAlias: remover}) || room.member({name: remover})
......@@ -406,7 +422,10 @@ async function checkRoomLeave(
return true
}
function parseRoomTopic(content: string): [string, string] {
function parseRoomTopic(
this: PuppetPuppeteer,
content: string,
): [string, string] {
const reList = regexConfig.roomTopic
let found: string[]|null = []
......@@ -418,10 +437,12 @@ function parseRoomTopic(content: string): [string, string] {
return [topic, changer]
}
async function checkRoomTopic(m: PuppeteerMessage): Promise<boolean> {
async function checkRoomTopic(
this: PuppetPuppeteer,
m: PuppeteerMessage): Promise<boolean> {
let topic, changer
try {
[topic, changer] = parseRoomTopic(m.text())
[topic, changer] = parseRoomTopic.call(this, m.text())
} catch (e) { // not found
return false
}
......@@ -436,7 +457,7 @@ async function checkRoomTopic(m: PuppeteerMessage): Promise<boolean> {
let changerContact: PuppeteerContact | null
if (/^You$/.test(changer) || /^你$/.test(changer)) {
changerContact = PuppeteerContact.load(this.userId) as PuppeteerContact
changerContact = this.userSelf()
changerContact.puppet = m.puppet
} else {
changerContact = room.member(changer)
......
......@@ -58,15 +58,17 @@ test('Puppet smoke testing', async t => {
test('login/logout events', sinonTest(async function (t: test.Test) {
sinon.stub(Contact, 'findAll')
const sandbox = sinon.sandbox.create()
sandbox.stub(Contact, 'findAll')
.onFirstCall().resolves([])
.onSecondCall().resolves([1])
.resolves([1, 2])
sinon.stub(Event, 'onScan') // block the scan event to prevent reset logined user
sandbox.stub(Event, 'onScan') // block the scan event to prevent reset logined user
sinon.stub(Bridge.prototype, 'getUserName').resolves('mockedUserName')
sinon.stub(PuppetPuppeteer.prototype, 'getContact') .resolves({
sandbox.stub(Bridge.prototype, 'getUserName').resolves('mockedUserName')
sandbox.stub(PuppetPuppeteer.prototype, 'getContact') .resolves({
NickName: 'mockedNickName',
UserName: 'mockedUserName',
})
......@@ -110,6 +112,7 @@ test('login/logout events', sinonTest(async function (t: test.Test) {
} catch (e) {
t.fail(e)
} finally {
sandbox.restore()
t.end()
}
}))
......@@ -24,18 +24,17 @@ import * as sinon from 'sinon'
import cloneClass from 'clone-class'
import Profile from '../profile'
import Wechaty from '../wechaty' // `Wechaty` need to be imported before `Puppet`
import PuppetPuppeteer from './puppet-puppeteer'
import PuppeteerContact from './puppeteer-contact'
import Profile from '../profile'
import Wechaty from '../wechaty'
test('Contact smoke testing', async t => {
// tslint:disable-next-line:variable-name
const MyContact = cloneClass(PuppeteerContact)
MyContact.puppet = new PuppetPuppeteer({
const puppet = new PuppetPuppeteer({
profile: new Profile(),
wechaty: new Wechaty(),
})
......@@ -45,19 +44,24 @@ test('Contact smoke testing', async t => {
const NickName = 'NickNameTest'
const RemarkName = 'AliasTest'
sinon.stub((MyContact.puppet as PuppetPuppeteer), 'getContact', function(id: string) {
const sandbox = sinon.sandbox.create()
sandbox.stub(puppet, 'getContact')
.callsFake(function(id: string) {
return new Promise<any>((resolve, reject) => {
if (id !== UserName) return resolve({})
setTimeout(() => {
return resolve({
UserName: UserName,
NickName: NickName,
UserName: UserName,
NickName: NickName,
RemarkName: RemarkName,
})
}, 200)
}, 10)
})
})
MyContact.puppet = puppet
const c = new MyContact(UserName)
t.is(c.id, UserName, 'id/UserName right')
......@@ -66,8 +70,7 @@ test('Contact smoke testing', async t => {
t.is(r.name(), NickName, 'NickName set')
t.is(r.alias(), RemarkName, 'should get the right alias from Contact')
const s = r.toString()
t.is(typeof s, 'string', 'toString()')
sandbox.restore()
// const contact1 = await Contact.find({name: 'NickNameTest'})
// t.is(contact1.id, UserName, 'should find contact by name')
......
......@@ -29,10 +29,11 @@ import Wechaty from '../wechaty'
import {
Puppet,
} from '../puppet/'
FriendRequestType,
} from '../puppet/'
import {
PuppetMock,
} from '../puppet-mock/'
} from '../puppet-mock/'
import PuppeteerContact from './puppeteer-contact'
import PuppeteerMessage from './puppeteer-message'
......@@ -55,9 +56,9 @@ test('PuppetPuppeteerFriendRequest.receive smoke testing', async t => {
fr.receive(rawObj.RecommendInfo)
t.true(typeof fr.payload === 'object', 'should has info object')
t.is(fr.hello, '我是群聊"Wechaty"的李卓桓.PreAngel', 'should has right request message')
t.true(fr.contact instanceof PuppeteerContact, 'should have a Contact instance')
t.is(fr.type as any, 'receive', 'should be receive type')
t.is(fr.hello(), '我是群聊"Wechaty"的李卓桓.PreAngel', 'should has right request message')
t.true(fr.contact() instanceof PuppeteerContact, 'should have a Contact instance')
t.is(fr.type(), FriendRequestType.RECEIVE, 'should be receive type')
})
test('PuppetPuppeteerFriendRequest.confirm smoke testing', async t => {
......@@ -89,6 +90,6 @@ test('PuppetPuppeteerFriendRequest.confirm smoke testing', async t => {
const contact = m.from()
fr.confirm(contact || new MyContact('xx'))
t.true(fr.contact instanceof PuppeteerContact, 'should have a Contact instance')
t.is(fr.type as any, 'confirm', 'should be confirm type')
t.true(fr.contact() instanceof PuppeteerContact, 'should have a Contact instance')
t.is(fr.type(), FriendRequestType.CONFIRM, 'should be confirm type')
})
......@@ -35,6 +35,7 @@ import {
} from '../config'
import {
FriendRequest,
FriendRequestType,
} from '../puppet/'
import {
......@@ -50,6 +51,9 @@ export class PuppeteerFriendRequest extends FriendRequest {
public payload: RecommendPayload
private ticket: string
private _contact: PuppeteerContact
private _hello: string
private _type: FriendRequestType
constructor() {
log.verbose('PuppeteerFriendRequest', 'constructor()')
......@@ -67,8 +71,8 @@ export class PuppeteerFriendRequest extends FriendRequest {
const contact = PuppeteerContact.load(payload.UserName)
contact.puppet = this.puppet
this.contact = contact
this.hello = payload.Content
this._contact = contact
this._hello = payload.Content
this.ticket = payload.Ticket
// ??? this.nick = info.NickName
......@@ -76,7 +80,7 @@ export class PuppeteerFriendRequest extends FriendRequest {
throw new Error('ticket not found')
}
this.type = 'receive'
this._type = FriendRequestType.RECEIVE
return
}
......@@ -87,8 +91,8 @@ export class PuppeteerFriendRequest extends FriendRequest {
if (!contact) {
throw new Error('contact not found')
}
this.contact = contact
this.type = 'confirm'
this._contact = contact
this._type = FriendRequestType.CONFIRM
}
/**
......@@ -107,11 +111,11 @@ export class PuppeteerFriendRequest extends FriendRequest {
if (!contact) {
throw new Error('contact not found')
}
this.contact = contact
this.type = 'send'
this._contact = contact
this._type = FriendRequestType.SEND
if (hello) {
this.hello = hello
this._hello = hello
}
await this.puppet.friendRequestSend(contact, hello)
......@@ -125,11 +129,11 @@ export class PuppeteerFriendRequest extends FriendRequest {
public async accept(): Promise<void> {
log.verbose('FriendRequest', 'accept() %s', this.contact)
if (this.type !== 'receive') {
if (this._type !== FriendRequestType.RECEIVE) {
throw new Error('request is not a `receive` type. it is a ' + this.type + ' type')
}
await this.puppet.friendRequestAccept(this.contact, this.ticket)
await this.puppet.friendRequestAccept(this.contact(), this.ticket)
const max = 20
const backoff = 300
......@@ -143,10 +147,10 @@ export class PuppeteerFriendRequest extends FriendRequest {
await retryPromise({ max: max, backoff: backoff }, async (attempt: number) => {
log.silly('PuppeteerFriendRequest', 'accept() retryPromise() attempt %d with timeout %d', attempt, timeout)
await this.contact.ready()
await this.contact().ready()
if ((this.contact as PuppeteerContact).isReady()) {
log.verbose('PuppeteerFriendRequest', 'accept() with contact %s ready()', this.contact.name())
if (this.contact().isReady()) {
log.verbose('PuppeteerFriendRequest', 'accept() with contact %s ready()', this.contact().name())
return
}
throw new Error('FriendRequest.accept() content.ready() not ready')
......@@ -157,6 +161,22 @@ export class PuppeteerFriendRequest extends FriendRequest {
}
public hello(): string {
return this._hello
}
public contact(): PuppeteerContact {
return this._contact
}
public async reject(): Promise<void> {
log.warn('PuppeteerFriendRequest', 'reject() not necessary, NOP.')
return
}
public type(): FriendRequestType {
return this._type
}
}
export default PuppeteerFriendRequest
......@@ -214,9 +214,12 @@ test('mentioned()', async t => {
// puppet1 = { getContact: mockContactGetter }
// config.puppetInstance(puppet1)
// }
MyContact.puppet = MyRoom.puppet = MyMessage.puppet = {
const puppet = MyRoom.puppet = MyMessage.puppet = {
getContact: mockContactGetter,
} as any
} as PuppetPuppeteer
MyContact.puppet = puppet
const msg11 = new MyMessage(rawObj11)
const room11 = msg11.room()
if (room11) {
......
......@@ -75,7 +75,7 @@ export class PuppeteerMessage extends Message {
* @private
*/
constructor(
fileOrObj?: string | MsgRawPayload,
fileOrPayload?: string | MsgRawPayload,
) {
super()
log.silly('PuppeteerMessage', 'constructor()')
......@@ -83,14 +83,14 @@ export class PuppeteerMessage extends Message {
this.obj = {} as MsgPayload
// this.rawObj = {} as MsgRawObj
if (!fileOrObj) {
if (!fileOrPayload) {
return
}
if (typeof fileOrObj === 'string') {
this.parsedPath = path.parse(fileOrObj)
} else if (typeof fileOrObj === 'object') {
this.rawObj = fileOrObj
if (typeof fileOrPayload === 'string') {
this.parsedPath = path.parse(fileOrPayload)
} else if (typeof fileOrPayload === 'object') {
this.rawObj = fileOrPayload
this.obj = this.parse(this.rawObj)
this.id = this.obj.id
} else {
......@@ -246,7 +246,7 @@ export class PuppeteerMessage extends Message {
}
if (this.obj.room) {
const r = PuppeteerRoom.load(this.obj.room) as PuppeteerRoom
const r = PuppeteerRoom.load(this.obj.room)
r.puppet = this.puppet
return r
}
......@@ -506,7 +506,7 @@ export class PuppeteerMessage extends Message {
)
if (contactList.length === 0) {
log.warn(`Message`, `message.mentioned() can not found member using room.member() from mentionList, metion string: ${JSON.stringify(mentionList)}`)
log.warn('PuppeteerMessage', `message.mentioned() can not found member using room.member() from mentionList, metion string: ${JSON.stringify(mentionList)}`)
}
return contactList
}
......
......@@ -101,7 +101,7 @@ export class PuppeteerRoom extends Room {
* @private
*/
public async ready(): Promise<Room> {
log.silly('PuppeteerRoom', 'ready(%s)')
log.silly('PuppeteerRoom', 'ready()')
if (!this.id) {
const e = new Error('ready() on a un-inited Room')
log.warn('PuppeteerRoom', e.message)
......@@ -614,7 +614,7 @@ export class PuppeteerRoom extends Room {
}
const filterMap = this.obj[filterMapName] as Map<string, string>
const idList = Object.keys(filterMap)
const idList = Array.from(filterMap.keys())
.filter(id => filterMap.get(id) === filterValue)
log.silly('PuppeteerRoom', 'memberAll() check %s from %s: %s', filterValue, filterKey, JSON.stringify(filterMap))
......
......@@ -22,6 +22,12 @@ import PuppetAccessory from '../puppet-accessory'
import Contact from './contact'
export enum FriendRequestType {
SEND,
RECEIVE,
CONFIRM,
}
/**
* Send, receive friend request, and friend confirmation events.
*
......@@ -33,12 +39,14 @@ import Contact from './contact'
*/
export abstract class FriendRequest extends PuppetAccessory {
public contact: Contact
public hello: string
public type: 'send' | 'receive' | 'confirm'
public abstract send(contact: Contact, hello: string): Promise<void>
public abstract accept(): Promise<void>
public abstract reject(): Promise<void>
public abstract contact() : Contact
public abstract hello() : string
public abstract type() : FriendRequestType
}
......
......@@ -5,18 +5,20 @@ export {
} from './contact'
export {
FriendRequest,
FriendRequestType,
} from './friend-request'
export {
Message,
} from './message'
export {
Room,
RoomMemberQueryFilter,
RoomQueryFilter,
} from './room'
export {
Puppet,
PuppetEventName,
PuppetOptions,
ScanData,
} from './puppet'
export {
Room,
RoomMemberQueryFilter,
RoomQueryFilter,
} from './room'
......@@ -78,11 +78,11 @@ export abstract class Message extends PuppetAccessory implements Sayable {
* @private
*/
constructor(
readonly fileOrObj?: string | Object,
readonly fileOrPayload?: string | Object,
) {
super()
log.silly('Message', 'constructor(%s) for class %s',
fileOrObj || '',
log.silly('Message', 'constructor(%s) for child class %s',
fileOrPayload || '',
this.constructor.name,
)
}
......@@ -197,7 +197,7 @@ export abstract class Message extends PuppetAccessory implements Sayable {
* if (/^ding$/i.test(m.text())) {
* await m.say('hello world')
* console.log('Bot REPLY: hello world')
* await m.say(new bot.Message.create(__dirname + '/wechaty.png'))
* await m.say(new bot.Message(__dirname + '/wechaty.png'))
* console.log('Bot REPLY: Image')
* }
* })
......
......@@ -158,7 +158,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public emit(event: 'room-topic', room: Room, topic: string, oldTopic: string, changer: Contact) : boolean
public emit(event: 'scan', url: string, code: number) : boolean
public emit(event: 'watchdog', food: WatchdogFood) : boolean
public emit(event: never, ...args: never[]) : never
public emit(event: never, ...args: never[]): never
public emit(
event: PuppetEventName,
......@@ -216,7 +216,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
* Login / Logout
*/
public abstract logonoff() : boolean
public abstract login(user: Contact): Promise<void>
// public abstract login(user: Contact): Promise<void>
public abstract logout() : Promise<void>
/**
......
......@@ -128,6 +128,7 @@ export abstract class Room extends PuppetAccessory implements Sayable {
* @param {RoomQueryFilter} query
* @returns {Promise<Room | null>} If can find the room, return Room, or return null
*/
public static async find<T extends typeof Room>(
this : T,
query : RoomQueryFilter,
......
......@@ -29,12 +29,12 @@
, "dist/"
]
, "include": [
"bin/*.ts"
, "scripts/**/*.ts"
"app/**/*.ts"
, "bin/*.ts"
, "bot/**/*.ts"
, "examples/**/*.ts"
, "scripts/**/*.ts"
, "src/**/*.ts"
, "tests/**/*.spec.ts"
, "bot/**/*.ts"
, "app/**/*.ts"
]
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册