314 lines
12 KiB
JavaScript
314 lines
12 KiB
JavaScript
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.registerMessageNotificationConverters = registerMessageNotificationConverters;
|
||
exports.tryMakeSmsNotification = tryMakeSmsNotification;
|
||
exports.tryMakeEmailNotification = tryMakeEmailNotification;
|
||
const uuid_1 = require("oak-domain/lib/utils/uuid");
|
||
const assert_1 = require("oak-domain/lib/utils/assert");
|
||
const lodash_1 = require("oak-domain/lib/utils/lodash");
|
||
const ConverterDict = {};
|
||
function registerMessageNotificationConverters(converters) {
|
||
converters.forEach(ele => {
|
||
(0, assert_1.assert)(!ConverterDict[ele.type]);
|
||
ConverterDict[ele.type] = ele;
|
||
});
|
||
}
|
||
const InitialChannelByWeightMatrix = {
|
||
high: ['wechatMp', 'wechatPublic', 'sms', 'email'],
|
||
medium: ['wechatMp', 'wechatPublic', 'email'],
|
||
low: ['wechatMp', 'wechatPublic', 'email'],
|
||
};
|
||
async function tryMakeSmsNotification(message, context) {
|
||
const { userId, type, entity, entityId, router } = message;
|
||
(0, assert_1.assert)(userId);
|
||
const [mobile] = await context.select('mobile', {
|
||
data: {
|
||
id: 1,
|
||
mobile: 1,
|
||
},
|
||
filter: {
|
||
userId,
|
||
},
|
||
indexFrom: 0,
|
||
count: 1,
|
||
}, { dontCollect: true });
|
||
if (mobile) {
|
||
const converter = ConverterDict[type] && ConverterDict[type].toSms;
|
||
if (converter) {
|
||
const dispersedData = await converter(message, context);
|
||
if (dispersedData) {
|
||
return {
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
data: dispersedData,
|
||
channel: 'sms',
|
||
data1: mobile,
|
||
};
|
||
}
|
||
}
|
||
}
|
||
}
|
||
async function tryMakeEmailNotification(message, context) {
|
||
const { userId, type, entity, entityId, router } = message;
|
||
const converter = ConverterDict[type] && ConverterDict[type].toEmail;
|
||
if (converter) {
|
||
const dispersedData = await converter(message, context);
|
||
if (dispersedData) {
|
||
return {
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
data: dispersedData,
|
||
channel: 'email',
|
||
};
|
||
}
|
||
}
|
||
}
|
||
async function createNotification(message, context) {
|
||
const { restriction, userId, weight, type, entity, entityId, platformId, channels } = message;
|
||
(0, assert_1.assert)(userId);
|
||
// 根据用户所关联的system和定义限制,选择将要发送的system。这里有的应用是到platform级别,有的是到system级别
|
||
const filter = {
|
||
userId,
|
||
};
|
||
if (platformId) {
|
||
filter.system = {
|
||
platformId,
|
||
};
|
||
}
|
||
const userSystems = await context.select('userSystem', {
|
||
data: {
|
||
id: 1,
|
||
system: {
|
||
id: 1,
|
||
config: 1,
|
||
application$system: {
|
||
$entity: 'application',
|
||
data: {
|
||
id: 1,
|
||
type: 1,
|
||
config: 1,
|
||
},
|
||
},
|
||
},
|
||
},
|
||
filter,
|
||
}, { dontCollect: true });
|
||
// 这里实测线上跑出来多条相同的userSystem,还未知道原因 by Xc 20230317
|
||
const systems = (0, lodash_1.uniqBy)(userSystems.map(ele => ele.system).filter(ele => {
|
||
if (restriction && restriction.systemIds) {
|
||
return restriction.systemIds.includes(ele.id);
|
||
}
|
||
return true;
|
||
}), 'id');
|
||
if (systems.length === 0) {
|
||
console.warn(`类型为${type}的消息在生成时,尝试为之生成通知,找不到可推送的system`);
|
||
return 0;
|
||
}
|
||
const messageTypeTemplates = await context.select('messageTypeTemplate', {
|
||
data: {
|
||
id: 1,
|
||
templateId: 1,
|
||
template: {
|
||
id: 1,
|
||
wechatId: 1,
|
||
applicationId: 1,
|
||
},
|
||
type: 1,
|
||
},
|
||
filter: {
|
||
type,
|
||
template: {
|
||
application: {
|
||
systemId: {
|
||
$in: systems.map(ele => ele.id),
|
||
},
|
||
},
|
||
},
|
||
},
|
||
}, { dontCollect: true });
|
||
// 根据定义所限制的渠道和weight,计算出相应的推送渠道
|
||
const channels2 = ((channels && channels.length > 0) ? channels : InitialChannelByWeightMatrix[weight]).filter(ele => {
|
||
if (restriction && restriction.channels) {
|
||
return restriction.channels.includes(ele);
|
||
}
|
||
return true;
|
||
});
|
||
/* if (channels.length === 0) {
|
||
console.warn(`类型为${type}的消息在生成时,尝试为之生成通知,找不到可推送的channel`);
|
||
return 0;
|
||
} */
|
||
// 逐system逐channel去构造messageSystem和messageSent数据
|
||
let messageSentCount = 0;
|
||
const messageSystemDatas = [];
|
||
await Promise.all(systems.map(async (system) => {
|
||
const { application$system: applications, config } = system;
|
||
const notificationDatas = [];
|
||
await Promise.all(channels2.map(async (channel) => {
|
||
switch (channel) {
|
||
case 'wechatMp': {
|
||
const apps = applications.filter(ele => ele.type === 'wechatMp');
|
||
const wechatUsers = await context.select('wechatUser', {
|
||
data: {
|
||
id: 1,
|
||
applicationId: 1,
|
||
openId: 1,
|
||
},
|
||
filter: {
|
||
applicationId: {
|
||
$in: apps.map(ele => ele.id),
|
||
},
|
||
userId,
|
||
}
|
||
}, { dontCollect: true });
|
||
for (const app of apps) {
|
||
// 如果是wechatMp或者wechat,还要保证用户已经有openId
|
||
const wechatUser = wechatUsers.find(ele => ele.applicationId === app.id);
|
||
const messageTypeTemplate = messageTypeTemplates.find(ele => ele.template.applicationId === app.id && ele.type === type);
|
||
if (messageTypeTemplate && wechatUser) {
|
||
const converter = ConverterDict[type] && ConverterDict[type].toWechatMp;
|
||
const dispersedData = converter &&
|
||
(await converter(message, apps, app, context));
|
||
if (dispersedData) {
|
||
notificationDatas.push({
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
data: dispersedData,
|
||
channel,
|
||
applicationId: app.id,
|
||
templateId: messageTypeTemplate.template.wechatId,
|
||
data1: {
|
||
openId: wechatUser.openId,
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case 'wechatPublic': {
|
||
const apps = applications.filter(ele => ele.type === 'wechatPublic');
|
||
const [user] = await context.select('user', {
|
||
data: {
|
||
id: 1,
|
||
refId: 1,
|
||
},
|
||
filter: {
|
||
id: userId
|
||
}
|
||
}, { dontCollect: true });
|
||
const userIds = user.refId ? [userId, user.refId] : [userId];
|
||
const wechatUsers = await context.select('wechatUser', {
|
||
data: {
|
||
id: 1,
|
||
applicationId: 1,
|
||
openId: 1,
|
||
},
|
||
filter: {
|
||
applicationId: {
|
||
$in: apps.map((ele) => ele.id),
|
||
},
|
||
userId: {
|
||
$in: userIds
|
||
},
|
||
},
|
||
}, { dontCollect: true });
|
||
for (const app of apps) {
|
||
// 如果是wechatMp或者wechat,还要保证用户已经有openId
|
||
const wechatUser = wechatUsers.find(ele => ele.applicationId === app.id);
|
||
const messageTypeTemplate = messageTypeTemplates.find(ele => ele.template.applicationId === app.id && ele.type === type);
|
||
if (messageTypeTemplate && wechatUser) {
|
||
const converter = ConverterDict[type] && ConverterDict[type].toWechatPublic;
|
||
const disperseResult = converter &&
|
||
(await converter(message, apps, app, context));
|
||
if (disperseResult) {
|
||
const { data, wechatMpAppId } = disperseResult;
|
||
notificationDatas.push({
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
data,
|
||
channel,
|
||
applicationId: app.id,
|
||
templateId: messageTypeTemplate.template.wechatId,
|
||
data1: {
|
||
openId: wechatUser.openId,
|
||
wechatMpAppId,
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case 'email': {
|
||
const emailNotification = await tryMakeEmailNotification(message, context);
|
||
if (emailNotification) {
|
||
notificationDatas.push(emailNotification);
|
||
}
|
||
break;
|
||
}
|
||
default: {
|
||
(0, assert_1.assert)(channel === 'sms'); // 目前只支持三种
|
||
const smsNotification = await tryMakeSmsNotification(message, context);
|
||
if (smsNotification) {
|
||
notificationDatas.push(smsNotification);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}));
|
||
const messageSystemData = {
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
messageId: message.id,
|
||
systemId: system.id,
|
||
};
|
||
if (notificationDatas.length > 0) {
|
||
messageSentCount += notificationDatas.length;
|
||
messageSystemData.notification$messageSystem = [
|
||
{
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
action: 'create',
|
||
data: notificationDatas,
|
||
}
|
||
];
|
||
}
|
||
messageSystemDatas.push(messageSystemData);
|
||
}));
|
||
if (messageSystemDatas.length > 0) {
|
||
message.messageSystem$message = [
|
||
{
|
||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||
action: 'create',
|
||
data: messageSystemDatas,
|
||
}
|
||
];
|
||
}
|
||
message.iState = messageSentCount ? 'sending' : 'failure';
|
||
return messageSentCount;
|
||
}
|
||
const triggers = [
|
||
{
|
||
name: '当创建message时,创建相应的通知数据',
|
||
entity: 'message',
|
||
action: 'create',
|
||
when: 'before',
|
||
fn: async ({ operation }, context, params) => {
|
||
const { data } = operation;
|
||
let count = 0;
|
||
const closeRootMode = context.openRootMode();
|
||
try {
|
||
if (data instanceof Array) {
|
||
for (const d of data) {
|
||
count += await createNotification(d, context);
|
||
}
|
||
}
|
||
else {
|
||
count = await createNotification(data, context);
|
||
}
|
||
}
|
||
catch (err) {
|
||
closeRootMode();
|
||
throw err;
|
||
}
|
||
closeRootMode();
|
||
return count;
|
||
}
|
||
},
|
||
];
|
||
exports.default = triggers;
|