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

implment room join event with better regex and language support

上级 3a2f835f
......@@ -265,6 +265,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),
......
......@@ -115,31 +115,31 @@ test('roomJoinEventMessageParser() EN-other-invite-bot-with-2-others', async t =
t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
})
// test('roomJoinEventMessageParser() EN-bot-invite-other', async t => {
// const MESSAGE_PAYLOAD: PadchatMessagePayload = {
// content : '3453262102@chatroom:\n<sysmsg type="delchatroommember">\n\t<delchatroommember>\n\t\t<plain><![CDATA[You invited . 李 卓 桓 .呵呵 to the group chat. ]]></plain>\n\t\t<text><![CDATA[You invited . 李 卓 桓 .呵呵 to the group chat. ]]></text>\n\t\t<link>\n\t\t\t<scene>invite</scene>\n\t\t\t<text><![CDATA[ Revoke]]></text>\n\t\t\t<memberlist>\n\t\t\t\t<username><![CDATA[wxid_a8d806dzznm822]]></username>\n\t\t\t</memberlist>\n\t\t</link>\n\t</delchatroommember>\n</sysmsg>\n',
// continue : 1,
// description : '',
// from_user : '3453262102@chatroom',
// msg_id : '4030118997146183783',
// msg_source : '',
// msg_type : 5,
// status : 1,
// sub_type : 10002,
// timestamp : 1528755135,
// to_user : 'wxid_5zj4i5htp9ih22',
// uin : 1928023446,
// }
// const EXPECTED_EVENT: PuppetRoomJoinEvent = {
// inviteeNameList : ['. 李 卓 桓 .呵呵'],
// inviterName : YOU,
// roomId : '3453262102@chatroom',
// }
// const event = roomJoinEventMessageParser(MESSAGE_PAYLOAD)
// t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
// })
test('roomJoinEventMessageParser() EN-bot-invite-other', async t => {
const MESSAGE_PAYLOAD: PadchatMessagePayload = {
content : '3453262102@chatroom:\n<sysmsg type="delchatroommember">\n\t<delchatroommember>\n\t\t<plain><![CDATA[You invited . 李 卓 桓 .呵呵 to the group chat. ]]></plain>\n\t\t<text><![CDATA[You invited . 李 卓 桓 .呵呵 to the group chat. ]]></text>\n\t\t<link>\n\t\t\t<scene>invite</scene>\n\t\t\t<text><![CDATA[ Revoke]]></text>\n\t\t\t<memberlist>\n\t\t\t\t<username><![CDATA[wxid_a8d806dzznm822]]></username>\n\t\t\t</memberlist>\n\t\t</link>\n\t</delchatroommember>\n</sysmsg>\n',
continue : 1,
description : '',
from_user : '3453262102@chatroom',
msg_id : '4030118997146183783',
msg_source : '',
msg_type : 5,
status : 1,
sub_type : 10002,
timestamp : 1528755135,
to_user : 'wxid_5zj4i5htp9ih22',
uin : 1928023446,
}
const EXPECTED_EVENT: PuppetRoomJoinEvent = {
inviteeNameList : ['. 李 卓 桓 .呵呵'],
inviterName : YOU,
roomId : '3453262102@chatroom',
}
const event = roomJoinEventMessageParser(MESSAGE_PAYLOAD)
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')
......
......@@ -97,30 +97,30 @@ test('roomJoinEventMessageParser() ZH-other-invite-bot-with-others', async t =>
t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
})
// test('roomJoinEventMessageParser() ZH-bot-invite-other', async t => {
// const MESSAGE_PAYLOAD: PadchatMessagePayload = {
// content : '5354656522@chatroom:\n<sysmsg type="delchatroommember">\n\t<delchatroommember>\n\t\t<plain><![CDATA[你邀请"Huan LI++"加入了群聊 ]]></plain>\n\t\t<text><![CDATA[你邀请"Huan LI++"加入了群聊 ]]></text>\n\t\t<link>\n\t\t\t<scene>invite</scene>\n\t\t\t<text><![CDATA[ 撤销]]></text>\n\t\t\t<memberlist>\n\t\t\t\t<username><![CDATA[wxid_5zj4i5htp9ih22]]></username>\n\t\t\t</memberlist>\n\t\t</link>\n\t</delchatroommember>\n</sysmsg>\n',
// continue : 1,
// description : '',
// from_user : '5354656522@chatroom',
// msg_id : '6278175026243694414',
// msg_source : '',
// msg_type : 5,
// status : 1,
// sub_type : 10002,
// timestamp : 1528657265,
// to_user : 'lizhuohuan',
// uin : 4763975,
// }
// const EXPECTED_EVENT: PuppetRoomJoinEvent = {
// inviteeNameList : ['Huan LI++'],
// inviterName : YOU,
// roomId : '5354656522@chatroom',
// }
// const event = roomJoinEventMessageParser(MESSAGE_PAYLOAD)
// t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
// })
test('roomJoinEventMessageParser() ZH-bot-invite-other', async t => {
const MESSAGE_PAYLOAD: PadchatMessagePayload = {
content : '5354656522@chatroom:\n<sysmsg type="delchatroommember">\n\t<delchatroommember>\n\t\t<plain><![CDATA[你邀请"Huan LI++"加入了群聊 ]]></plain>\n\t\t<text><![CDATA[你邀请"Huan LI++"加入了群聊 ]]></text>\n\t\t<link>\n\t\t\t<scene>invite</scene>\n\t\t\t<text><![CDATA[ 撤销]]></text>\n\t\t\t<memberlist>\n\t\t\t\t<username><![CDATA[wxid_5zj4i5htp9ih22]]></username>\n\t\t\t</memberlist>\n\t\t</link>\n\t</delchatroommember>\n</sysmsg>\n',
continue : 1,
description : '',
from_user : '5354656522@chatroom',
msg_id : '6278175026243694414',
msg_source : '',
msg_type : 5,
status : 1,
sub_type : 10002,
timestamp : 1528657265,
to_user : 'lizhuohuan',
uin : 4763975,
}
const EXPECTED_EVENT: PuppetRoomJoinEvent = {
inviteeNameList : ['Huan LI++'],
inviterName : YOU,
roomId : '5354656522@chatroom',
}
const event = roomJoinEventMessageParser(MESSAGE_PAYLOAD)
t.deepEqual(event, EXPECTED_EVENT, 'should parse event')
})
test('roomJoinEventMessageParser() ZH-bot-invite-others', async t => {
t.skip('tbw')
......
......@@ -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.equal(list, EXPECTED_LIST, 'should split chinese name list')
})
test('splitEnglihshNameList()', async t => {
const TEXT = 'Zhuohuan, 李佳芮, 太阁_传话助手'
const EXPECTED_LIST = ['Zhuohuan', '李佳芮', '太阁_传话助手']
const list = splitEnglishNameList(TEXT)
t.equal(list, EXPECTED_LIST, 'should split english name list')
})
import { toJson } from 'xml2json'
import {
PuppetRoomJoinEvent,
PuppetRoomLeaveEvent,
......@@ -6,44 +8,19 @@ import {
} from '../../puppet/'
import {
PadchatMessagePayload,
PadchatMessagePayload, PadchatMessageType,
} from '../padchat-schemas'
import {
isPayload,
isRoomId,
} from './is-type'
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.
......@@ -53,65 +30,189 @@ const REGEX_CONFIG = {
* 李卓桓 invited you and Huan to the group chat
* 2.
* "李卓桓"邀请"Huan LI++"加入了群聊
* 李卓桓 invited 李佳芮, 李卓桓2 to the group chat
* "李佳芮"邀请你加入了群聊,群聊参与人还有:小桔、桔小秘、小小桔、wuli舞哩客服、舒米
* "李卓桓"邀请你和"Huan LI++"加入了群聊
*/
export function roomJoinEventMessageParser(rawPayload: PadchatMessagePayload): null | PuppetRoomJoinEvent {
const roomId = rawPayload.from_user
const content = rawPayload.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 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/,
]
// const [inviterName, inviteeStr] = foundInvite ? [ foundInvite[1], foundInvite[2] ] : [ foundQrcode[2], foundQrcode[1] ]
const [inviterName, inviteeStr] = [ foundInvite[1], foundInvite[2] ]
////////////////////////////////////////////////////
/**
* 李卓桓 invited you and Huan to the group chat
*/
let inviteeNameList: (string | YOU)[] = []
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) {
interface XmlSchema {
plain: string,
}
const jsonPayload = toJson(content, { object: true }) as XmlSchema
content = jsonPayload.plain
}
if (!isRoomId(roomId)) {
let matchesForBotInviteOtherEn = null as null | string[]
let matchesForOtherInviteBotEn = null as null | string[]
let matchesForOtherInviteOtherEn = null as null | string[]
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.
......@@ -121,47 +222,62 @@ export function roomJoinEventMessageParser(rawPayload: PadchatMessagePayload): n
* 你将"Huan LI++"移出了群聊
* 你被"李卓桓"移出群聊
*/
export function roomLeaveEventMessageParser(rawPayload: PadchatMessagePayload): null | PuppetRoomLeaveEvent {
const roomId = rawPayload.from_user
const ROOM_LEAVE_OTHER_REGEX_LIST = [
/^(You) removed "(.+)" from the group chat/,
/^()将"(.+)"移出了群聊/,
]
const ROOM_LEAVE_BOT_REGEX_LIST = [
/^(You) were removed from the group chat by "([^"]+)"/,
/^()被"([^"]+?)"移出群聊/,
]
export function roomLeaveEventMessageParser(
rawPayload: PadchatMessagePayload,
): null | PuppetRoomLeaveEvent {
if (!isPayload(rawPayload)) {
return null
}
const roomId = rawPayload.from_user
const content = rawPayload.content
let matchIKickOther: null | string[] = []
REGEX_CONFIG.roomLeaveBotKickOther.some(
if (!isRoomId(roomId)) {
return null
}
let matchesForOther: null | string[] = []
ROOM_LEAVE_OTHER_REGEX_LIST.some(
regex => !!(
matchIKickOther = content.match(regex)
matchesForOther = content.match(regex)
),
)
let matchOtherKickMe: null | string[] = []
REGEX_CONFIG.roomLeaveOtherKickMe.some(
let matchesForBot: null | string[] = []
ROOM_LEAVE_BOT_REGEX_LIST.some(
re => !!(
matchOtherKickMe = content.match(re)
matchesForBot = content.match(re)
),
)
let leaverName : undefined | string | YOU
let removerName : undefined | string | YOU
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')
}
if (!isRoomId(roomId)) {
const matches = matchesForOther || matchesForBot
if (!matches) {
return null
}
if (leaverName === '' || leaverName === 'You') {
leaverName = YOU
}
let leaverName : undefined | string | YOU
let removerName : undefined | string | YOU
if (removerName === '' || removerName === '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 = {
......@@ -172,35 +288,70 @@ export function roomLeaveEventMessageParser(rawPayload: PadchatMessagePayload):
return roomLeaveEvent
}
export function roomTopicEventMessageParser(rawPayload: PadchatMessagePayload): null | PuppetRoomTopicEvent {
const roomId = rawPayload.from_user
const content = rawPayload.content
/**
*
* 3. Room Topic Event
*
*/
const reList = REGEX_CONFIG.roomTopic
const ROOM_TOPIC_OTHER_REGEX_LIST = [
/^"(.+)" 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')
}
const ROOM_TOPIC_YOU_REGEX_LIST = [
/^(You) changed the group name to "(.+)"$/,
/^()修改群名为“(.+)”$/,
]
let changerName: undefined | string | YOU
let topic: string
export function roomTopicEventMessageParser(
rawPayload: PadchatMessagePayload,
): null | PuppetRoomTopicEvent {
[, changerName, topic] = found
if (!isPayload(rawPayload)) {
return null
}
const roomId = rawPayload.from_user
const content = rawPayload.content
if (!isRoomId(roomId)) {
return null
}
if (changerName === '' || changerName === '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.
先完成此消息的编辑!
想要评论请 注册