Skip to content
This repository has been archived by the owner on Jun 1, 2020. It is now read-only.

Add implementation for room-invite event #107

Merged
merged 7 commits into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@
"tslint": "^5.10.0",
"tslint-config-standard": "^7.1.0",
"typescript": "^2.9.2",
"wechaty": "^0.17.133",
"wechaty-puppet": "^0.8.5"
"wechaty": "^0.19.107"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to notify you that this is a BREAKING change and you should bump your MINOR version number when you changing the dependence to wechaty 0.17 to 0.19

},
"git": {
"scripts": {
Expand All @@ -79,20 +78,24 @@
},
"peerDependencies": {
"file-box": "^0.8.22",
"wechaty-puppet": "^0.8.2"
"wechaty-puppet": "^0.9.19"
},
"homepage": "https://github.com/lijiarui/wechaty-puppet-padchat#readme",
"dependencies": {
"array-flatten": "^2.1.1",
"axios": "^0.18.0",
"express": "^4.16.3",
"flash-store": "^0.5.9",
"fs-extra": "^6.0.1",
"jimp": "^0.2.28",
"json-rpc-peer": "^0.15.3",
"jsqr": "^1.1.0",
"lru-cache": "^4.1.3",
"promise-retry": "^1.1.1",
"qr-image": "^3.2.0",
"read-pkg-up": "^4.0.0",
"request": "^2.87.0",
"request-promise": "^4.2.2",
"rx-queue": "^0.4.26",
"rxjs": "^6.2.1",
"ws": "^5.2.1",
Expand Down
50 changes: 50 additions & 0 deletions src/padchat-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
PadchatContactPayload,
PadchatContinue,

PadchatRoomInvitationPayload,
PadchatRoomInviteEvent,
PadchatRoomMemberPayload,
PadchatRoomPayload,
} from './padchat-schemas'
Expand Down Expand Up @@ -70,6 +72,7 @@ export class PadchatManager extends PadchatRpc {
[contactId: string]: PadchatRoomMemberPayload,
}>
private cacheRoomRawPayload? : FlashStoreSync<string, PadchatRoomPayload>
private cacheRoomInvitationRawPayload? : FlashStoreSync<string, PadchatRoomInvitationPayload>

private readonly state : StateSwitch
private readonly delayQueueExecutor : DelayQueueExector
Expand Down Expand Up @@ -106,6 +109,7 @@ export class PadchatManager extends PadchatRpc {
if ( this.cacheContactRawPayload
|| this.cacheRoomMemberRawPayload
|| this.cacheRoomRawPayload
|| this.cacheRoomInvitationRawPayload
) {
throw new Error('cache exists')
}
Expand All @@ -130,11 +134,13 @@ export class PadchatManager extends PadchatRpc {
this.cacheContactRawPayload = new FlashStoreSync(path.join(baseDir, 'contact-raw-payload'))
this.cacheRoomMemberRawPayload = new FlashStoreSync(path.join(baseDir, 'room-member-raw-payload'))
this.cacheRoomRawPayload = new FlashStoreSync(path.join(baseDir, 'room-raw-payload'))
this.cacheRoomInvitationRawPayload = new FlashStoreSync(path.join(baseDir, 'room-invitation-raw-payload'))

await Promise.all([
this.cacheContactRawPayload.ready(),
this.cacheRoomMemberRawPayload.ready(),
this.cacheRoomRawPayload.ready(),
this.cacheRoomInvitationRawPayload.ready(),
])

const roomMemberTotalNum = [...this.cacheRoomMemberRawPayload.values()].reduce(
Expand All @@ -158,18 +164,21 @@ export class PadchatManager extends PadchatRpc {
if ( this.cacheContactRawPayload
&& this.cacheRoomMemberRawPayload
&& this.cacheRoomRawPayload
&& this.cacheRoomInvitationRawPayload
) {
log.silly('PuppetPadchatManager', 'releaseCache() closing caches ...')

await Promise.all([
this.cacheContactRawPayload.close(),
this.cacheRoomMemberRawPayload.close(),
this.cacheRoomRawPayload.close(),
this.cacheRoomInvitationRawPayload.close(),
])

this.cacheContactRawPayload = undefined
this.cacheRoomMemberRawPayload = undefined
this.cacheRoomRawPayload = undefined
this.cacheRoomInvitationRawPayload = undefined

log.silly('PuppetPadchatManager', 'releaseCache() cache closed.')
} else {
Expand Down Expand Up @@ -987,6 +996,47 @@ export class PadchatManager extends PadchatRpc {
return rawPayload
}

public async roomInvitationRawPayload (roomInvitationId: string): Promise<PadchatRoomInvitationPayload> {
log.verbose('PuppetPadchatManager', 'roomInvitationRawPayload(%s)', roomInvitationId)
if (!this.cacheRoomInvitationRawPayload) {
throw new Error('no cache')
}

const payload = await this.cacheRoomInvitationRawPayload.get(roomInvitationId)

if (payload) {
return payload
} else {
throw new Error(`can not get invitation with invitation id: ${roomInvitationId}`)
}
}

public async roomInvitationRawPayloadDirty (roomInvitationId: string): Promise<void> {
log.verbose('PuppetPadchatManager', 'roomInvitationRawPayloadDirty(%s)', roomInvitationId)
if (!this.cacheRoomInvitationRawPayload) {
throw new Error('no cache')
}

await this.cacheRoomInvitationRawPayload.delete(roomInvitationId)
}

public async saveRoomInvitationRawPayload (roomInvitation: PadchatRoomInviteEvent): Promise<void> {
log.verbose('PuppetPadchatManager', 'saveRoomInvitationRawPayload(%s)', JSON.stringify(roomInvitation))
const { msgId, roomName, url, fromUser, timestamp } = roomInvitation

if (!this.cacheRoomInvitationRawPayload) {
throw new Error('no cache')
}

this.cacheRoomInvitationRawPayload.set(msgId, {
fromUser,
id: msgId,
roomName,
timestamp,
url,
})
}

public ding (data?: string): void {
log.verbose('PuppetPadchatManager', 'ding(%s)', data || '')
// TODO: healthy check
Expand Down
3 changes: 2 additions & 1 deletion src/padchat-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
PadchatPayload,
PadchatPayloadType,

PadchatRequestTokenPayload,
PadchatRoomMemberListPayload,
PadchatRoomMemberPayload,
PadchatRoomPayload,
Expand Down Expand Up @@ -1096,7 +1097,7 @@ export class PadchatRpc extends EventEmitter {
// 公众号中获取url访问token, 给下面的函数使用[WXRequestUrl]
// user 公众号用户名
// url 访问的链接
public async WXGetRequestToken (id: string, url: string): Promise<any> {
public async WXGetRequestToken (id: string, url: string): Promise<PadchatRequestTokenPayload> {
const result = await this.rpcCall('WXGetRequestToken', id, url)
log.silly('PadchatRpc', 'WXGetRequestToken , stranger,result: %s', JSON.stringify(result))
if (!result || result.status !== 0) {
Expand Down
52 changes: 51 additions & 1 deletion src/padchat-schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
import {
ContactGender,
FriendshipType,
} from 'wechaty-puppet'

// 1 when use WXSyncContact, 0 when use WXGetContact
Expand Down Expand Up @@ -438,9 +439,58 @@ export interface PadchatRoomMemberListPayload {
// sourcenickname: '' },
// brandlist: [ [Object] ] } }

export interface PadchatRoomInvitationPayload {
id: string,
fromUser: string,
roomName: string,
timestamp: number,
url: string,
}

export interface PadchatFriendshipPayload {
fromusername : string, // 'lizhuohuan'
encryptusername : string // v1_xxx@stranger'
encryptusername : string, // v1_xxx@stranger'
content : string, // 'hello'
ticket : string, // 'v2_1a0d2cf325e64b6f74bed09e944529e7cc7a7580cb323475050664566dd0302d89b8e2ed95b596b459cf762d94a0ce606da39babbae0dc26b18a62e079bfc120@stranger',
}

export interface PadchatRequestTokenPayload {
full_url : string,
info : string,
message : string,
share_url : string,
status : number,
}

export interface PadchatRoomInviteEvent {
fromUser: string,
msgId: string,
roomName: string,
timestamp: number,
url: string,
}

export interface FriendshipPayloadBase {
id : string,

contactId : string,
hello? : string,
}

export type FriendshipPayloadConfirm = FriendshipPayloadBase & {
type : FriendshipType.Confirm,
}

export type FriendshipPayloadReceive = FriendshipPayloadBase & {
stranger? : string,
ticket : string,
type : FriendshipType.Receive,
}

export type FriendshipPayloadVerify = FriendshipPayloadBase & {
type : FriendshipType.Verify,
}

export type FriendshipPayload = FriendshipPayloadConfirm
| FriendshipPayloadReceive
| FriendshipPayloadVerify
79 changes: 75 additions & 4 deletions src/puppet-padchat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
*/

import path from 'path'
import path from 'path'

import flatten from 'array-flatten'
import LRU from 'lru-cache'
Expand All @@ -31,7 +31,6 @@ import {
ContactType,

FriendshipPayload,
FriendshipPayloadReceive,

MessagePayload,
MessageType,
Expand All @@ -40,6 +39,7 @@ import {

PuppetOptions,
Receiver,
RoomInvitationPayload,
RoomMemberPayload,
RoomPayload,
} from 'wechaty-puppet'
Expand All @@ -60,10 +60,10 @@ import {
isStrangerV2,

messageRawPayloadParser,
roomInviteEventMessageParser,
roomJoinEventMessageParser,
roomLeaveEventMessageParser,
roomRawPayloadParser,

roomTopicEventMessageParser,
} from './pure-function-helpers'

Expand All @@ -82,9 +82,11 @@ import {
} from './padchat-manager'

import {
FriendshipPayloadReceive,
PadchatContactPayload,
PadchatMessagePayload,
PadchatMessageType,
PadchatRoomInvitationPayload,
PadchatRoomMemberPayload,
PadchatRoomPayload,
} from './padchat-schemas'
Expand Down Expand Up @@ -303,19 +305,38 @@ export class PuppetPadchat extends Puppet {
break

case PadchatMessageType.App:
await Promise.all([
this.onPadchatMessageRoomInvitation(rawPayload),
])
break
case PadchatMessageType.Emoticon:
case PadchatMessageType.Image:
case PadchatMessageType.MicroVideo:
case PadchatMessageType.Video:
case PadchatMessageType.Voice:
// TODO: the above types are filel type
// TODO: the above types are field type

default:
this.emit('message', rawPayload.msg_id)
break
}
}

protected async onPadchatMessageRoomInvitation (rawPayload: PadchatMessagePayload): Promise<void> {
log.verbose('PuppetPadchat', 'onPadchatMessageRoomInvitation(%s)', rawPayload)
const roomInviteEvent = roomInviteEventMessageParser(rawPayload)

if (!this.padchatManager) {
throw new Error('no padchat manager')
}

if (roomInviteEvent) {
await this.padchatManager.saveRoomInvitationRawPayload(roomInviteEvent)

this.emit('room-invite', roomInviteEvent.msgId)
}
}

/**
* Look for room join event
*/
Expand Down Expand Up @@ -1242,6 +1263,56 @@ export class PuppetPadchat extends Puppet {
}
}

public async roomInvitationRawPayload (roomInvitationId: string): Promise<PadchatRoomInvitationPayload> {
if (!this.padchatManager) {
throw new Error('no padchat manager')
}

return this.padchatManager.roomInvitationRawPayload(roomInvitationId)
}

public async roomInvitationRawPayloadParser (rawPayload: PadchatRoomInvitationPayload): Promise<RoomInvitationPayload> {
return {
id: rawPayload.id,
inviterId: rawPayload.fromUser,
roomMemberCount: 0,
roomMemberIdList: [],
roomTopic: rawPayload.roomName,
timestamp: rawPayload.timestamp
}
}

public async roomInvitationAccept (roomInvitationId: string): Promise<void> {

if (!this.padchatManager) {
throw new Error('no padcaht manager')
}

let res: string = ''
try {
const payload = await this.padchatManager.roomInvitationRawPayload(roomInvitationId)
const shareUrl = payload.url

const response = await this.padchatManager.WXGetRequestToken(this.selfId(), shareUrl)

res = await require('request-promise')({
method: 'POST',
simple: false,
uri: response.full_url,
})
} catch (e) {
throw new Error('UNKNOWN: Unexpected error happened when trying to accept invitation\n' + e)
}
console.log(res)
if (res.indexOf('你无法查看被转发过的邀请') !== -1 || res.indexOf('Unable to view forwarded invitations')) {
throw new Error('FORWARDED: Accept invitation failed, this is a forwarded invitation, can not be accepted')
} else if (res.indexOf('你未开通微信支') !== -1 || res.indexOf('You haven\'t enabled WeChat Pay')) {
throw new Error('WXPAY: The user need to enable wechaty pay(微信支付) to join the room, this is requested by Wechat.')
} else if (res.indexOf('该邀请已过期') !== -1 || res.indexOf('Invitation expired')) {
throw new Error('EXPIRED: The invitation is expired, please request the user to send again')
}
}

/**
*
* Friendship
Expand Down
8 changes: 4 additions & 4 deletions src/pure-function-helpers/friendship-raw-payload-parser.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { toJson } from 'xml2json'

import {
FriendshipType
} from 'wechaty-puppet'

import {
FriendshipPayload,
FriendshipPayloadConfirm,
FriendshipPayloadReceive,
FriendshipPayloadVerify,
FriendshipType,
} from 'wechaty-puppet'

import {
PadchatFriendshipPayload,
PadchatMessagePayload,
} from '../padchat-schemas'
Expand Down