提交 cc1fad6d 编写于 作者: ruiruibupt's avatar ruiruibupt

Merge branch 'room-test' of github.com:lijiarui/wechaty into room-test

{
"name": "wechaty",
"version": "0.15.145",
"version": "0.15.147",
"description": "Wechat for Bot(Personal Account)",
"main": "dist/src/index.js",
"typings": "dist/src/index.d.ts",
......
......@@ -324,7 +324,7 @@ export class PadchatRpc extends EventEmitter {
private async rpcCall(
apiName : string,
...params : (string | WXSearchContactTypeStatus)[]
...params : string[]
): Promise<any> {
log.silly('PadchatRpc', 'rpcCall(%s, %s)', apiName, JSON.stringify(params).substr(0, 500))
return await this.jsonRpc.request(apiName, params)
......@@ -851,7 +851,13 @@ export class PadchatRpc extends EventEmitter {
}
public async WXAddUser(strangerV1: string, strangerV2: string, type: WXSearchContactTypeStatus, verify: string): Promise<any> {
const result = await this.rpcCall('WXAddUser', strangerV1, strangerV2, type, verify)
const result = await this.rpcCall(
'WXAddUser',
strangerV1,
strangerV2,
String(type),
verify,
)
log.silly('PadchatRpc', 'WXAddUser result: %s', JSON.stringify(result))
return result
}
......
......@@ -50,9 +50,14 @@ import {
import {
contactRawPayloadParser,
fileBoxToQrcode,
// friendRequestEventMessageParser,
friendshipRawPayloadParser,
isStrangerV1,
isStrangerV2,
messageRawPayloadParser,
roomRawPayloadParser,
......@@ -269,6 +274,29 @@ export class PuppetPadchat extends Puppet {
this.emit('friendship', rawPayload.msg_id)
break
case PadchatMessageType.Recalled:
/**
* When someone joined the room invited by Bot,
* the bot will receive a `recall-able` message for room event
*
* { content: '12740017638@chatroom:\n<sysmsg type="delchatroommember">\n\t<delchatroommember>\n\t\t<plain>
* <![CDATA[You invited 卓桓、Zhuohuan, 太阁_传话助手, 桔小秘 to the group chat. ]]></plain>...,
* continue: 1,
* description: '',
* from_user: '12740017638@chatroom',
* msg_id: '232220931339852872',
* msg_source: '',
* msg_type: 5,
* status: 1,
* sub_type: 10002,
* timestamp: 1528831349,
* to_user: 'wxid_zj2cahpwzgie12',
* uin: 324216852 }
*/
await Promise.all([
this.onPadchatMessageRoomEvent(rawPayload),
])
break
case PadchatMessageType.Sys:
await Promise.all([
this.onPadchatMessageFriendshipEvent(rawPayload),
......@@ -960,17 +988,17 @@ export class PuppetPadchat extends Puppet {
/**
* If the contact is not stranger, than ussing WXSearchContact can get user_name
*/
if (rawSearchPayload.user_name !== '' && !pfHelper.isStrangerV1(rawSearchPayload.user_name) && !pfHelper.isStrangerV2(rawSearchPayload.user_name)) {
if (rawSearchPayload.user_name !== '' && !isStrangerV1(rawSearchPayload.user_name) && !isStrangerV2(rawSearchPayload.user_name)) {
log.warn('PuppetPadchat', 'friendRequestSend %s has been friend with bot, no need to send friend request!', contactId)
return
}
let strangerV1
let strangerV2
if (pfHelper.isStrangerV1(rawSearchPayload.stranger)) {
if (isStrangerV1(rawSearchPayload.stranger)) {
strangerV1 = rawSearchPayload.stranger
strangerV2 = rawSearchPayload.user_name
} else if (pfHelper.isStrangerV2(rawSearchPayload.stranger)) {
} else if (isStrangerV2(rawSearchPayload.stranger)) {
strangerV2 = rawSearchPayload.stranger
strangerV1 = rawSearchPayload.user_name
} else {
......
// import {
// YOU,
// } from '../../puppet/'
import { toJson } from 'xml2json'
import { PadchatMessagePayload } from '../padchat-schemas'
export function friendshipConfirmEventMessageParser(rawPayload: PadchatMessagePayload): null | string {
const FRIENDSHIP_CONFIRM_REGEX_LIST = [
/^You have added (.+) as your WeChat contact. Start chatting!$/,
/^你已添加了(.+),现在可以开始聊天了。$/,
/^(.+) just added you to his\/her contacts list. Send a message to him\/her now!$/,
/^(.+)刚刚把你添加到通讯录,现在可以开始聊天了。$/,
]
import {
isContactId,
isPayload,
} from './is-type'
let matches: null | RegExpMatchArray = null as any
const text = rawPayload.content
/**
*
* 1. Friendship Confirm Event
*
*/
const FRIENDSHIP_CONFIRM_REGEX_LIST = [
/^You have added (.+) as your WeChat contact. Start chatting!$/,
/^你已添加了(.+),现在可以开始聊天了。$/,
/I've accepted your friend request. Now let's chat!$/,
/^(.+) just added you to his\/her contacts list. Send a message to him\/her now!$/,
/^(.+)刚刚把你添加到通讯录,现在可以开始聊天了。$/,
]
export function friendshipConfirmEventMessageParser(
rawPayload: PadchatMessagePayload,
): null | string {
if (!isPayload(rawPayload)) {
return null
}
let matches = null as null | string[]
const text = rawPayload.content
FRIENDSHIP_CONFIRM_REGEX_LIST.some(
regexp => {
......@@ -26,17 +42,82 @@ export function friendshipConfirmEventMessageParser(rawPayload: PadchatMessagePa
return null
}
return matches[0]
return rawPayload.from_user
}
/**
*
* 2. Friendship Receive Event
*
*/
export function friendshipReceiveEventMessageParser(
rawPayload: PadchatMessagePayload,
): null | string {
if (!isPayload(rawPayload)) {
return null
}
interface XmlSchema {
msg: {
fromusername: string,
encryptusername: string,
content: string,
ticket: string,
}
}
try {
const jsonPayload: XmlSchema = JSON.parse(
toJson(
rawPayload.content,
),
)
const contactId = jsonPayload.msg.fromusername
if (isContactId(contactId)) {
return contactId
}
} catch (e) {
// not receive event
}
return null
}
/**
*
* 3. Friendship Verify Event
*
*/
const FRIENDSHIP_VERIFY_REGEX_LIST = [
/^(.+) has enabled Friend Confirmation/,
/^(.+)开启了朋友验证,你还不是他(她)朋友。请先发送朋友验证请求,对方验证通过后,才能聊天。/,
]
export function friendshipVerifyEventMessageParser(
rawPayload: PadchatMessagePayload,
): null | string {
return null
if (!isPayload(rawPayload)) {
return null
}
let matches = null as null | string[]
const text = rawPayload.content
FRIENDSHIP_VERIFY_REGEX_LIST.some(
regexp => {
matches = text.match(regexp)
return !!matches
},
)
if (!matches) {
return null
}
return rawPayload.from_user
}
......@@ -14,22 +14,20 @@ import {
PadchatMessagePayload,
} from '../padchat-schemas'
import { padchatDecode } from './padchat-decode'
import { friendshipRawPayloadParser } from './friendship-raw-payload-parser'
test('friendshipRawPayloadParser()', async t => {
const DATA = '%5B%7B%22content%22%3A%22%3Cmsg+fromusername%3D%5C%22lizhuohuan%5C%22+encryptusername%3D%5C%22v1_cf269def9b946093f9d131a5e733ba169351013c95e46a860cddecaf485c4b10%40stranger%5C%22+fromnickname%3D%5C%22%E6%9D%8E%E5%8D%93%E6%A1%93%5C%22+content%3D%5C%22xixixi%5C%22+fullpy%3D%5C%22lizhuohuan%5C%22+shortpy%3D%5C%22LZH%5C%22+imagestatus%3D%5C%223%5C%22+scene%3D%5C%226%5C%22+country%3D%5C%22CN%5C%22+province%3D%5C%22Beijing%5C%22+city%3D%5C%22Haidian%5C%22+sign%3D%5C%22PreAngel%E6%8A%95%E8%B5%84%E4%BA%BA%E3%80%82%E6%B0%B4%E6%9C%A8%E6%B8%85%E5%8D%8EBBS%E7%AB%99%E9%95%BF%E3%80%82%E6%8A%95%E8%B5%84%E4%BA%BA%E4%B8%AD%E6%9C%80%E4%BC%9A%E9%A3%9E%E7%9A%84AI%E7%A8%8B%E5%BA%8F%E5%91%98%E3%80%82%5C%22+percard%3D%5C%221%5C%22+sex%3D%5C%221%5C%22+alias%3D%5C%22%5C%22+weibo%3D%5C%22%5C%22+weibonickname%3D%5C%22%5C%22+albumflag%3D%5C%220%5C%22+albumstyle%3D%5C%220%5C%22+albumbgimgid%3D%5C%22913943270785024_913943270785024%5C%22+snsflag%3D%5C%22177%5C%22+snsbgimgid%3D%5C%22http%3A%2F%2Fshmmsns.qpic.cn%2Fmmsns%2FNoFChqEQomEyhyNjzExH3v78BHSVmIzHBIdOECg9jgcTpRNwThgXJicCsGicI6Kib4xLETc2PuKwhM%2F0%5C%22+snsbgobjectid%3D%5C%2212683064081608282338%5C%22+mhash%3D%5C%22d98b28f4cb1708bb584f3e66078e0a0d%5C%22+mfullhash%3D%5C%22d98b28f4cb1708bb584f3e66078e0a0d%5C%22+bigheadimgurl%3D%5C%22http%3A%2F%2Fwx.qlogo.cn%2Fmmhead%2Fver_1%2FciaaFRTCqfHIKLY0wBjv3h0LSPkCEEcJ0fo6kQkMxQLBiahJWFk7rS9G4VLU5n9OfAnXWlMaIV01oeTITYS0OHlg%2F0%5C%22+smallheadimgurl%3D%5C%22http%3A%2F%2Fwx.qlogo.cn%2Fmmhead%2Fver_1%2FciaaFRTCqfHIKLY0wBjv3h0LSPkCEEcJ0fo6kQkMxQLBiahJWFk7rS9G4VLU5n9OfAnXWlMaIV01oeTITYS0OHlg%2F96%5C%22+ticket%3D%5C%22v2_1a0d2cf325e64b6f74bed09e944529e7cc7a7580cb323475050664566dd0302d89b8e2ed95b596b459cf762d94a0ce606da39babbae0dc26b18a62e079bfc120%40stranger%5C%22+opcode%3D%5C%222%5C%22+googlecontact%3D%5C%22%5C%22+qrticket%3D%5C%22%5C%22+chatroomusername%3D%5C%22%5C%22+sourceusername%3D%5C%22%5C%22+sourcenickname%3D%5C%22%5C%22%3E%3Cbrandlist+count%3D%5C%220%5C%22+ver%3D%5C%22652101432%5C%22%3E%3C%2Fbrandlist%3E%3C%2Fmsg%3E%22%2C%22continue%22%3A1%2C%22description%22%3A%22%22%2C%22from_user%22%3A%22fmessage%22%2C%22msg_id%22%3A%222957327798149218888%22%2C%22msg_source%22%3A%22%22%2C%22msg_type%22%3A5%2C%22status%22%3A1%2C%22sub_type%22%3A37%2C%22timestamp%22%3A1528557626%2C%22to_user%22%3A%22wxid_5zj4i5htp9ih22%22%2C%22uin%22%3A1928023446%7D%5D%0A'
// https://stackoverflow.com/a/24417399/1123955
const data = DATA.replace(/\+/g, '%20')
const TENCENT_PAYLOAD_LIST: PadchatMessagePayload[] = JSON.parse(decodeURIComponent(data))
const TENCENT_PAYLOAD_LIST: PadchatMessagePayload[] = padchatDecode(DATA)
const PADCHAT_MESSAGE_PAYLOAD = TENCENT_PAYLOAD_LIST[0]
const EXPECTED_FRIEND_REQUEST_PAYLOAD = {
id : '2957327798149218888',
contactId : 'lizhuohuan',
hello : 'xixixi',
stranger : 'v1_cf269def9b946093f9d131a5e733ba169351013c95e46a860cddecaf485c4b10@stranger',
ticket : 'v2_1a0d2cf325e64b6f74bed09e944529e7cc7a7580cb323475050664566dd0302d89b8e2ed95b596b459cf762d94a0ce606da39babbae0dc26b18a62e079bfc120@stranger',
type : FriendshipType.Receive,
}
......
......@@ -2,6 +2,9 @@ import { toJson } from 'xml2json'
import {
FriendshipPayload,
FriendshipPayloadConfirm,
FriendshipPayloadReceive,
FriendshipPayloadVerify,
FriendshipType,
} from '../../puppet/'
......@@ -10,25 +13,78 @@ import {
PadchatFriendshipPayload,
} from '../padchat-schemas'
export async function friendshipRawPayloadParser(
import {
friendshipConfirmEventMessageParser,
friendshipVerifyEventMessageParser,
friendshipReceiveEventMessageParser,
} from './friendship-event-message-parser'
export function friendshipRawPayloadParser(
rawPayload: PadchatMessagePayload,
) : FriendshipPayload {
if (friendshipConfirmEventMessageParser(rawPayload)) {
/**
* 1. Confirm Event
*/
return friendshipRawPayloadParserConfirm(rawPayload)
} else if (friendshipVerifyEventMessageParser(rawPayload)) {
/**
* 2. Verify Event
*/
return friendshipRawPayloadParserVerify(rawPayload)
} else if (friendshipReceiveEventMessageParser(rawPayload)) {
/**
* 3. Receive Event
*/
return friendshipRawPayloadParserReceive(rawPayload)
} else {
throw new Error('event type is neither confirm nor verify, and not receive')
}
}
function friendshipRawPayloadParserConfirm(
rawPayload: PadchatMessagePayload,
) : Promise<FriendshipPayload> {
): FriendshipPayload {
const payload: FriendshipPayloadConfirm = {
id : rawPayload.msg_id,
contactId : rawPayload.from_user,
type : FriendshipType.Confirm,
}
return payload
}
function friendshipRawPayloadParserVerify(
rawPayload: PadchatMessagePayload,
): FriendshipPayload {
const payload: FriendshipPayloadVerify = {
id : rawPayload.msg_id,
contactId : rawPayload.from_user,
type : FriendshipType.Verify,
}
return payload
}
let tryXmlText = rawPayload.content
tryXmlText = tryXmlText.replace(/\+/g, ' ')
function friendshipRawPayloadParserReceive(
rawPayload: PadchatMessagePayload,
) {
const tryXmlText = rawPayload.content
interface XmlSchema {
msg?: PadchatFriendshipPayload,
}
const jsonPayload: XmlSchema = JSON.parse(toJson(tryXmlText))
const jsonPayload: XmlSchema = toJson(tryXmlText, { object: true })
if (!jsonPayload.msg) {
throw new Error('no msg found')
}
const padchatFriendshipPayload: PadchatFriendshipPayload = jsonPayload.msg
const friendshipPayload: FriendshipPayload = {
const friendshipPayload: FriendshipPayloadReceive = {
id : rawPayload.msg_id,
contactId : padchatFriendshipPayload.fromusername,
hello : padchatFriendshipPayload.content,
......@@ -38,36 +94,4 @@ export async function friendshipRawPayloadParser(
}
return friendshipPayload
// switch (rawPayload.sub_type) {
// case PadchatMessageType.VerifyMsg:
// if (!rawPayload.RecommendInfo) {
// throw new Error('no RecommendInfo')
// }
// const recommendInfo: WebRecomendInfo = rawPayload.RecommendInfo
// if (!recommendInfo) {
// throw new Error('no recommendInfo')
// }
// const payloadReceive: FriendshipPayloadReceive = {
// id : rawPayload.MsgId,
// contactId : recommendInfo.UserName,
// hello : recommendInfo.Content,
// ticket : recommendInfo.Ticket,
// type : FriendshipType.Receive,
// }
// return payloadReceive
// case PadchatMessageType.Sys:
// const payloadConfirm: FriendshipPayloadConfirm = {
// id : rawPayload.MsgId,
// contactId : rawPayload.FromUserName,
// type : FriendshipType.Confirm,
// }
// return payloadConfirm
// default:
// throw new Error('not supported friend request message raw payload')
// }
}
......@@ -9,6 +9,7 @@ import {
isRoomId,
isContactId,
isContactOfficialId,
isPayload,
isStrangerV1,
isStrangerV2,
} from './is-type'
......@@ -58,3 +59,10 @@ test('isStrangerV2()', async t => {
t.equal(isStrangerV2(STRANGER_V2), true, 'should return true for STRANGER_V2')
t.equal(isStrangerV2(NOT_STRANGER_V2), false, 'should return false for NOT_STRANGER_V2')
})
test('isPayload()', async t => {
t.equal(isPayload(undefined as any) , false, 'undefined is not payload')
t.equal(isPayload(null as any) , false, 'null is not payload')
t.equal(isPayload({}) , false, '{} is not payload')
t.equal(isPayload({a: 42}) , true, 'valid payload')
})
export function isRoomId(id?: string): boolean {
if (!id) {
throw new Error('no id')
// throw new Error('no id')
return false
}
return /@chatroom$/.test(id)
}
export function isContactId(id?: string): boolean {
if (!id) {
throw new Error('no id')
return false
// throw new Error('no id')
}
return !isRoomId(id)
}
export function isContactOfficialId(id?: string): boolean {
if (!id) {
throw new Error('no id')
return false
// throw new Error('no id')
}
return /^gh_/i.test(id)
}
export function isStrangerV1(strangerId?: string): boolean {
if (!strangerId) {
throw new Error('no id')
return false
// throw new Error('no id')
}
return /^v1_/i.test(strangerId)
}
export function isStrangerV2(strangerId?: string): boolean {
if (!strangerId) {
throw new Error('no id')
return false
// throw new Error('no id')
}
return /^v2_/i.test(strangerId)
}
export function isPayload(payload: Object): boolean {
if ( payload
&& typeof payload === 'object'
&& Object.keys(payload).length > 0
) {
return true
}
return false
}
......@@ -6,7 +6,6 @@ import test from 'blue-tape'
import {
PuppetRoomJoinEvent,
YOU,
} from '../../puppet/'
......@@ -91,7 +90,7 @@ test('roomJoinEventMessageParser() EN-other-invite-bot', async t => {
t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
})
test('roomJoinEventMessageParser() EN-other-invite-bot-with-others', async t => {
test('roomJoinEventMessageParser() EN-other-invite-bot-with-2-others', async t => {
const MESSAGE_PAYLOAD: PadchatMessagePayload = {
content : '李卓桓 invited you and Huan to the group chat',
continue : 1,
......@@ -320,8 +319,8 @@ test('roomJoinEventMessageParser() EN-scan-qrcode-shared-by-other-when-bot-no-ow
t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
})
test('roomJoinEventMessageParser() EN-bot-invite-others', async t => {
t.skip('should be the same as the bot-invite-other')
test('roomJoinEventMessageParser() EN-bot-invite-many', async t => {
t.skip('should be the same as the bot-invite-many')
})
test('roomJoinEventMessageParser() EN-room-create', async t => {
......
......@@ -38,33 +38,12 @@ test('roomJoinEventMessageParser() ZH-other-invite-other', async t => {
}
const event = roomJoinEventMessageParser(MESSAGE_PAYLOAD)
console.log('payload:', event)
// console.log('payload:', event)
t.deepEqual(event, EXPECTED_EVENT, 'should parse room join message payload')
})
test('roomJoinEventMessageParser() ZH-other-invite-others', async t => {
const MESSAGE_PAYLOAD: PadchatMessagePayload = {
content : '李卓桓 invited 李佳芮, 李卓桓2 to the group chat',
continue : 1,
description : '',
from_user : '5178377660@chatroom',
msg_id : '3318447775079396781',
msg_source : '',
msg_type : 5,
status : 1,
sub_type : 10000,
timestamp : 1528752402,
to_user : 'wxid_5zj4i5htp9ih22',
uin : 1928023446,
}
const EXPECTED_EVENT: PuppetRoomJoinEvent = {
inviteeNameList : ['李佳芮', '李卓桓2'],
inviterName : '李卓桓',
roomId : '5178377660@chatroom',
}
const event = roomJoinEventMessageParser(MESSAGE_PAYLOAD)
t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
t.skip('tbw')
})
test('roomJoinEventMessageParser() ZH-other-invite-bot', async t => {
......@@ -93,7 +72,7 @@ test('roomJoinEventMessageParser() ZH-other-invite-bot', async t => {
t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
})
test('roomJoinEventMessageParser() ZH-other-invite-bot-with-others', async t => {
test('roomJoinEventMessageParser() ZH-other-invite-bot-with-other', async t => {
const MESSAGE_PAYLOAD: PadchatMessagePayload = {
content : '"李卓桓"邀请你和"Huan LI++"加入了群聊',
continue : 1,
......@@ -321,8 +300,8 @@ test('roomJoinEventMessageParser() ZH-scan-qrcode-shared-by-other-when-bot-is-ow
t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
})
test('roomJoinEventMessageParser() ZH-bot-invite-others', async t => {
t.skip('the same as remove other')
test('roomJoinEventMessageParser() ZH-bot-invite-three', async t => {
t.skip('tbw')
})
test('roomJoinEventMessageParser() ZH-room-create', async t => {
......
......@@ -13,6 +13,9 @@ import {
roomJoinEventMessageParser,
roomLeaveEventMessageParser,
roomTopicEventMessageParser,
splitChineseNameList,
splitEnglishNameList,
} from './room-event-message-parser'
test('roomJoinEventMessageParser() not detected', async t => {
......@@ -113,3 +116,19 @@ test('roomTopicEventMessageParser() not detected', async t => {
)
})
test('splitChineseNameList()', async t => {
const TEXT = '李卓桓、李佳芮、桔小秘'
const EXPECTED_LIST = ['李卓桓', '李佳芮', '桔小秘']
const list = splitChineseNameList(TEXT)
t.deepEqual(list, EXPECTED_LIST, 'should split chinese name list')
})
test('splitEnglihshNameList()', async t => {
const TEXT = 'Zhuohuan, 李佳芮, 太阁_传话助手'
const EXPECTED_LIST = ['Zhuohuan', '李佳芮', '太阁_传话助手']
const list = splitEnglishNameList(TEXT)
t.deepEqual(list, EXPECTED_LIST, 'should split english name list')
})
import { toJson } from 'xml2json'
import {
PuppetRoomJoinEvent,
PuppetRoomLeaveEvent,
......@@ -6,46 +8,19 @@ import {
} from '../../puppet/'
import {
PadchatMessagePayload,
PadchatMessagePayload, PadchatMessageType,
} from '../padchat-schemas'
import {
isPayload,
isRoomId,
} from './is-type'
import { log } from '../../config'
const REGEX_CONFIG = {
roomJoinInvite: [
/^"(.+?)"邀请"(.+)"加入了群聊$/,
/^"(.+?)"邀请(.+?)加入了群聊,群聊参与人还有:/,
/^(.+?) invited (.+?) to the group chat$/,
/^(.+?) invited (.+?) to a group chat with $/,
/^"(.+?)"邀请你和"(.+?)"加入了群聊$/,
],
roomJoinInviteYou: [
/^"(.+?)"邀请你和"(.+?)"加入了群聊$/,
],
roomLeaveBotKickOther: [
/^(You) removed "(.+)" from the group chat$/,
/^()将"(.+)"移出了群聊$/,
],
roomLeaveOtherKickMe: [
/^(You) were removed from the group chat by "(.+)"$/,
/^()被"(.+)"移出群聊$/,
],
roomTopic: [
/^"(.+?)" changed the group name to "(.+)"$/,
/^"(.+?)"修改群名为“(.+)”$/,
/^(You) changed the group name to "(.+)"$/,
/^()修改群名为“(.+)”$/,
],
}
/**
*
* 1. Room Join Event
*
*
* try to find 'join' event for Room
*
* 1.
......@@ -55,74 +30,205 @@ const REGEX_CONFIG = {
* 李卓桓 invited you and Huan to the group chat
* 2.
* "李卓桓"邀请"Huan LI++"加入了群聊
* 李卓桓 invited 李佳芮, 李卓桓2 to the group chat
* "李佳芮"邀请你加入了群聊,群聊参与人还有:小桔、桔小秘、小小桔、wuli舞哩客服、舒米
* "李卓桓"邀请你和"Huan LI++"加入了群聊
*/
function parseRoomJoin(
content: string,
): [string[], string] {
log.verbose('PuppetPadchatFirer', 'parseRoomJoin(%s)', content)
const reListInvite = REGEX_CONFIG.roomJoinInvite
// TODO:
// const reListQrcode = REGEX_CONFIG.roomJoinQrcode
let foundInvite: string[]|null = []
reListInvite.some(re => !!(foundInvite = content.match(re)))
// TODO:
// let foundQrcode: string[]|null = []
// reListQrcode.some(re => !!(foundQrcode = content.match(re)))
// if ((!foundInvite || !foundInvite.length) && (!foundQrcode || !foundQrcode.length)) {
if ((!foundInvite || !foundInvite.length)) {
throw new Error('parseRoomJoin() not found matched re of ' + content)
}
// const [inviterName, inviteeStr] = foundInvite ? [ foundInvite[1], foundInvite[2] ] : [ foundQrcode[2], foundQrcode[1] ]
const [inviterName, inviteeStr] = [ foundInvite[1], foundInvite[2] ]
const ROOM_JOIN_BOT_INVITE_OTHER_REGEX_LIST_ZH = [
/^你邀请"(.+)"加入了群聊/,
/^"(.+)"通过扫描你分享的二维码加入群聊/,
]
const ROOM_JOIN_BOT_INVITE_OTHER_REGEX_LIST_EN = [
/^You invited (.+) to the group chat/,
/^"(.+)" joined group chat via the QR code you shared/,
]
/**
* 李卓桓 invited you and Huan to the group chat
*/
let inviteeNameList: string[] = []
if (/^you and/.test(inviteeStr)) {
inviteeNameList = inviteeStr.split(/ and /)
} else {
inviteeNameList = inviteeStr.split(/, /)
////////////////////////////////////////////////////
const ROOM_JOIN_OTHER_INVITE_BOT_REGEX_LIST_ZH = [
/^"([^"]+?)"邀请你加入了群聊/,
/^"([^"]+?)"邀请你和"(.+)"加入了群聊/,
]
const ROOM_JOIN_OTHER_INVITE_BOT_REGEX_LIST_EN = [
/^(.+) invited you to a group chat/,
/^(.+) invited you and (.+) to the group chat/,
]
////////////////////////////////////////////////////
const ROOM_JOIN_OTHER_INVITE_OTHER_REGEX_LIST_ZH = [
/^"(.+)"邀请"(.+)"加入了群聊/,
]
const ROOM_JOIN_OTHER_INVITE_OTHER_REGEX_LIST_EN = [
/^(.+?) invited (.+?) to (the|a) group chat/,
]
export function roomJoinEventMessageParser(
rawPayload: PadchatMessagePayload,
): null | PuppetRoomJoinEvent {
if (!isPayload(rawPayload)) {
return null
}
const roomId = rawPayload.from_user
if (!isRoomId(roomId)) {
return null
}
let content = rawPayload.content
/**
* "李卓桓"邀请你和"Huan LI++"加入了群聊
* when the message is a Recalled type, bot can undo the invitation
*/
if (REGEX_CONFIG.roomJoinInviteYou[0].test(content)) {
const invitee = inviteeNameList[0]
inviteeNameList = ['', invitee]
if (rawPayload.sub_type === PadchatMessageType.Recalled) {
/**
* content:
* ```
* 3453262102@chatroom:
* <sysmsg type="delchatroommember">
* ...
* </sysmsg>
* ```
*/
const tryXmlText = content.replace(/^[^\n]+\n/, '')
interface XmlSchema {
sysmsg: {
type: string,
delchatroommember: {
plain: string,
text: string,
},
}
}
const jsonPayload = toJson(tryXmlText, { object: true }) as XmlSchema
content = jsonPayload.sysmsg.delchatroommember.plain
}
return [inviteeNameList, inviterName] // put invitee at first place
}
let matchesForBotInviteOtherEn = null as null | string[]
let matchesForOtherInviteBotEn = null as null | string[]
let matchesForOtherInviteOtherEn = null as null | string[]
export function roomJoinEventMessageParser(rawPayload: PadchatMessagePayload): null | PuppetRoomJoinEvent {
const roomId = rawPayload.from_user
const content = rawPayload.content
const [inviteeRawNameList, inviterName] = parseRoomJoin(content)
const inviteeNameList: (string | YOU)[] = inviteeRawNameList
if (!isRoomId(roomId)) {
let matchesForBotInviteOtherZh = null as null | string[]
let matchesForOtherInviteBotZh = null as null | string[]
let matchesForOtherInviteOtherZh = null as null | string[]
ROOM_JOIN_BOT_INVITE_OTHER_REGEX_LIST_EN.some(
regex => !!(matchesForBotInviteOtherEn = content.match(regex)),
)
ROOM_JOIN_OTHER_INVITE_BOT_REGEX_LIST_EN.some(
regex => !!(matchesForOtherInviteBotEn = content.match(regex)),
)
ROOM_JOIN_OTHER_INVITE_OTHER_REGEX_LIST_EN.some(
regex => !!(matchesForOtherInviteOtherEn = content.match(regex)),
)
ROOM_JOIN_BOT_INVITE_OTHER_REGEX_LIST_ZH.some(
regex => !!(matchesForBotInviteOtherZh = content.match(regex)),
)
ROOM_JOIN_OTHER_INVITE_BOT_REGEX_LIST_ZH.some(
regex => !!(matchesForOtherInviteBotZh = content.match(regex)),
)
ROOM_JOIN_OTHER_INVITE_OTHER_REGEX_LIST_ZH.some(
regex => !!(matchesForOtherInviteOtherZh = content.match(regex)),
)
const matchesForBotInviteOther = matchesForBotInviteOtherEn || matchesForBotInviteOtherZh
const matchesForOtherInviteBot = matchesForOtherInviteBotEn || matchesForOtherInviteBotZh
const matchesForOtherInviteOther = matchesForOtherInviteOtherEn || matchesForOtherInviteOtherZh
const languageEn = matchesForBotInviteOtherEn || matchesForOtherInviteBotEn || matchesForOtherInviteOtherEn
const languageZh = matchesForBotInviteOtherZh || matchesForOtherInviteBotZh || matchesForOtherInviteOtherZh
const matches = matchesForBotInviteOther
|| matchesForOtherInviteBot
|| matchesForOtherInviteOther
if (!matches) {
return null
}
if (inviteeNameList[0] === '' || inviteeNameList[0] === 'you') {
inviteeNameList[0] = YOU
}
const roomJoinEvent: PuppetRoomJoinEvent = {
inviteeNameList : inviteeNameList,
inviterName : inviterName,
roomId,
if (matchesForBotInviteOther) {
const other = matches[1]
let inviteeNameList
if (languageEn) {
inviteeNameList = splitEnglishNameList(other)
} else if (languageZh) {
inviteeNameList = splitChineseNameList(other)
} else {
throw new Error('make typescript happy')
}
const inviterName: string | YOU = YOU
const joinEvent: PuppetRoomJoinEvent = {
inviteeNameList,
inviterName,
roomId,
}
return joinEvent
} else if (matchesForOtherInviteBot) {
// /^"([^"]+?)"邀请你加入了群聊/,
// /^"([^"]+?)"邀请你和"(.+?)"加入了群聊/,
const inviterName = matches[1]
let inviteeNameList: (YOU | string)[] = [YOU]
if (matches[2]) {
let nameList
if (languageEn) {
nameList = splitEnglishNameList(matches[2])
} else if (languageZh) {
nameList = splitChineseNameList(matches[2])
} else {
throw new Error('neither English nor Chinese')
}
inviteeNameList = inviteeNameList.concat(nameList)
}
const joinEvent: PuppetRoomJoinEvent = {
inviteeNameList,
inviterName,
roomId,
}
return joinEvent
} else if (matchesForOtherInviteOther) {
// /^"([^"]+?)"邀请"([^"]+)"加入了群聊$/,
// /^([^"]+?) invited ([^"]+?) to (the|a) group chat/,
const inviterName = matches[1]
let inviteeNameList: string[]
const other = matches[2]
if (languageEn) {
inviteeNameList = splitEnglishNameList(other)
} else if (languageZh) {
inviteeNameList = splitChineseNameList(other)
} else {
throw new Error('neither English nor Chinese')
}
const joinEvent: PuppetRoomJoinEvent = {
inviteeNameList,
inviterName,
roomId,
}
return joinEvent
} else {
throw new Error('who invite who?')
}
return roomJoinEvent
}
/**
*
* 2. Room Leave Event
*
*
* try to find 'leave' event for Room
*
* 1.
......@@ -132,55 +238,62 @@ export function roomJoinEventMessageParser(rawPayload: PadchatMessagePayload): n
* 你将"Huan LI++"移出了群聊
* 你被"李卓桓"移出群聊
*/
function parseRoomLeave(
content: string,
): [string, string] {
let matchIKickOther: null | string[] = []
REGEX_CONFIG.roomLeaveBotKickOther.some(
regex => !!(
matchIKickOther = content.match(regex)
),
)
let matchOtherKickMe: null | string[] = []
REGEX_CONFIG.roomLeaveOtherKickMe.some(
re => !!(
matchOtherKickMe = content.match(re)
),
)
const ROOM_LEAVE_OTHER_REGEX_LIST = [
/^(You) removed "(.+)" from the group chat/,
/^()将"(.+)"移出了群聊/,
]
let leaverName : undefined | string
let removerName : undefined | string
const ROOM_LEAVE_BOT_REGEX_LIST = [
/^(You) were removed from the group chat by "([^"]+)"/,
/^()被"([^"]+?)"移出群聊/,
]
if (matchIKickOther && matchIKickOther.length) {
leaverName = matchIKickOther[2]
removerName = matchIKickOther[1]
} else if (matchOtherKickMe && matchOtherKickMe.length) {
leaverName = matchOtherKickMe[1]
removerName = matchOtherKickMe[2]
} else {
throw new Error('no match')
}
export function roomLeaveEventMessageParser(
rawPayload: PadchatMessagePayload,
): null | PuppetRoomLeaveEvent {
return [leaverName, removerName]
}
if (!isPayload(rawPayload)) {
return null
}
export function roomLeaveEventMessageParser(rawPayload: PadchatMessagePayload): null | PuppetRoomLeaveEvent {
const roomId = rawPayload.from_user
const roomId = rawPayload.from_user
const content = rawPayload.content
const [leaverRawName, removerRawName] = parseRoomLeave(content)
let leaverName: string | YOU = leaverRawName
let removerName: string | YOU = removerRawName
if (!isRoomId(roomId)) {
return null
}
if (leaverRawName === '' || leaverRawName === 'You') {
leaverName = YOU
let matchesForOther: null | string[] = []
ROOM_LEAVE_OTHER_REGEX_LIST.some(
regex => !!(
matchesForOther = content.match(regex)
),
)
let matchesForBot: null | string[] = []
ROOM_LEAVE_BOT_REGEX_LIST.some(
re => !!(
matchesForBot = content.match(re)
),
)
const matches = matchesForOther || matchesForBot
if (!matches) {
return null
}
if (removerRawName === '' || removerRawName === 'You') {
let leaverName : undefined | string | YOU
let removerName : undefined | string | YOU
if (matchesForOther) {
removerName = YOU
leaverName = matchesForOther[2]
} else if (matchesForBot) {
removerName = matchesForBot[2]
leaverName = YOU
} else {
throw new Error('for typescript type checking, will never go here')
}
const roomLeaveEvent: PuppetRoomLeaveEvent = {
......@@ -191,38 +304,70 @@ export function roomLeaveEventMessageParser(rawPayload: PadchatMessagePayload):
return roomLeaveEvent
}
function parseRoomTopic(
content: string,
): [string, string] {
const reList = REGEX_CONFIG.roomTopic
/**
*
* 3. Room Topic Event
*
*/
const ROOM_TOPIC_OTHER_REGEX_LIST = [
/^"(.+)" changed the group name to "(.+)"$/,
/^"(.+)"修改群名为“(.+)”$/,
]
const ROOM_TOPIC_YOU_REGEX_LIST = [
/^(You) changed the group name to "(.+)"$/,
/^()修改群名为“(.+)”$/,
]
let found: string[]|null = []
reList.some(re => !!(found = content.match(re)))
if (!found || !found.length) {
throw new Error('checkRoomTopic() not found')
export function roomTopicEventMessageParser(
rawPayload: PadchatMessagePayload,
): null | PuppetRoomTopicEvent {
if (!isPayload(rawPayload)) {
return null
}
const [, changer, topic] = found
return [topic, changer]
}
export function roomTopicEventMessageParser(rawPayload: PadchatMessagePayload): null | PuppetRoomTopicEvent {
const roomId = rawPayload.from_user
const roomId = rawPayload.from_user
const content = rawPayload.content
const [topic, rawChangerName] = parseRoomTopic(content)
let changerName: string | YOU = rawChangerName
if (!isRoomId(roomId)) {
return null
}
if (rawChangerName === '' || rawChangerName === 'You') {
let matchesForOther: null | string[] = []
let matchesForYou: null | string[] = []
ROOM_TOPIC_OTHER_REGEX_LIST .some(regex => !!(matchesForOther = content.match(regex)))
ROOM_TOPIC_YOU_REGEX_LIST .some(regex => !!(matchesForYou = content.match(regex)))
const matches: (string | YOU)[] = matchesForOther || matchesForYou
if (!matches) {
return null
}
let changerName = matches[1]
const topic = matches[2] as string
if (matchesForYou && changerName === '' || changerName === 'You') {
changerName = YOU
}
const roomTopicEvent: PuppetRoomTopicEvent = {
changerName: changerName,
topic: topic,
changerName,
roomId,
topic,
}
return roomTopicEvent
}
export function splitChineseNameList(nameListText: string): string[] {
// 李卓桓、李佳芮、桔小秘
return nameListText.split('')
}
export function splitEnglishNameList(nameListText: string): string[] {
// Zhuohuan, 太阁_传话助手, 桔小秘
return nameListText.split(', ')
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册