Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ npm install n8n-nodes-wecom
- ✅ [分配客服会话](https://developer.work.weixin.qq.com/document/path/94669)
- ✅ [发送消息](https://developer.work.weixin.qq.com/document/path/94677)
- ✅ [发送欢迎语等事件响应消息](https://developer.work.weixin.qq.com/document/path/95122)
- ✅ [读取消息](https://developer.work.weixin.qq.com/document/path/94670)
- ✅ [「升级服务」配置](https://developer.work.weixin.qq.com/document/path/94674)
- ✅ [获取客户基础信息](https://developer.work.weixin.qq.com/document/path/95159)

Expand Down
68 changes: 68 additions & 0 deletions nodes/WeCom/resources/kf/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,74 @@ export async function executeKf(
open_kfid,
upgrade_config: parsedConfig,
});
} else if (operation === 'syncMsg') {
const open_kfid = this.getNodeParameter('open_kfid', i) as string;
const cursor = this.getNodeParameter('cursor', i, '') as string;
const token = this.getNodeParameter('token', i, '') as string;
const limit = this.getNodeParameter('limit', i, 100) as number;
const voice_format = this.getNodeParameter('voice_format', i, 0) as number;
const parse_message_types = this.getNodeParameter('parse_message_types', i, true) as boolean;

const body: IDataObject = {
open_kfid,
limit,
voice_format,
};

if (cursor) body.cursor = cursor;
if (token) body.token = token;

response = await weComApiRequest.call(this, 'POST', '/cgi-bin/kf/sync_msg', body);

// 如果需要解析消息类型,对msg_list进行处理
if (parse_message_types && response.msg_list && Array.isArray(response.msg_list)) {
response.msg_list = (response.msg_list as IDataObject[]).map((msg: IDataObject) => {
const msgtype = msg.msgtype as string;

// 为每个消息添加解析后的字段,便于后续处理
const parsedMsg: IDataObject = {
...msg,
parsed_content: null,
};

// 根据消息类型解析内容
if (msgtype === 'text' && msg.text) {
parsedMsg.parsed_content = msg.text;
} else if (msgtype === 'image' && msg.image) {
parsedMsg.parsed_content = msg.image;
} else if (msgtype === 'voice' && msg.voice) {
parsedMsg.parsed_content = msg.voice;
} else if (msgtype === 'video' && msg.video) {
parsedMsg.parsed_content = msg.video;
} else if (msgtype === 'file' && msg.file) {
parsedMsg.parsed_content = msg.file;
} else if (msgtype === 'location' && msg.location) {
parsedMsg.parsed_content = msg.location;
} else if (msgtype === 'link' && msg.link) {
parsedMsg.parsed_content = msg.link;
} else if (msgtype === 'business_card' && msg.business_card) {
parsedMsg.parsed_content = msg.business_card;
} else if (msgtype === 'miniprogram' && msg.miniprogram) {
parsedMsg.parsed_content = msg.miniprogram;
} else if (msgtype === 'msgmenu' && msg.msgmenu) {
parsedMsg.parsed_content = msg.msgmenu;
} else if (msgtype === 'channels_shop_product' && msg.channels_shop_product) {
parsedMsg.parsed_content = msg.channels_shop_product;
} else if (msgtype === 'channels_shop_order' && msg.channels_shop_order) {
parsedMsg.parsed_content = msg.channels_shop_order;
} else if (msgtype === 'merged_msg' && msg.merged_msg) {
parsedMsg.parsed_content = msg.merged_msg;
} else if (msgtype === 'channels' && msg.channels) {
parsedMsg.parsed_content = msg.channels;
} else if (msgtype === 'event' && msg.event) {
parsedMsg.parsed_content = msg.event;
// 为事件类型添加event_type字段方便筛选
parsedMsg.event_type = (msg.event as IDataObject).event_type;
}

return parsedMsg;
});
}
} else if (operation === 'getCustomerInfo') {
const open_kfid = this.getNodeParameter('open_kfid', i) as string;
const external_userid = this.getNodeParameter('external_userid', i) as string;
Expand Down
7 changes: 7 additions & 0 deletions nodes/WeCom/resources/kf/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { listServicerDescription } from './listServicer';
import { transServiceStateDescription } from './transServiceState';
import { sendKfMsgDescription } from './sendKfMsg';
import { sendKfEventMsgDescription } from './sendKfEventMsg';
import { syncMsgDescription } from './syncMsg';
import { setUpgradeServiceDescription } from './setUpgradeService';
import { getCustomerInfoDescription } from './getCustomerInfo';

Expand Down Expand Up @@ -100,6 +101,11 @@ export const kfDescription: INodeProperties[] = [
value: 'sendKfEventMsg',
action: '发送事件响应消息',
},
{
name: '读取消息',
value: 'syncMsg',
action: '读取消息',
},
{
name: '设置升级服务配置',
value: 'setUpgradeService',
Expand Down Expand Up @@ -149,6 +155,7 @@ export const kfDescription: INodeProperties[] = [
...transServiceStateDescription,
...sendKfMsgDescription,
...sendKfEventMsgDescription,
...syncMsgDescription,
...setUpgradeServiceDescription,
...getCustomerInfoDescription,
// 统计管理
Expand Down
94 changes: 94 additions & 0 deletions nodes/WeCom/resources/kf/syncMsg.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import type { INodeProperties } from 'n8n-workflow';

const showOnlyForSyncMsg = {
resource: ['kf'],
operation: ['syncMsg'],
};

export const syncMsgDescription: INodeProperties[] = [
{
displayName: '客服账号 Name or ID',
name: 'open_kfid',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getKfAccounts',
},
required: true,
displayOptions: {
show: showOnlyForSyncMsg,
},
default: '',
description:
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
hint: '客服账号',
},
{
displayName: '游标',
name: 'cursor',
type: 'string',
displayOptions: {
show: showOnlyForSyncMsg,
},
default: '',
description: '上一次调用的next_cursor,第一次拉取可以不填。持久化保存游标可以实现增量拉取。',
hint: '增量拉取的游标,第一次可不填',
},
{
displayName: 'Token',
name: 'token',
type: 'string',
displayOptions: {
show: showOnlyForSyncMsg,
},
default: '',
description: '回调事件返回的token字段,10分钟内有效。可选,如果不填接口有严格的频率限制。',
hint: '回调事件的token,可选',
},
{
displayName: '拉取条数',
name: 'limit',
type: 'number',
displayOptions: {
show: showOnlyForSyncMsg,
},
default: 100,
typeOptions: {
minValue: 1,
maxValue: 1000,
},
description: '期望请求的数据量,默认100,最大1000。实际返回可能小于设定值。',
hint: '期望拉取的消息数量,最大1000',
},
{
displayName: '语音格式',
name: 'voice_format',
type: 'options',
displayOptions: {
show: showOnlyForSyncMsg,
},
options: [
{
name: 'AMR',
value: 0,
},
{
name: 'SILK',
value: 1,
},
],
default: 0,
description: '语音消息类型,0-Amr 1-Silk,默认0。可根据需求选择合适的语音格式。',
hint: '语音消息的格式',
},
{
displayName: '解析消息类型',
name: 'parse_message_types',
type: 'boolean',
displayOptions: {
show: showOnlyForSyncMsg,
},
default: true,
description: '是否自动解析并展开不同的消息类型到单独的字段,便于后续处理',
hint: '自动解析消息类型',
},
];
Loading