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

WIP: PadchatRpc for a JsonRPC gateway

上级 719f4d5d
......@@ -94,13 +94,15 @@
},
"dependencies": {
"bl": "^2.0.0",
"brolog": "^1.6.2",
"brolog": "^1.6.3",
"clone-class": "^0.6.11",
"cuid": "^2.1.1",
"express": "^4.16.3",
"file-box": "^0.8.19",
"hot-import": "^0.2.1",
"jimp": "^0.2.28",
"json-rpc-peer": "^0.15.3",
"json-rpc-protocol": "^0.11.4",
"jsqr": "^1.0.4",
"lru-cache": "^4.1.3",
"memory-card": "0.2.0",
......
......@@ -19,18 +19,18 @@ import {
PadchatPayloadType,
PadchatContactMsgType,
PadchatContactRawPayload,
PadchatContactPayload,
PadchatMessagePayload,
PadchatRoomMember,
PadchatRoomMemberPayload,
PadchatRoomRawPayload,
PadchatRoomPayload,
} from './padchat-schemas'
import {
AutoDataType,
FunctionType,
PadchatRpcRequest,
InitType,
WXGenerateWxDatType,
WXGetQRCodeType,
......@@ -46,7 +46,7 @@ import {
WXCheckQRCodeStatus,
StandardType,
WXAddChatRoomMemberType,
} from './bridge.type'
} from './padchat-rpc.type'
import {
PadchatPureFunctionHelper as pfHelper,
......@@ -77,8 +77,8 @@ export class Bridge extends EventEmitter {
private loginSucceed = false
private cacheRoomRawPayload : { [id: string]: PadchatRoomRawPayload }
private cacheContactRawPayload : { [id: string]: PadchatContactRawPayload }
private cacheRoomRawPayload : { [id: string]: PadchatRoomPayload }
private cacheContactRawPayload : { [id: string]: PadchatContactPayload }
private readonly state: StateSwitch
......@@ -151,7 +151,7 @@ export class Bridge extends EventEmitter {
private async sendToWebSocket(name: string, args: string[]): Promise<any> {
const msgId = cuid()
const data: FunctionType = {
const data: PadchatRpcRequest = {
userId: this.options.token,
msgId: msgId,
apiName: name,
......@@ -422,9 +422,9 @@ export class Bridge extends EventEmitter {
/**
* Load all Contact and Room
* see issue https://github.com/lijiarui/test-ipad-puppet/issues/39
* @returns {Promise<(PadchatRoomRawPayload | PadchatContactRawPayload)[]>}
* @returns {Promise<(PadchatRoomPayload | PadchatContactPayload)[]>}
*/
private async WXSyncContact(): Promise<(PadchatRoomRawPayload | PadchatContactRawPayload)[]> {
private async WXSyncContact(): Promise<(PadchatRoomPayload | PadchatContactPayload)[]> {
const result = await this.sendToWebSocket('WXSyncContact', [])
if (!result) {
throw Error('WXSyncContact error! canot get result from websocket server')
......@@ -456,8 +456,8 @@ export class Bridge extends EventEmitter {
log.verbose('PuppetPadchatBridge', `syncContactsAndRooms()`)
let cont = true
// const syncContactMap = new Map<string, PadchatContactRawPayload>()
// const syncRoomMap = new Map<string, PadchatRoomRawPayload>()
// const syncContactMap = new Map<string, PadchatContactPayload>()
// const syncRoomMap = new Map<string, PadchatRoomPayload>()
// let contactIdList: string[] = []
// let roomIdList: string[] = []
......@@ -490,11 +490,11 @@ export class Bridge extends EventEmitter {
if (syncContact.msg_type === PadchatContactMsgType.Contact) {
console.log('syncContact:', syncContact.user_name, syncContact.nick_name)
if (pfHelper.isRoomId(syncContact.user_name)) { // /@chatroom$/.test(syncContact.user_name)) {
this.cacheRoomRawPayload[syncContact.user_name] = syncContact as PadchatRoomRawPayload
// syncRoomMap.set(syncContact.user_name, syncContact as PadchatRoomRawPayload)
this.cacheRoomRawPayload[syncContact.user_name] = syncContact as PadchatRoomPayload
// syncRoomMap.set(syncContact.user_name, syncContact as PadchatRoomPayload)
} else if (syncContact.user_name) {
this.cacheContactRawPayload[syncContact.user_name] = syncContact as PadchatContactRawPayload
// syncContactMap.set(syncContact.user_name, syncContact as PadchatContactRawPayload)
this.cacheContactRawPayload[syncContact.user_name] = syncContact as PadchatContactPayload
// syncContactMap.set(syncContact.user_name, syncContact as PadchatContactPayload)
} else {
throw new Error('no user_name')
}
......@@ -636,7 +636,7 @@ export class Bridge extends EventEmitter {
* Get contact by contact id
* @param {any} id user_name
*/
private async WXGetContact(id: string): Promise<PadchatContactRawPayload | PadchatRoomRawPayload> {
private async WXGetContact(id: string): Promise<PadchatContactPayload | PadchatRoomPayload> {
const result = await this.sendToWebSocket('WXGetContact', [id])
if (!result) {
......@@ -658,11 +658,11 @@ export class Bridge extends EventEmitter {
* Get contact by contact id
* @param {any} id user_name
*/
public async WXGetContactPayload(id: string): Promise<PadchatContactRawPayload> {
public async WXGetContactPayload(id: string): Promise<PadchatContactPayload> {
if (!pfHelper.isContactId(id)) { // /@chatroom$/.test(id)) {
throw Error(`should use WXGetRoomPayload because get a room id :${id}`)
}
const result = await this.WXGetContact(id) as PadchatContactRawPayload
const result = await this.WXGetContact(id) as PadchatContactPayload
return result
}
......@@ -670,11 +670,11 @@ export class Bridge extends EventEmitter {
* Get contact by contact id
* @param {any} id user_name
*/
public async WXGetRoomPayload(id: string): Promise<PadchatRoomRawPayload> {
public async WXGetRoomPayload(id: string): Promise<PadchatRoomPayload> {
if (!pfHelper.isRoomId(id)) { // (/@chatroom$/.test(id))) {
throw Error(`should use WXGetContactPayload because get a contact id :${id}`)
}
const result = await this.WXGetContact(id) as PadchatRoomRawPayload
const result = await this.WXGetContact(id) as PadchatRoomPayload
return result
}
......@@ -965,7 +965,7 @@ export class Bridge extends EventEmitter {
}
}
public async contactRawPayload(id: string): Promise<PadchatContactRawPayload> {
public async contactRawPayload(id: string): Promise<PadchatContactPayload> {
log.verbose('PuppetPadchatBridge', 'contactRawPayload(%s)', id)
const rawPayload = await Misc.retry(async (retry, attempt) => {
......@@ -989,7 +989,7 @@ export class Bridge extends EventEmitter {
return rawPayload
}
public async roomRawPayload(id: string): Promise<PadchatRoomRawPayload> {
public async roomRawPayload(id: string): Promise<PadchatRoomPayload> {
log.verbose('PuppetPadchatBridge', 'roomRawPayload(%s)', id)
const rawPayload = await Misc.retry(async (retry, attempt) => {
......
此差异已折叠。
export interface FunctionType {
export interface PadchatRpcRequest {
userId: string,
msgId: string,
apiName: string,
......
......@@ -87,7 +87,7 @@ export interface PadchatPayload {
* - WXGetContact
* @interface PadchatContactPayload
*/
export interface PadchatContactRawPayload {
export interface PadchatContactPayload {
/**
* Sometimes, WXSyncContact can only get the following result:
* {
......@@ -336,7 +336,7 @@ export interface PadchatRoomMember {
* - WXGetContact
* @interface PadchatRoomPayload
*/
export interface PadchatRoomRawPayload {
export interface PadchatRoomPayload {
/**
* Sometimes, WXSyncContact can only get the following result:
* {
......
......@@ -68,9 +68,9 @@ import {
import {
// PadchatPayload,
PadchatContactRawPayload,
PadchatContactPayload,
PadchatMessagePayload,
PadchatRoomRawPayload,
PadchatRoomPayload,
// PadchatMessageType,
// PadchatContinue,
......@@ -90,8 +90,7 @@ export class PuppetPadchat extends Puppet {
private readonly cachePadchatMessagePayload : LRU.Cache<string, PadchatMessagePayload>
// private readonly cachePadchatRoomPayload : LRU.Cache<string, PadchatRoomRawPayload>
public bridge: Bridge
// public botWs: WebSocket
public readonly bridge: Bridge
constructor(
public options: PuppetOptions,
......@@ -179,6 +178,12 @@ export class PuppetPadchat extends Puppet {
public async start(): Promise<void> {
log.verbose('PuppetPadchat', `start() with ${this.options.memory.name}`)
if (this.state.on()) {
log.warn('PuppetPadchat', 'start() already on(pending)?')
await this.state.ready('on')
return
}
/**
* state has two main state: ON / OFF
* ON (pending)
......@@ -190,7 +195,7 @@ export class PuppetPadchat extends Puppet {
await this.startWatchdog()
this.state.on(true)
// this.emit('start')
this.emit('start')
}
......@@ -198,9 +203,7 @@ export class PuppetPadchat extends Puppet {
log.verbose('PuppetPadchat', 'startBridge()')
if (this.state.off()) {
const e = new Error('startBridge() state is off')
log.warn('PuppetPadchat', e.message)
throw e
throw new Error('startBridge() state is off')
}
this.bridge.removeAllListeners()
......@@ -221,8 +224,8 @@ export class PuppetPadchat extends Puppet {
)
this.emit('message', messagePayload.msg_id)
})
this.bridge.on('scan', (qrCode: string, statusCode: number, data?: string) => {
this.emit('scan', qrCode, statusCode, data)
this.bridge.on('scan', (qrCode: string, status: number, data?: string) => {
this.emit('scan', qrCode, status, data)
})
await this.bridge.start()
......@@ -232,7 +235,7 @@ export class PuppetPadchat extends Puppet {
log.verbose('PuppetPadchat', 'quit()')
if (this.state.off()) {
log.warn('PuppetPadchat', 'quit() is called on a OFF puppet. await ready(off) and return.')
log.warn('PuppetPadchat', 'stop() is called on a OFF puppet. await ready(off) and return.')
await this.state.ready('off')
return
}
......@@ -247,8 +250,7 @@ export class PuppetPadchat extends Puppet {
// await some tasks...
this.state.off(true)
// this.emit('stop')
this.emit('stop')
}
public async logout(): Promise<void> {
......@@ -285,7 +287,6 @@ export class PuppetPadchat extends Puppet {
return
}
// public async contactFindAll(query: ContactQueryFilter): Promise<string[]> {
public async contactList(): Promise<string[]> {
log.verbose('PuppetPadchat', 'contactList()')
......@@ -307,14 +308,14 @@ export class PuppetPadchat extends Puppet {
return file
}
public async contactRawPayload(id: string): Promise<PadchatContactRawPayload> {
log.verbose('PuppetPadchat', 'contactRawPayload(%s)', id)
public async contactRawPayload(contactId: string): Promise<PadchatContactPayload> {
log.verbose('PuppetPadchat', 'contactRawPayload(%s)', contactId)
const rawPayload = await this.bridge.contactRawPayload(id)
const rawPayload = await this.bridge.contactRawPayload(contactId)
return rawPayload
}
public async contactRawPayloadParser(rawPayload: PadchatContactRawPayload): Promise<ContactPayload> {
public async contactRawPayloadParser(rawPayload: PadchatContactPayload): Promise<ContactPayload> {
log.verbose('PuppetPadchat', 'contactRawPayloadParser(rawPayload.user_name="%s")', rawPayload.user_name)
const payload: ContactPayload = pfHelper.contactRawPayloadParser(rawPayload)
......@@ -433,14 +434,14 @@ export class PuppetPadchat extends Puppet {
* Room
*
*/
public async roomRawPayload(id: string): Promise<PadchatRoomRawPayload> {
public async roomRawPayload(id: string): Promise<PadchatRoomPayload> {
log.verbose('PuppetPadchat', 'roomRawPayload(%s)', id)
const rawPayload = await this.bridge.roomRawPayload(id)
return rawPayload
}
public async roomRawPayloadParser(rawPayload: PadchatRoomRawPayload): Promise<RoomPayload> {
public async roomRawPayloadParser(rawPayload: PadchatRoomPayload): Promise<RoomPayload> {
log.verbose('PuppetPadchat', 'roomRawPayloadParser(rawPayload.user_name="%s")', rawPayload.user_name)
const roomRawMemberList = (await this.bridge.WXGetChatRoomMember(rawPayload.user_name)).member
......
......@@ -22,14 +22,14 @@ import {
} from '../puppet/'
import {
PadchatContactRawPayload,
PadchatContactPayload,
PadchatMessagePayload,
// PadchatContactMsgType,
// PadchatMessageStatus,
PadchatMessageType,
PadchatRoomRawPayload,
PadchatRoomPayload,
PadchatRoomMember,
} from './padchat-schemas'
......@@ -74,7 +74,7 @@ export class PadchatPureFunctionHelper {
}
public static contactRawPayloadParser(
rawPayload: PadchatContactRawPayload,
rawPayload: PadchatContactPayload,
): ContactPayload {
if (!rawPayload.user_name) {
throw Error('cannot get user_name(wxid)!')
......@@ -203,7 +203,7 @@ export class PadchatPureFunctionHelper {
}
public static roomRawPayloadParser(
rawPayload : PadchatRoomRawPayload,
rawPayload : PadchatRoomPayload,
roomRawMemberList : PadchatRoomMember[],
): RoomPayload {
const aliasDict = {} as { [id: string]: string | undefined }
......
......@@ -66,11 +66,11 @@ async function onScan(
): Promise<void> {
log.verbose('PuppetPuppeteerEvent', 'onScan({code: %d, url: %s})', payload.code, payload.url)
if (this.state.off()) {
log.verbose('PuppetPuppeteerEvent', 'onScan(%s) state.off()=%s, NOOP',
payload, this.state.off())
return
}
// if (this.state.off()) {
// log.verbose('PuppetPuppeteerEvent', 'onScan(%s) state.off()=%s, NOOP',
// payload, this.state.off())
// return
// }
this.scanPayload = payload
......@@ -115,11 +115,11 @@ async function onLogin(
return
}
if (this.state.off()) {
log.verbose('PuppetPuppeteerEvent', 'onLogin(%s, %d) state.off()=%s, NOOP',
note, ttl, this.state.off())
return
}
// if (this.state.off()) {
// log.verbose('PuppetPuppeteerEvent', 'onLogin(%s, %d) state.off()=%s, NOOP',
// note, ttl, this.state.off())
// return
// }
if (this.logonoff()) {
throw new Error('onLogin() user had already logined: ' + this.selfId())
......@@ -151,9 +151,9 @@ async function onLogin(
log.silly('PuppetPuppeteerEvent', `onLogin() user ${userId} logined`)
if (this.state.on() === true) {
await this.saveCookie()
}
// if (this.state.on() === true) {
await this.saveCookie()
// }
// fix issue #668
await this.waitStable()
......
......@@ -59,16 +59,16 @@ class PuppetTest extends PuppetPuppeteer {
}
}
test('Puppet smoke testing', async t => {
const puppet = new PuppetTest({ memory: new MemoryCard() })
const wechaty = new WechatyTest({ puppet })
wechaty.initPuppetAccessory(puppet)
t.ok(puppet.state.off(), 'should be OFF state after instanciate')
puppet.state.on('pending')
t.ok(puppet.state.on(), 'should be ON state after set')
t.ok(puppet.state.pending(), 'should be pending state after set')
})
// test('Puppet smoke testing', async t => {
// const puppet = new PuppetTest({ memory: new MemoryCard() })
// const wechaty = new WechatyTest({ puppet })
// wechaty.initPuppetAccessory(puppet)
// t.ok(puppet.state.off(), 'should be OFF state after instanciate')
// puppet.state.on('pending')
// t.ok(puppet.state.on(), 'should be ON state after set')
// t.ok(puppet.state.pending(), 'should be pending state after set')
// })
test('login/logout events', sinonTest(async function (t: test.Test) {
const sandbox = sinon.createSandbox()
......
......@@ -84,18 +84,20 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public readonly cacheMessagePayload : LRU.Cache<string, MessagePayload>
public readonly cacheRoomPayload : LRU.Cache<string, RoomPayload>
public readonly state : StateSwitch
protected readonly state : StateSwitch
protected readonly watchdog : Watchdog
protected readonly counter : number
protected id?: string
/**
* childPkg stores the `package.json` that the NPM module who extends the `Puppet`
*/
private readonly childPkg: undefined | normalize.Package
/**
* Login-ed User ID
*/
protected id?: string
/**
*
*
......@@ -129,30 +131,6 @@ export abstract class Puppet extends EventEmitter implements Sayable {
this.cacheMessagePayload = new LRU<string, MessagePayload>(lruOptions)
this.cacheRoomPayload = new LRU<string, RoomPayload>(lruOptions)
/**
* 1. Init Classes
*/
// if ( !this.options.wechaty.Contact
// || !this.options.wechaty.FriendRequest
// || !this.options.wechaty.Message
// || !this.options.wechaty.Room
// ) {
// throw new Error('wechaty classes are not inited')
// }
// this.Contact = this.options.wechaty.Contact
// this.FriendRequest = this.options.wechaty.FriendRequest
// this.Message = this.options.wechaty.Message
// this.Room = this.options.wechaty.Room
/**
* Make sure that Wechaty had attached to this puppet
*
* When we declare a wechaty without a puppet instance,
* the wechaty need to attach to puppet later.
*/
// this.options.wechaty.attach(this)
/**
* 2. Load the package.json for Puppet Plugin version range matching
*
......@@ -200,7 +178,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public emit(event: 'room-join', roomId: string, inviteeIdList: string[], inviterId: string) : boolean
public emit(event: 'room-leave', roomId: string, leaverIdList: string[], remover?: string) : boolean
public emit(event: 'room-topic', roomId: string, topic: string, oldTopic: string, changerId: string) : boolean
public emit(event: 'scan', qrCode: string, code: number, data?: string) : boolean
public emit(event: 'scan', qrCode: string, status: number, data?: string) : boolean
public emit(event: 'start') : boolean
public emit(event: 'stop') : boolean
// Internal Usage: watchdog
......@@ -228,9 +206,9 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public on(event: 'logout', listener: (contactId: string) => void) : this
public on(event: 'message', listener: (messageId: string) => void) : this
public on(event: 'room-join', listener: (roomId: string, inviteeIdList: string[], inviterId: string) => void) : this
public on(event: 'room-leave', listener: (roomId: string, leaverIdList : string[], removerId?: string) => void) : this
public on(event: 'room-leave', listener: (roomId: string, leaverIdList : string[], removerId?: string) => void) : this
public on(event: 'room-topic', listener: (roomId: string, topic: string, oldTopic: string, changerId: string) => void) : this
public on(event: 'scan', listener: (qrCode: string, code: number, data?: string) => void) : this
public on(event: 'scan', listener: (qrCode: string, status: number, data?: string) => void) : this
public on(event: 'start', listener: () => void) : this
public on(event: 'stop', listener: () => void) : this
// Internal Usage: watchdog
......@@ -264,8 +242,27 @@ export abstract class Puppet extends EventEmitter implements Sayable {
*
*/
/**
* Need to be called internaly when the puppet is logined.
* this method will emit a `login` event
*/
protected async login(userId: string): Promise<void> {
log.verbose('Puppet', 'login(%s)', userId)
if (this.id) {
throw new Error('must logout first before login again!')
}
this.id = userId
// console.log('this.id=', this.id)
this.emit('login', userId)
}
/**
* `this.id = undefined`
* Need to be called internaly/externaly when the puppet need to be logouted
* this method will emit a `logout` event,
*
* Note: must set `this.id = undefined` in this function.
*/
public abstract async logout(): Promise<void>
......@@ -287,18 +284,6 @@ export abstract class Puppet extends EventEmitter implements Sayable {
}
}
protected async login(userId: string): Promise<void> {
log.verbose('Puppet', 'login(%s)', userId)
if (this.id) {
throw new Error('must logout first before login again!')
}
this.id = userId
// console.log('this.id=', this.id)
this.emit('login', userId)
}
/**
*
* Misc
......@@ -370,7 +355,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public abstract async contactAvatar(contactId: string) : Promise<FileBox>
public abstract async contactList() : Promise<string[]>
public abstract async contactRawPayload(id: string) : Promise<any>
public abstract async contactRawPayload(contactId: string) : Promise<any>
public abstract async contactRawPayloadParser(rawPayload: any) : Promise<ContactPayload>
public async contactSearch(
......@@ -392,15 +377,15 @@ export abstract class Puppet extends EventEmitter implements Sayable {
return searchIdList
}
const searchContactPayloadList = await Promise.all(
const searchContactPayloadList: ContactPayload[] = await Promise.all(
searchIdList.map(
id => this.contactPayload(id),
),
)
const filterFuncion = this.contactQueryFilterFactory(query)
const filterFuncion: ContactPayloadFilterFunction = this.contactQueryFilterFactory(query)
const idList = searchContactPayloadList
const idList: string[] = searchContactPayloadList
.filter(filterFuncion)
.map(payload => payload.id)
......@@ -414,12 +399,6 @@ export abstract class Puppet extends EventEmitter implements Sayable {
JSON.stringify(query),
)
// Object.keys(query).forEach((key: keyof ContactQueryFilter) => {
// if (typeof query[key] === 'undefined') {
// delete query[key]
// }
// })
Object.keys(query).forEach(key => {
if (query[key as keyof ContactQueryFilter] === undefined) {
delete query[key as keyof ContactQueryFilter]
......@@ -430,13 +409,13 @@ export abstract class Puppet extends EventEmitter implements Sayable {
throw new Error('query only support one key. multi key support is not availble now.')
}
// TypeScript bug: have to set `undefined | string | RegExp` at here, or the later code type check will get error
const filterKey = Object.keys(query)[0] as keyof ContactQueryFilter
if (!/^name|alias$/.test(filterKey)) {
throw new Error('key not supported: ' + filterKey)
}
// TypeScript bug: have to set `undefined | string | RegExp` at here, or the later code type check will get error
const filterValue: undefined | string | RegExp = query[filterKey]
if (!filterValue) {
throw new Error('filterValue not found for filterKey: ' + filterKey)
......@@ -444,10 +423,10 @@ export abstract class Puppet extends EventEmitter implements Sayable {
let filterFunction
if (filterValue instanceof RegExp) {
filterFunction = (payload: ContactPayload) => !!payload[filterKey] && filterValue.test(payload[filterKey]!)
} else if (typeof filterValue === 'string') {
if (typeof filterValue === 'string') {
filterFunction = (payload: ContactPayload) => filterValue === payload[filterKey]
} else if (filterValue instanceof RegExp) {
filterFunction = (payload: ContactPayload) => !!payload[filterKey] && filterValue.test(payload[filterKey]!)
} else {
throw new Error('unsupport filterValue type: ' + typeof filterValue)
}
......@@ -456,21 +435,21 @@ export abstract class Puppet extends EventEmitter implements Sayable {
}
public async contactPayload(
id: string,
contactId: string,
noCache = false,
): Promise<ContactPayload> {
log.silly('Puppet', 'contactPayload(id=%s, noCache=%s) @ %s', id, noCache, this)
log.silly('Puppet', 'contactPayload(id=%s, noCache=%s) @ %s', contactId, noCache, this)
if (!id) {
if (!contactId) {
throw new Error('no id')
}
if (noCache) {
log.silly('Puppet', 'contactPayload() cache PURGE')
this.cacheContactPayload.del(id)
this.cacheContactPayload.del(contactId)
}
const hitPayload = this.cacheContactPayload.get(id)
const hitPayload = this.cacheContactPayload.get(contactId)
if (hitPayload) {
log.silly('Puppet', 'contactPayload() cache HIT')
......@@ -479,10 +458,10 @@ export abstract class Puppet extends EventEmitter implements Sayable {
log.silly('Puppet', 'contactPayload() cache MISS')
const rawPayload = await this.contactRawPayload(id)
const rawPayload = await this.contactRawPayload(contactId)
const payload = await this.contactRawPayloadParser(rawPayload)
this.cacheContactPayload.set(id, payload)
this.cacheContactPayload.set(contactId, payload)
log.silly('Puppet', 'contactPayload() cache SET')
return payload
......@@ -496,25 +475,25 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public abstract async friendRequestSend(contactId: string, hello?: string) : Promise<void>
public abstract async friendRequestAccept(contactId: string, ticket: string) : Promise<void>
public abstract async friendRequestRawPayload(id: string) : Promise<any>
public abstract async friendRequestRawPayloadParser(rawPayload: any) : Promise<FriendRequestPayload>
public abstract async friendRequestRawPayload(friendRequestId: string) : Promise<any>
public abstract async friendRequestRawPayloadParser(rawPayload: any) : Promise<FriendRequestPayload>
public async friendRequestPayload(
id: string,
friendRequestId: string,
noCache = false,
): Promise<FriendRequestPayload> {
log.verbose('Puppet', 'friendRequestPayload(id=%s, noCache=%s)', id, noCache)
log.verbose('Puppet', 'friendRequestPayload(id=%s, noCache=%s)', friendRequestId, noCache)
if (!id) {
if (!friendRequestId) {
throw new Error('no id')
}
if (noCache) {
log.silly('Puppet', 'friendRequestPayload() cache PURGE')
this.cacheFriendRequestPayload.del(id)
this.cacheFriendRequestPayload.del(friendRequestId)
}
const hitPayload = this.cacheFriendRequestPayload.get(id)
const hitPayload = this.cacheFriendRequestPayload.get(friendRequestId)
if (hitPayload) {
log.silly('Puppet', 'friendRequestPayload() cache HIT')
......@@ -523,10 +502,10 @@ export abstract class Puppet extends EventEmitter implements Sayable {
log.silly('Puppet', 'friendRequestPayload() cache MISS')
const rawPayload = await this.friendRequestRawPayload(id)
const rawPayload = await this.friendRequestRawPayload(friendRequestId)
const payload = await this.friendRequestRawPayloadParser(rawPayload)
this.cacheFriendRequestPayload.set(id, payload)
this.cacheFriendRequestPayload.set(friendRequestId, payload)
return payload
}
......@@ -537,29 +516,29 @@ export abstract class Puppet extends EventEmitter implements Sayable {
*
*/
public abstract async messageFile(messageId: string) : Promise<FileBox>
public abstract async messageForward(to: Receiver, messageId: string) : Promise<void>
public abstract async messageSendText(to: Receiver, text: string) : Promise<void>
public abstract async messageSendFile(to: Receiver, file: FileBox) : Promise<void>
public abstract async messageForward(receiver: Receiver, messageId: string) : Promise<void>
public abstract async messageSendText(receiver: Receiver, text: string) : Promise<void>
public abstract async messageSendFile(receiver: Receiver, file: FileBox) : Promise<void>
public abstract async messageRawPayload(id: string) : Promise<any>
public abstract async messageRawPayload(messageId: string) : Promise<any>
public abstract async messageRawPayloadParser(rawPayload: any) : Promise<MessagePayload>
public async messagePayload(
id: string,
messageId : string,
noCache = false,
): Promise<MessagePayload> {
log.verbose('Puppet', 'messagePayload(id=%s, noCache=%s)', id, noCache)
log.verbose('Puppet', 'messagePayload(id=%s, noCache=%s)', messageId, noCache)
if (!id) {
if (!messageId) {
throw new Error('no id')
}
if (noCache) {
log.silly('Puppet', 'messagePayload() cache PURGE')
this.cacheMessagePayload.del(id)
this.cacheMessagePayload.del(messageId)
}
const hitPayload = this.cacheMessagePayload.get(id)
const hitPayload = this.cacheMessagePayload.get(messageId)
if (hitPayload) {
log.silly('Puppet', 'messagePayload() cache HIT')
......@@ -569,10 +548,10 @@ export abstract class Puppet extends EventEmitter implements Sayable {
log.silly('Puppet', 'messagePayload() cache MISS')
const rawPayload = await this.messageRawPayload(id)
const rawPayload = await this.messageRawPayload(messageId)
const payload = await this.messageRawPayloadParser(rawPayload)
this.cacheMessagePayload.set(id, payload)
this.cacheMessagePayload.set(messageId, payload)
log.silly('Puppet', 'messagePayload() cache SET')
return payload
......@@ -591,7 +570,7 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public abstract async roomTopic(roomId: string, topic?: string) : Promise<string | void>
public abstract async roomList() : Promise<string[]>
public abstract async roomRawPayload(id: string) : Promise<any>
public abstract async roomRawPayload(roomId: string) : Promise<any>
public abstract async roomRawPayloadParser(rawPayload: any) : Promise<RoomPayload>
public async roomMemberSearch(
......@@ -648,9 +627,9 @@ export abstract class Puppet extends EventEmitter implements Sayable {
public async roomSearch(query?: RoomQueryFilter): Promise<string[]> {
log.verbose('Puppet', 'roomSearch(%s)', JSON.stringify(query))
const allRoomIdList = await this.roomList()
const allRoomIdList: string[] = await this.roomList()
log.silly('Puppet', 'roomSearch() allRoomIdList.length=%d', allRoomIdList.length)
console.log('allRoomIdList length=' + allRoomIdList.length)
if (!query || Object.keys(query).length <= 0) {
return allRoomIdList
}
......@@ -676,11 +655,9 @@ export abstract class Puppet extends EventEmitter implements Sayable {
protected roomQueryFilterFactory(
query: RoomQueryFilter,
): RoomPayloadFilterFunction {
log.verbose('Puppet', 'roomQueryFilterFactory({ %s })',
Object.keys(query)
.map(k => `${k}: ${query[k as keyof RoomQueryFilter]}`)
.join(', '),
)
log.verbose('Puppet', 'roomQueryFilterFactory(%s)',
JSON.stringify(query),
)
if (Object.keys(query).length !== 1) {
throw new Error('query only support one key. multi key support is not availble now.')
......@@ -745,8 +722,4 @@ export abstract class Puppet extends EventEmitter implements Sayable {
}
// export class WechatError extends Error {
// public code: WechatErrorCode
// }
export default Puppet
{
"compilerOptions": {
"target": "es6"
, "module": "commonjs"
, "outDir": "dist"
, "strict": true
, "traceResolution": false
, "noLib": false
, "module" : "commonjs"
, "outDir" : "dist"
, "traceResolution" : false
, "noLib" : false
, "declaration" : true
, "sourceMap" : true
, "skipLibCheck" : true
, "experimentalDecorators": true
, "emitDecoratorMetadata": true
, "declaration": true
, "sourceMap": true
, "noEmitOnError": true
, "emitDecoratorMetadata" : true
, "experimentalDecorators" : true
, "noUnusedLocals": true
, "noImplicitReturns": true
, "noFallthroughCasesInSwitch": true
, "strictNullChecks": true
, "noImplicitAny": true
, "noUnusedParameters": true
, "noImplicitThis": true
, "skipLibCheck": true
, "lib": [
"esnext"
]
, "strict" : true
, "noEmitOnError" : true
, "noUnusedLocals" : true
, "noImplicitReturns" : true
, "noFallthroughCasesInSwitch" : true
, "strictNullChecks" : true
, "noImplicitAny" : true
, "noUnusedParameters" : true
, "noImplicitThis" : true
}
, "exclude": [
"node_modules/"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册