diff --git a/src/puppet-padchat/bridge.ts b/src/puppet-padchat/bridge.ts index 42041e0c37c90b7d7dabfbbd94579b662d93d62b..c9025e9be1e0752b773aa48a18910127f33eeabe 100644 --- a/src/puppet-padchat/bridge.ts +++ b/src/puppet-padchat/bridge.ts @@ -48,6 +48,10 @@ import { WXAddChatRoomMemberType, } from './bridge.type' +import { + PadchatPureFunctionHelper as pfHelper, +} from './pure-function-helper' + import { log } from '../config' const AUTO_DATA_SLOT = 'autoData' @@ -194,7 +198,7 @@ export class Bridge extends EventEmitter { ws.on('message', (data: string) => { const payload: PadchatPayload = JSON.parse(data) - this.onServerPayload(payload) + this.onServerMessage(payload) }) await new Promise((resolve, reject) => { @@ -218,7 +222,7 @@ export class Bridge extends EventEmitter { this.serverWebSocket = undefined } - private onServerPayload(payload: PadchatPayload) { + private onServerMessage(payload: PadchatPayload) { console.log('server payload:', payload) log.verbose('PuppetPadchatBridge', 'onServerPayload(%s)', @@ -485,7 +489,7 @@ export class Bridge extends EventEmitter { if (syncContact.continue === PadchatContinue.Go) { if (syncContact.msg_type === PadchatContactMsgType.Contact) { console.log('syncContact:', syncContact.user_name, syncContact.nick_name) - if (/@chatroom$/.test(syncContact.user_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) } else if (syncContact.user_name) { @@ -655,7 +659,7 @@ export class Bridge extends EventEmitter { * @param {any} id user_name */ public async WXGetContactPayload(id: string): Promise { - if (/@chatroom$/.test(id)) { + 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 @@ -667,7 +671,7 @@ export class Bridge extends EventEmitter { * @param {any} id user_name */ public async WXGetRoomPayload(id: string): Promise { - if (!(/@chatroom$/.test(id))) { + 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 diff --git a/src/puppet-padchat/misc.spec.ts b/src/puppet-padchat/misc.spec.ts deleted file mode 100755 index 3f85c4bc331f5a490964db65bce0b10db4327712..0000000000000000000000000000000000000000 --- a/src/puppet-padchat/misc.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env ts-node - -// tslint:disable:no-shadowed-variable -import * as test from 'blue-tape' - -import { - isRoomId, - isContactId, - isContactOfficialId, -} from './misc' - -test('isRoomId()', async t => { - const ROOM_ID = 'xxx@chatroom' - const NOT_ROOM_ID = 'xxxxxxx' - - t.ok(isRoomId(ROOM_ID), 'should return true for ROOM_ID') - t.notOk(isRoomId(NOT_ROOM_ID), 'should return false for ROOM_ID') -}) - -test('isContactId()', async t => { - const CONTACT_ID = 'sxxfdsa' - const NOT_CONTACT_ID = 'fdsafasd@chatroom' - - t.ok(isContactId(CONTACT_ID), 'should return true for CONTACT_ID') - t.notOk(isContactId(NOT_CONTACT_ID), 'should return false for CONTACT_ID') -}) - -test('isOfficialContactId()', async t => { - const OFFICIAL_CONTACT_ID = 'gh_sxxfdsa' - const NOT_OFFICIAL_CONTACT_ID = 'fdsafasd@chatroom' - - t.ok(isContactOfficialId(OFFICIAL_CONTACT_ID), 'should return true for OFFICIAL_CONTACT_ID') - t.notOk(isContactOfficialId(NOT_OFFICIAL_CONTACT_ID), 'should return false for NOT_OFFICIAL_CONTACT_ID') -}) diff --git a/src/puppet-padchat/misc.ts b/src/puppet-padchat/misc.ts deleted file mode 100644 index bd4118ba522c20b565d601cadd130a68efe8462e..0000000000000000000000000000000000000000 --- a/src/puppet-padchat/misc.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function isRoomId(id: string) { - return /@chatroom$/.test(id) -} - -export function isContactId(id: string) { - return !isRoomId(id) -} - -export function isContactOfficialId(id: string) { - return /^gh_/i.test(id) -} diff --git a/src/puppet-padchat/puppet-padchat.ts b/src/puppet-padchat/puppet-padchat.ts index 92dd84a0afa44362c89df582aa1cefb26a2d2846..a3908809815e72427b013da86f500ee9f1adf12f 100644 --- a/src/puppet-padchat/puppet-padchat.ts +++ b/src/puppet-padchat/puppet-padchat.ts @@ -33,7 +33,7 @@ import { // ContactQueryFilter, // ContactGender, - ContactType, + // ContactType, ContactPayload, RoomPayload, @@ -47,11 +47,8 @@ import { } from '../puppet/' import { - isContactOfficialId, - isRoomId, -} from './misc' - -// import Misc from '../misc' + PadchatPureFunctionHelper as pfHelper, +} from './pure-function-helper' import { log, @@ -75,7 +72,7 @@ import { PadchatMessagePayload, PadchatRoomRawPayload, - PadchatMessageType, + // PadchatMessageType, // PadchatContinue, // PadchatMsgType, // PadchatStatus, @@ -88,10 +85,10 @@ export type ScanFoodType = 'scan' | 'login' | 'logout' export class PuppetPadchat extends Puppet { - public readonly cachePadchatContactPayload : LRU.Cache - // public readonly cachePadchatFriendRequestRawPayload : LRU.Cache - public readonly cachePadchatMessagePayload : LRU.Cache - public readonly cachePadchatRoomPayload : LRU.Cache + // private readonly cachePadchatContactPayload : LRU.Cache + // private readonly cachePadchatFriendRequestRawPayload : LRU.Cache + private readonly cachePadchatMessagePayload : LRU.Cache + // private readonly cachePadchatRoomPayload : LRU.Cache public bridge: Bridge // public botWs: WebSocket @@ -110,10 +107,10 @@ export class PuppetPadchat extends Puppet { maxAge: 1000 * 60 * 60, } - this.cachePadchatContactPayload = new LRU(lruOptions) + // this.cachePadchatContactPayload = new LRU(lruOptions) // this.cacheFriendRequestPayload = new LRU(lruOptions) this.cachePadchatMessagePayload = new LRU(lruOptions) - this.cachePadchatRoomPayload = new LRU(lruOptions) + // this.cachePadchatRoomPayload = new LRU(lruOptions) this.bridge = new Bridge({ memory : this.options.memory, @@ -292,73 +289,11 @@ export class PuppetPadchat extends Puppet { public async contactList(): Promise { log.verbose('PuppetPadchat', 'contactList()') - // const contactRawPayloadMap = (await this.bridge.checkSyncContactOrRoom()).contactMap - const contactIdList = this.bridge.getContactIdList() - // for (const contactRawPayload in contactRawPayloadMap) { - - // } - - // contactRawPayloadMap.forEach((value , id) => { - // contactIdList.push(id) - // this.Contact.load( - // id, - // await this.contactRawPayloadParser(value), - // ) - // }) - - // // const payloadList = await Promise.all( - // // contactIdList.map( - // // id => this.contactPayload(id), - // // ), - // // ) - // const contactList = contactIdList.filter(id => { - // await this.contactPayload(id) - // return true - // }) return contactIdList } - // protected contactQueryFilterToFunction( - // query: ContactQueryFilter, - // ): (payload: ContactPayload) => boolean { - // log.verbose('PuppetPadchat', 'contactQueryFilterToFunctionString({ %s })', - // Object.keys(query) - // .map(k => `${k}: ${query[k as keyof ContactQueryFilter]}`) - // .join(', '), - // ) - - // if (Object.keys(query).length !== 1) { - // throw new Error('query only support one key. multi key support is not availble now.') - // } - - // const filterKey = Object.keys(query)[0] as keyof ContactQueryFilter - - // let filterValue: string | RegExp | undefined = query[filterKey] - // if (!filterValue) { - // throw new Error('filterValue not found') - // } - - // /** - // * must be string because we need inject variable value - // * into code as variable namespecialContactList - // */ - // let filterFunction: (payload: ContactPayload) => boolean - - // if (filterValue instanceof RegExp) { - // const regex = filterValue - // filterFunction = (payload: ContactPayload) => regex.test(payload[filterKey] || '') - // } else if (typeof filterValue === 'string') { - // filterValue = filterValue.replace(/'/g, '\\\'') - // filterFunction = (payload: ContactPayload) => payload[filterKey] === filterValue - // } else { - // throw new Error('unsupport name type') - // } - - // return filterFunction - // } - public async contactAvatar(contactId: string): Promise { log.verbose('PuppetPadchat', 'contactAvatar(%s)', contactId) @@ -382,32 +317,7 @@ export class PuppetPadchat extends Puppet { public async contactRawPayloadParser(rawPayload: PadchatContactRawPayload): Promise { log.verbose('PuppetPadchat', 'contactRawPayloadParser(rawPayload.user_name="%s")', rawPayload.user_name) - if (!rawPayload.user_name) { - throw Error('cannot get user_name(wxid)!') - } - - if (isRoomId(rawPayload.user_name)) { - throw Error('Room Object instead of Contact!') - } - - let contactType = ContactType.Unknown - if (isContactOfficialId(rawPayload.user_name)) { - contactType = ContactType.Official - } else { - contactType = ContactType.Personal - } - - const payload: ContactPayload = { - id : rawPayload.user_name, - gender : rawPayload.sex, - type : contactType, - alias : rawPayload.remark, - avatar : rawPayload.big_head, - city : rawPayload.city, - name : rawPayload.nick_name, - province : rawPayload.provincia, - signature : (rawPayload.signature).replace('+', ' '), // Stay+Foolish - } + const payload: ContactPayload = pfHelper.contactRawPayloadParser(rawPayload) return payload } @@ -452,117 +362,12 @@ export class PuppetPadchat extends Puppet { } return rawPayload - - // log.verbose('PuppetPadchat', 'messageRawPayload(%s)', id) - // const rawPayload: PadchatMessageRawPayload = { - // content: '', - // data: '', - // continue: 1, - // description: '', - // from_user: '', - // msg_id: '', - // msg_source: '', - // msg_type: 5, - // status: 1, - // sub_type: PadchatMessageType.TEXT, - // timestamp: 11111111, - // to_user: '', - // uin: 111111, - - // // from : 'from_id', - // // text : 'padchat message text', - // // to : 'to_id', - // } - // return rawPayload } public async messageRawPayloadParser(rawPayload: PadchatMessagePayload): Promise { log.warn('PuppetPadChat', 'messageRawPayloadParser(rawPayload.msg_id=%s)', rawPayload.msg_id) - let type: MessageType - - switch (rawPayload.sub_type) { - case PadchatMessageType.Text: - type = MessageType.Text - break - case PadchatMessageType.Image: - type = MessageType.Image - break - case PadchatMessageType.Voice: - type = MessageType.Audio - break - case PadchatMessageType.Emoticon: - type = MessageType.Emoticon - break - case PadchatMessageType.App: - type = MessageType.Attachment - break - case PadchatMessageType.Video: - type = MessageType.Video - break - default: - log.warn('PuppetPadChat', 'messageRawPayloadParser() unknown type %s[%s], treat as Text', - PadchatMessageType[rawPayload.sub_type], - rawPayload.sub_type, - ) - type = MessageType.Text - } - - const payloadBase = { - id : rawPayload.msg_id, - timestamp : Date.now(), - fromId : rawPayload.from_user, - text : rawPayload.content, - // toId : rawPayload.to_user, - type : type, - } - - let roomId: undefined | string = undefined - let toId: undefined | string = undefined - - // Msg from room - if (isRoomId(rawPayload.from_user)) { - // update fromId to actual sender instead of the room - payloadBase.fromId = rawPayload.content.split(':\n')[0] - // update the text to actual text of the message - payloadBase.text = rawPayload.content.split(':\n')[1] - - roomId = rawPayload.from_user - - if (!roomId || !payloadBase.fromId) { - throw Error('empty roomId or empty contactId!') - } - } - - // Msg to room - if (isRoomId(rawPayload.to_user)) { - roomId = rawPayload.to_user - - // TODO: if the message @someone, the toId should set to the mentioned contact id(?) - toId = undefined - } else { - toId = rawPayload.to_user - } - - let payload: MessagePayload - - // Two branch is the same code. - // Only for making TypeScript happy - if (toId) { - payload = { - ...payloadBase, - toId, - roomId, - } - } else if (roomId) { - payload = { - ...payloadBase, - toId, - roomId, - } - } else { - throw new Error('neither toId nor roomId') - } + const payload: MessagePayload = pfHelper.messageRawPayloadParser(rawPayload) log.verbose('PuppetPadchat', 'messagePayload(%s)', JSON.stringify(payload)) return payload @@ -638,31 +443,9 @@ export class PuppetPadchat extends Puppet { public async roomRawPayloadParser(rawPayload: PadchatRoomRawPayload): Promise { log.verbose('PuppetPadchat', 'roomRawPayloadParser(rawPayload.user_name="%s")', rawPayload.user_name) - // const memberList = (rawPayload.member || []) - // .map(id => this.Contact.load(id)) - - // await Promise.all(memberList.map(c => c.ready())) - const roomRawMemberList = (await this.bridge.WXGetChatRoomMember(rawPayload.user_name)).member - const aliasDict = {} as { [id: string]: string | undefined } - - if (Array.isArray(roomRawMemberList)) { - roomRawMemberList.forEach( - rawMember => { - aliasDict[rawMember.user_name] = rawMember.chatroom_nick_name - }, - ) - } - - const memberIdList = roomRawMemberList.map(m => m.user_name) - - const payload: RoomPayload = { - id : rawPayload.user_name, - topic : rawPayload.nick_name, - memberIdList, - aliasDict, - } + const payload: RoomPayload = pfHelper.roomRawPayloadParser(rawPayload, roomRawMemberList) return payload } @@ -754,9 +537,9 @@ export class PuppetPadchat extends Puppet { let strangerV1 let strangerV2 - if (/^v1_/i.test(rawPayload.stranger)) { + if (pfHelper.isStrangerV1(rawPayload.stranger)) { // /^v1_/i.test(rawPayload.stranger)) { strangerV1 = rawPayload.stranger - } else if (/^v2_/i.test(rawPayload.stranger)) { + } else if (pfHelper.isStrangerV2(rawPayload.stranger)) { // /^v2_/i.test(rawPayload.stranger)) { strangerV2 = rawPayload.stranger } else { throw new Error('stranger neither v1 nor v2!') @@ -795,48 +578,14 @@ export class PuppetPadchat extends Puppet { public async friendRequestRawPayloadParser(rawPayload: any) : Promise { log.verbose('PuppetPadchat', 'friendRequestRawPayloadParser(%s)', rawPayload) - // TODO - - return rawPayload - // switch (rawPayload.MsgType) { - // case WebMessageType.VERIFYMSG: - // if (!rawPayload.RecommendInfo) { - // throw new Error('no RecommendInfo') - // } - // const recommendInfo: WebRecomendInfo = rawPayload.RecommendInfo - - // if (!recommendInfo) { - // throw new Error('no recommendInfo') - // } - - // const payloadReceive: FriendRequestPayloadReceive = { - // id : rawPayload.MsgId, - // contactId : recommendInfo.UserName, - // hello : recommendInfo.Content, - // ticket : recommendInfo.Ticket, - // type : FriendRequestType.Receive, - // } - // return payloadReceive - - // case WebMessageType.SYS: - // const payloadConfirm: FriendRequestPayloadConfirm = { - // id : rawPayload.MsgId, - // contactId : rawPayload.FromUserName, - // type : FriendRequestType.Confirm, - // } - // return payloadConfirm - - // default: - // throw new Error('not supported friend request message raw payload') - // } + const payload: FriendRequestPayload = pfHelper.friendRequestRawPayloadParser(rawPayload) + return payload } public async friendRequestRawPayload(id: string): Promise { // log.verbose('PuppetPadchat', 'friendRequestRawPayload(%s)', id) - // TODO - - console.log(id) + throw new Error('todo: ' + id) // const rawPayload = this.cacheMessageRawPayload.get(id) // if (!rawPayload) { // throw new Error('no rawPayload') diff --git a/src/puppet-padchat/pure-function-helper.spec.ts b/src/puppet-padchat/pure-function-helper.spec.ts new file mode 100755 index 0000000000000000000000000000000000000000..2c6cb3e725a69c34dc968f0b2c49b9289730dbd5 --- /dev/null +++ b/src/puppet-padchat/pure-function-helper.spec.ts @@ -0,0 +1,32 @@ +#!/usr/bin/env ts-node + +// tslint:disable:no-shadowed-variable +import * as test from 'blue-tape' + +import { + PadchatPureFunctionHelper as pfHelper, +} from './pure-function-helper' + +test('isRoomId()', async t => { + const ROOM_ID = 'xxx@chatroom' + const NOT_ROOM_ID = 'xxxxxxx' + + t.ok(pfHelper.isRoomId(ROOM_ID), 'should return true for ROOM_ID') + t.notOk(pfHelper.isRoomId(NOT_ROOM_ID), 'should return false for ROOM_ID') +}) + +test('isContactId()', async t => { + const CONTACT_ID = 'sxxfdsa' + const NOT_CONTACT_ID = 'fdsafasd@chatroom' + + t.ok(pfHelper.isContactId(CONTACT_ID), 'should return true for CONTACT_ID') + t.notOk(pfHelper.isContactId(NOT_CONTACT_ID), 'should return false for CONTACT_ID') +}) + +test('isOfficialContactId()', async t => { + const OFFICIAL_CONTACT_ID = 'gh_sxxfdsa' + const NOT_OFFICIAL_CONTACT_ID = 'fdsafasd@chatroom' + + t.ok(pfHelper.isContactOfficialId(OFFICIAL_CONTACT_ID), 'should return true for OFFICIAL_CONTACT_ID') + t.notOk(pfHelper.isContactOfficialId(NOT_OFFICIAL_CONTACT_ID), 'should return false for NOT_OFFICIAL_CONTACT_ID') +}) diff --git a/src/puppet-padchat/pure-function-helper.ts b/src/puppet-padchat/pure-function-helper.ts new file mode 100644 index 0000000000000000000000000000000000000000..2e931bf6f522d5558c25c12651bcc59824dd37e2 --- /dev/null +++ b/src/puppet-padchat/pure-function-helper.ts @@ -0,0 +1,272 @@ +/** + * + * Pure Function Helpers + * + * See: What's Pure Function Programming + * [Functional Programming Concepts: Pure Functions](https://hackernoon.com/functional-programming-concepts-pure-functions-cafa2983f757) + * [What Are Pure Functions And Why Use Them?](https://medium.com/@jamesjefferyuk/javascript-what-are-pure-functions-4d4d5392d49c) + * [Master the JavaScript Interview: What is a Pure Function?](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976) + * + */ + +import { + ContactPayload, + ContactType, + + MessagePayload, + MessageType, + + RoomPayload, + + FriendRequestPayload, +} from '../puppet/' + +import { + PadchatContactRawPayload, + PadchatMessagePayload, + // PadchatContactMsgType, + + // PadchatMessageStatus, + PadchatMessageType, + + PadchatRoomRawPayload, + PadchatRoomMember, +} from './padchat-schemas' + +export class PadchatPureFunctionHelper { + private constructor() { + throw new Error('should not be instanciated. use static methods only.') + } + + public static isRoomId(id?: string): boolean { + if (!id) { + throw new Error('no id') + } + return /@chatroom$/.test(id) + } + + public static isContactId(id?: string): boolean { + if (!id) { + throw new Error('no id') + } + return !this.isRoomId(id) + } + + public static isContactOfficialId(id?: string): boolean { + if (!id) { + throw new Error('no id') + } + return /^gh_/i.test(id) + } + + public static isStrangerV1(strangerId?: string): boolean { + if (!strangerId) { + throw new Error('no id') + } + return /^v1_/i.test(strangerId) + } + + public static isStrangerV2(strangerId?: string): boolean { + if (!strangerId) { + throw new Error('no id') + } + return /^v2_/i.test(strangerId) + } + + public static contactRawPayloadParser( + rawPayload: PadchatContactRawPayload, + ): ContactPayload { + if (!rawPayload.user_name) { + throw Error('cannot get user_name(wxid)!') + } + + if (this.isRoomId(rawPayload.user_name)) { + throw Error('Room Object instead of Contact!') + } + + let contactType = ContactType.Unknown + if (this.isContactOfficialId(rawPayload.user_name)) { + contactType = ContactType.Official + } else { + contactType = ContactType.Personal + } + + const payload: ContactPayload = { + id : rawPayload.user_name, + gender : rawPayload.sex, + type : contactType, + alias : rawPayload.remark, + avatar : rawPayload.big_head, + city : rawPayload.city, + name : rawPayload.nick_name, + province : rawPayload.provincia, + signature : (rawPayload.signature).replace('+', ' '), // Stay+Foolish + } + + return payload + } + + public static messageRawPayloadParser( + rawPayload: PadchatMessagePayload, + ): MessagePayload { + + let type: MessageType + + switch (rawPayload.sub_type) { + + case PadchatMessageType.Sys: // fall down + case PadchatMessageType.Text: + type = MessageType.Text + break + + case PadchatMessageType.Image: + type = MessageType.Image + break + + case PadchatMessageType.Voice: + type = MessageType.Audio + break + + case PadchatMessageType.Emoticon: + type = MessageType.Emoticon + break + + case PadchatMessageType.App: + type = MessageType.Attachment + break + + case PadchatMessageType.Video: + type = MessageType.Video + break + + default: + throw new Error('unsupported type') + } + + const payloadBase = { + id : rawPayload.msg_id, + timestamp : Date.now(), + fromId : rawPayload.from_user, + text : rawPayload.content, + // toId : rawPayload.to_user, + type : type, + } + + let roomId: undefined | string = undefined + let toId: undefined | string = undefined + + // Msg from room + if (this.isRoomId(rawPayload.from_user)) { + // update fromId to actual sender instead of the room + payloadBase.fromId = rawPayload.content.split(':\n')[0] + // update the text to actual text of the message + payloadBase.text = rawPayload.content.split(':\n')[1] + + roomId = rawPayload.from_user + + if (!roomId || !payloadBase.fromId) { + throw Error('empty roomId or empty contactId!') + } + } + + // Msg to room + if (this.isRoomId(rawPayload.to_user)) { + roomId = rawPayload.to_user + + // TODO: if the message @someone, the toId should set to the mentioned contact id(?) + toId = undefined + } else { + toId = rawPayload.to_user + } + + let payload: MessagePayload + + // Two branch is the same code. + // Only for making TypeScript happy + if (toId) { + payload = { + ...payloadBase, + toId, + roomId, + } + } else if (roomId) { + payload = { + ...payloadBase, + toId, + roomId, + } + } else { + throw new Error('neither toId nor roomId') + } + + return payload + } + + public static roomRawPayloadParser( + rawPayload : PadchatRoomRawPayload, + roomRawMemberList : PadchatRoomMember[], + ): RoomPayload { + const aliasDict = {} as { [id: string]: string | undefined } + + if (Array.isArray(roomRawMemberList)) { + roomRawMemberList.forEach( + rawMember => { + aliasDict[rawMember.user_name] = rawMember.chatroom_nick_name + }, + ) + } + + const memberIdList = roomRawMemberList.map(m => m.user_name) + + const payload: RoomPayload = { + id : rawPayload.user_name, + topic : rawPayload.nick_name, + memberIdList, + aliasDict, + } + + return payload + } + + public static friendRequestRawPayloadParser( + rawPayload: any, + ) : FriendRequestPayload { + // to do: + throw new Error('todo' + rawPayload) + + // switch (rawPayload.MsgType) { + // case WebMessageType.VERIFYMSG: + // if (!rawPayload.RecommendInfo) { + // throw new Error('no RecommendInfo') + // } + // const recommendInfo: WebRecomendInfo = rawPayload.RecommendInfo + + // if (!recommendInfo) { + // throw new Error('no recommendInfo') + // } + + // const payloadReceive: FriendRequestPayloadReceive = { + // id : rawPayload.MsgId, + // contactId : recommendInfo.UserName, + // hello : recommendInfo.Content, + // ticket : recommendInfo.Ticket, + // type : FriendRequestType.Receive, + // } + // return payloadReceive + + // case WebMessageType.SYS: + // const payloadConfirm: FriendRequestPayloadConfirm = { + // id : rawPayload.MsgId, + // contactId : rawPayload.FromUserName, + // type : FriendRequestType.Confirm, + // } + // return payloadConfirm + + // default: + // throw new Error('not supported friend request message raw payload') + // } + + } +} + +export default PadchatPureFunctionHelper diff --git a/src/puppet/README.md b/src/puppet/README.md new file mode 100644 index 0000000000000000000000000000000000000000..38b70d256813d24fe4ec530486ef698c7bd0ebe7 --- /dev/null +++ b/src/puppet/README.md @@ -0,0 +1,11 @@ +# WECHATY PUPPET + +Base Class of Wechaty Puppet Framework. + +## Resources + +### Pure Function + +* [Functional Programming Concepts: Pure Functions](https://hackernoon.com/functional-programming-concepts-pure-functions-cafa2983f757) +* [What Are Pure Functions And Why Use Them?](https://medium.com/@jamesjefferyuk/javascript-what-are-pure-functions-4d4d5392d49c) +* [Master the JavaScript Interview: What is a Pure Function?](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976)