@abtnode/blocklet-services 1.16.39-beta-20250215-130252-43410928 → 1.16.39-beta-20250218-110004-a308c501
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/index.js +6 -2
- package/api/libs/email.js +2 -2
- package/api/services/notification/index.js +4 -2
- package/api/services/notification/notification-queue.js +671 -0
- package/api/socket/channel/did.js +146 -473
- package/dist/assets/{Add-TglZpKpw.js → Add-eTw9dWVa.js} +1 -1
- package/dist/assets/{ArrowDropDown-DCM27ed6.js → ArrowDropDown-D-RD-2MB.js} +1 -1
- package/dist/assets/{CheckCircle-CH8SYy4d.js → CheckCircle-fnIa_Tjy.js} +1 -1
- package/dist/assets/{ChevronLeft-B7m8AFzR.js → ChevronLeft-B6BBtJvf.js} +1 -1
- package/dist/assets/{ChevronRight-DeRklga5.js → ChevronRight-BO6iBxGF.js} +1 -1
- package/dist/assets/{DeleteOutline-DZA1YKE4.js → DeleteOutline-6B6Fe5fo.js} +1 -1
- package/dist/assets/{Done-CVdTMvGH.js → Done-BpK9makc.js} +1 -1
- package/dist/assets/{Download-DECMRaRC.js → Download-CHVAgVy8.js} +1 -1
- package/dist/assets/{Error-B61ZB0Rr.js → Error-kGbi4Zxj.js} +1 -1
- package/dist/assets/{Google-D_UbrpMW.js → Google-T-9fe6qI.js} +1 -1
- package/dist/assets/{InfoOutlined-QBw5AmWP.js → InfoOutlined-BgLmQpjA.js} +1 -1
- package/dist/assets/{Launch-Cpp3LVnV.js → Launch-C9zEVLvk.js} +1 -1
- package/dist/assets/{LaunchOutlined-WdAKKV2H.js → LaunchOutlined-Cql1NmZZ.js} +1 -1
- package/dist/assets/{Loop-CbPhaPlF.js → Loop-CawJEzLG.js} +1 -1
- package/dist/assets/{MoreHoriz-BsTY94ce.js → MoreHoriz-M9rI-Gh1.js} +1 -1
- package/dist/assets/{PlayArrow-BgVzxA9Q.js → PlayArrow-BAowUCpY.js} +1 -1
- package/dist/assets/{ViewList-DBUe2NSG.js → ViewList-BPtSTNst.js} +1 -1
- package/dist/assets/{access-control-DeqFMOm5.js → access-control-DEUU0fDz.js} +1 -1
- package/dist/assets/{actions-DP_Rm54e.js → actions-wYAFmtYW.js} +1 -1
- package/dist/assets/{add-component-core-BnP0_g-C.js → add-component-core-C36Oh0S_.js} +1 -1
- package/dist/assets/{add-resource-B26HHRU4.js → add-resource-Xm48tGBR.js} +1 -1
- package/dist/assets/{addon-DH34oI6i.js → addon-DJRfOF39.js} +1 -1
- package/dist/assets/{analytics-DPn53GmC.js → analytics-BxMLe4sZ.js} +1 -1
- package/dist/assets/{ar-BJD4HTM3.js → ar-BFUPmTkR.js} +1 -1
- package/dist/assets/{audit-logs-C1oUmr2S.js → audit-logs-QI7Dc290.js} +1 -1
- package/dist/assets/{base32-CwwDjweV.js → base32-BMSr-Oor.js} +1 -1
- package/dist/assets/{branding-DFfBkuOI.js → branding-BiBArxE7.js} +2 -2
- package/dist/assets/{bundle-avatar-Cv2R2iWI.js → bundle-avatar-CcKbW8ZA.js} +1 -1
- package/dist/assets/{button-4qfNeG4u.js → button-hN0nkg5h.js} +1 -1
- package/dist/assets/{click-to-copy-886R1sA9.js → click-to-copy-DlRwVMBE.js} +1 -1
- package/dist/assets/{complete-Cz6Vt9yr.js → complete-BCHhjgui.js} +2 -2
- package/dist/assets/{component-BOGOOyWw.js → component---BohhtR.js} +1 -1
- package/dist/assets/{config-BBRmjpUL.js → config-BT7DA9eX.js} +1 -1
- package/dist/assets/{config-CE9eJ5Ce.js → config-Chtg5c7S.js} +1 -1
- package/dist/assets/{config-navigation-ZGyHDU_V.js → config-navigation-DGQXESo8.js} +3 -3
- package/dist/assets/config-space-D3_ddjoK.js +1 -0
- package/dist/assets/{confirm-f60NfF3X.js → confirm-BUf2FX6y.js} +1 -1
- package/dist/assets/{connect-D9S16wyT.js → connect-9ktVrhs9.js} +1 -1
- package/dist/assets/{connect-B2VVyCQY.js → connect-Bg1fiX7Q.js} +1 -1
- package/dist/assets/{connect-to-BSmtnPV9.js → connect-to-6-yxL1od.js} +1 -1
- package/dist/assets/{dashboard-BoV1-CrH.js → dashboard-CRO3eTt1.js} +4 -4
- package/dist/assets/{de-CaPBInxb.js → de-hV0yD3gq.js} +1 -1
- package/dist/assets/{did-address-CgDvtQbT.js → did-address-Rncailh0.js} +1 -1
- package/dist/assets/{domain-DLGsAByD.js → domain-CiQ58Nbb.js} +1 -1
- package/dist/assets/{domain-list-BLV11Y6_.js → domain-list-DlMnYtcT.js} +2 -2
- package/dist/assets/{email-Fgr58FLV.js → email-C7B2iQRL.js} +1 -1
- package/dist/assets/{es-hhXhgxGX.js → es-BcSAobJW.js} +1 -1
- package/dist/assets/{exchange-passport-CcsLEfpo.js → exchange-passport-DvgnrFhH.js} +1 -1
- package/dist/assets/{form-text-input-CbMAGh7u.js → form-text-input-B3XB3R1O.js} +1 -1
- package/dist/assets/{fr-BwQvAhhM.js → fr-8qti32p1.js} +1 -1
- package/dist/assets/{fuel-B8r20ueU.js → fuel-De_bc9rw.js} +1 -1
- package/dist/assets/{fullpage-DLk_Ap1u.js → fullpage-ClwEgpoB.js} +1 -1
- package/dist/assets/{get-safe-url-BzE2b8Zw.js → get-safe-url-3FtlbQXR.js} +1 -1
- package/dist/assets/{get-safe-url-C2hTfmjV.js → get-safe-url-DgnUmHPg.js} +1 -1
- package/dist/assets/{hi-CRWmR5oy.js → hi-DDEUhQcX.js} +1 -1
- package/dist/assets/{home-B30MMEWW.js → home-s4XxyP6G.js} +1 -1
- package/dist/assets/{id-Dlr6Q1sk.js → id-DkUYINLx.js} +1 -1
- package/dist/assets/{iframe-DvysnY8O.js → iframe-DkAOGH82.js} +1 -1
- package/dist/assets/{index-r2Lf0YIw.js → index-AKILhCB1.js} +46 -46
- package/dist/assets/{index-CM-Ew9KZ.js → index-BM6MW3P4.js} +1 -1
- package/dist/assets/{index-C-yw0A3M.js → index-BQD1ktrC.js} +1 -1
- package/dist/assets/{index-V7v6XM-s.js → index-BuAHCrPZ.js} +1 -1
- package/dist/assets/{index-EDdyNc1F.js → index-C3Z6Hby2.js} +1 -1
- package/dist/assets/{index-j5s7Rpz_.js → index-C3cP3eho.js} +1 -1
- package/dist/assets/{index-B4_ve2gt.js → index-CKmE0Sqg.js} +1 -1
- package/dist/assets/index-CctdI8X8.js +125 -0
- package/dist/assets/{index-EIsfexf1.js → index-DEkiPG8Y.js} +1 -1
- package/dist/assets/{index-uSZNIR4c.js → index-DFzh5oL0.js} +1 -1
- package/dist/assets/index-DiLNptzT.js +5 -0
- package/dist/assets/{index-DFM7u7wl.js → index-IC1Rf7BW.js} +1 -1
- package/dist/assets/{index-B6CyLMos.js → index-Pdt8JY75.js} +1 -1
- package/dist/assets/{index-RoF9rzF3.js → index-XjSUrEf9.js} +1 -1
- package/dist/assets/{index-U8kTDDEm.js → index-vSb5bw1I.js} +4 -4
- package/dist/assets/{invitation-ZW3n52Yc.js → invitation-398ugOww.js} +1 -1
- package/dist/assets/{invite-B8cpjqrT.js → invite-CxctjCks.js} +1 -1
- package/dist/assets/{issue-passport-DrbTLcdD.js → issue-passport-BzEXCFP0.js} +1 -1
- package/dist/assets/{item-BVrq9ZQD.js → item-BzigISWG.js} +1 -1
- package/dist/assets/{ja-CmKylH6K.js → ja-C2LP4WQG.js} +1 -1
- package/dist/assets/{ko-Blp8936a.js → ko-C-DMeONa.js} +1 -1
- package/dist/assets/{layout-Dw2Qx7hs.js → layout-N5xbN7Ti.js} +1 -1
- package/dist/assets/{list-BwH5q_Zc.js → list-QwzSO7Cs.js} +1 -1
- package/dist/assets/{list-header-BBHpD8dC.js → list-header-bKaZ4zsu.js} +1 -1
- package/dist/assets/{localization-Ciwo-y3M.js → localization-CNvFSQc0.js} +1 -1
- package/dist/assets/{log-Ba7iTEJj.js → log-Bz9TkxcV.js} +1 -1
- package/dist/assets/{login-BewdlPwi.js → login-DbJD9Sgu.js} +1 -1
- package/dist/assets/{login-oauth-callback-D_bP2yYx.js → login-oauth-callback-BagCPt1j.js} +1 -1
- package/dist/assets/{logo-uploader-CneV6CnS.js → logo-uploader-QnBnkpOO.js} +3 -3
- package/dist/assets/{lost-passport-CNuZ281r.js → lost-passport-se4N22vE.js} +1 -1
- package/dist/assets/{open-window-Q0PVNWdu.js → open-window-BWPlSJZK.js} +1 -1
- package/dist/assets/{overview-giDiT6rf.js → overview-u84fbCZU.js} +1 -1
- package/dist/assets/{page-header-BDwGXuEW.js → page-header-CVCtfFXY.js} +1 -1
- package/dist/assets/{permission-Cqed8iP-.js → permission-CoRqvd18.js} +1 -1
- package/dist/assets/{preferences-CBm0eML7.js → preferences-CCm3JuB9.js} +1 -1
- package/dist/assets/{pt-BbwAvpfn.js → pt-CbxvF__Z.js} +1 -1
- package/dist/assets/publish-resource-Cmlpn7H3.js +1 -0
- package/dist/assets/{react-beautiful-dnd.esm-BTWrOgJp.js → react-beautiful-dnd.esm-CrvlS-3X.js} +1 -1
- package/dist/assets/{relative-time-Bt6RtG4o.js → relative-time-IDiRzYUd.js} +1 -1
- package/dist/assets/{ru-DgfLeWul.js → ru-DLHrAeE7.js} +1 -1
- package/dist/assets/sdk-DRntvOGy.js +1 -0
- package/dist/assets/{session-BKdZFtFw.js → session-BzY_i5lZ.js} +1 -1
- package/dist/assets/{setup-BdFkCCIb.js → setup-CFL-k7o4.js} +3 -3
- package/dist/assets/{start-Cy0MNYb6.js → start-Bnol7r-4.js} +1 -1
- package/dist/assets/{step-actions-CPEQpBG3.js → step-actions-vFuOlgmX.js} +1 -1
- package/dist/assets/{studio-BzK2t7MU.js → studio-D8dNrjXX.js} +1 -1
- package/dist/assets/{switch-control-BSKk9hbF.js → switch-control-DTOAJIEb.js} +1 -1
- package/dist/assets/{th-DXRi_ppC.js → th-Dil9kwjH.js} +1 -1
- package/dist/assets/{traffic-BQRcq8gg.js → traffic-C-Or__6J.js} +1 -1
- package/dist/assets/{transfer-DhNfOwE1.js → transfer-tWhnvLV8.js} +1 -1
- package/dist/assets/{unsubscribe-C0PztwA5.js → unsubscribe-8PpNeEGq.js} +1 -1
- package/dist/assets/{useLocalStorage-Bx8dJwZw.js → useLocalStorage-DDsWbihG.js} +1 -1
- package/dist/assets/{user-center-BshF32Jc.js → user-center-FVVJclAc.js} +1 -1
- package/dist/assets/{util-BPubgk5p.js → util-CqwLA_zk.js} +1 -1
- package/dist/assets/{util-CWVLbRLp.js → util-DfAqJble.js} +1 -1
- package/dist/assets/{vendor-arcblock-HzAExiTd.js → vendor-arcblock-naCuSDgJ.js} +5 -5
- package/dist/assets/{vi-nO7JrO24.js → vi-B46hyfUM.js} +1 -1
- package/dist/assets/wrap-locale-JORvcC3E.js +1 -0
- package/dist/assets/{zh-CEvYioAt.js → zh-DWWuPzr1.js} +1 -1
- package/dist/assets/{zh-tw-BjfRYnXu.js → zh-tw-Ci21sS2Y.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/service-worker.js +1 -1
- package/package.json +24 -24
- package/dist/assets/config-space-Bgt2MtPU.js +0 -1
- package/dist/assets/index-4zAH1uuX.js +0 -5
- package/dist/assets/index-BkZLaapf.js +0 -123
- package/dist/assets/publish-resource-CQLawfAh.js +0 -1
- package/dist/assets/sdk-B4wNFenI.js +0 -1
- package/dist/assets/wrap-locale-DrPh3OVK.js +0 -1
|
@@ -1,31 +1,34 @@
|
|
|
1
|
-
const {
|
|
2
|
-
validateReceiver,
|
|
3
|
-
validateNotification,
|
|
4
|
-
validateMessage,
|
|
5
|
-
NOTIFICATION_TYPES,
|
|
6
|
-
} = require('@blocklet/sdk/lib/validators/notification');
|
|
1
|
+
const { validateNotification, validateMessage } = require('@blocklet/sdk/lib/validators/notification');
|
|
7
2
|
const { Joi } = require('@arcblock/validator');
|
|
8
|
-
const {
|
|
9
|
-
|
|
3
|
+
const {
|
|
4
|
+
NODE_MODES,
|
|
5
|
+
NOTIFICATION_SEND_STATUS,
|
|
6
|
+
NOTIFICATION_SEND_FAILED_REASON,
|
|
7
|
+
NOTIFICATION_SEND_CHANNEL,
|
|
8
|
+
} = require('@abtnode/constant');
|
|
10
9
|
const JWT = require('@arcblock/jwt');
|
|
11
|
-
const pMap = require('p-map');
|
|
12
|
-
const uniqBy = require('lodash/uniqBy');
|
|
13
10
|
const uniq = require('lodash/uniq');
|
|
14
|
-
const get = require('lodash/get');
|
|
15
|
-
const pLimit = require('p-limit');
|
|
16
11
|
|
|
17
12
|
const logger = require('../../libs/logger')('notification');
|
|
18
|
-
const { ensureSenderApp, getSenderServer, parseNotification,
|
|
13
|
+
const { ensureSenderApp, getSenderServer, parseNotification, EVENTS } = require('../util');
|
|
19
14
|
const states = require('../../state');
|
|
20
|
-
const {
|
|
15
|
+
const { sendEmail } = require('../../libs/email');
|
|
21
16
|
const { sendPush } = require('../../libs/push-kit');
|
|
22
|
-
const { getBlockletInfo } = require('../../cache');
|
|
23
|
-
const { nanoid } = require('../../util');
|
|
24
17
|
|
|
25
18
|
const CHANNEL_FIELD_MAP = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
[NOTIFICATION_SEND_CHANNEL.WALLET]: [
|
|
20
|
+
'walletSendStatus',
|
|
21
|
+
'walletSendAt',
|
|
22
|
+
'walletSendFailedReason',
|
|
23
|
+
'walletSendRecord',
|
|
24
|
+
],
|
|
25
|
+
[NOTIFICATION_SEND_CHANNEL.PUSH]: [
|
|
26
|
+
'pushKitSendStatus',
|
|
27
|
+
'pushKitSendAt',
|
|
28
|
+
'pushKitSendFailedReason',
|
|
29
|
+
'pushKitSendRecord',
|
|
30
|
+
],
|
|
31
|
+
[NOTIFICATION_SEND_CHANNEL.EMAIL]: ['emailSendStatus', 'emailSendAt', 'emailSendFailedReason', 'emailSendRecord'],
|
|
29
32
|
};
|
|
30
33
|
|
|
31
34
|
const updateNotificationSendStatus = async ({
|
|
@@ -41,7 +44,7 @@ const updateNotificationSendStatus = async ({
|
|
|
41
44
|
if (!node || !notificationId || !receivers.length) {
|
|
42
45
|
return undefined;
|
|
43
46
|
}
|
|
44
|
-
if (channel ===
|
|
47
|
+
if (channel === NOTIFICATION_SEND_CHANNEL.WEBHOOK && Object.keys(webhookParams).length > 0) {
|
|
45
48
|
const updateParams = {
|
|
46
49
|
receivers,
|
|
47
50
|
teamDid,
|
|
@@ -100,427 +103,86 @@ const updateNotificationSendStatus = async ({
|
|
|
100
103
|
* @param {ABTNode} options.node
|
|
101
104
|
* @param {WsServer} options.wsServer
|
|
102
105
|
*/
|
|
103
|
-
const sendToUserDid = async ({ sender, receiver: rawDid, notification, options, node
|
|
106
|
+
const sendToUserDid = async ({ sender, receiver: rawDid, notification, options, node }) => {
|
|
104
107
|
// FIXME: @zhanghan 默认不应该有 push(仅在测试阶段加上),后期需要移除
|
|
105
|
-
const {
|
|
108
|
+
const { channels = ['app', 'email', 'webhook', 'push'], ...rest } = options || {};
|
|
109
|
+
|
|
106
110
|
if (channels.length === 0) {
|
|
107
111
|
return;
|
|
108
112
|
}
|
|
109
|
-
|
|
110
|
-
const teamDid = notification?.appInfo?.did || sender.appDid;
|
|
111
|
-
|
|
112
|
-
// 要判断是否是 role Did
|
|
113
|
-
const userDids = Array.isArray(rawDid) ? rawDid : [rawDid];
|
|
114
|
-
|
|
115
|
-
const receivers = await node.getNotificationReceivers({ teamDid, userDids, enableConnectedAccounts: true });
|
|
116
|
-
const receiver = receivers.map((r) => r.did);
|
|
117
|
-
|
|
118
|
-
let receiverPushDidList = [];
|
|
119
|
-
let notEnabledPushReceiverList = [];
|
|
120
|
-
let receiverAppDidList = [];
|
|
121
|
-
let notEnabledAppReceiverList = [];
|
|
122
|
-
let receiverEmailList = [];
|
|
123
|
-
let notEnabledEmailReceiverList = [];
|
|
124
|
-
let webhookList = [];
|
|
125
|
-
|
|
126
|
-
const webhookSenders = new Map();
|
|
127
|
-
|
|
128
|
-
await pMap(receivers, async (user) => {
|
|
129
|
-
const walletEnabled = get(user, 'extra.notifications.wallet', true);
|
|
130
|
-
const emailEnabled = get(user, 'extra.notifications.email', true);
|
|
131
|
-
const pushEnabled = get(user, 'extra.notifications.push', true);
|
|
132
|
-
const webhooks = get(user, 'extra.webhooks', []);
|
|
133
|
-
|
|
134
|
-
const receiverDid = getWalletDid(user) || user.did;
|
|
135
|
-
const receiverEmail = user?.email;
|
|
136
|
-
if (!walletEnabled) {
|
|
137
|
-
notEnabledAppReceiverList.push(receiverDid);
|
|
138
|
-
}
|
|
139
|
-
if (!pushEnabled) {
|
|
140
|
-
notEnabledPushReceiverList.push(receiverDid);
|
|
141
|
-
}
|
|
142
|
-
if (!emailEnabled) {
|
|
143
|
-
notEnabledEmailReceiverList.push(receiverDid);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (receiverDid && (walletEnabled || pushEnabled)) {
|
|
147
|
-
try {
|
|
148
|
-
await validateReceiver(receiverDid);
|
|
149
|
-
if (walletEnabled) {
|
|
150
|
-
receiverAppDidList.push(receiverDid);
|
|
151
|
-
}
|
|
152
|
-
if (pushEnabled) {
|
|
153
|
-
receiverPushDidList.push(receiverDid);
|
|
154
|
-
}
|
|
155
|
-
} catch (error) {
|
|
156
|
-
logger.error(`Skip invalid did receiver: ${receiverDid}`, { error });
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (receiverEmail && emailEnabled) {
|
|
160
|
-
try {
|
|
161
|
-
await validateEmail(receiverEmail);
|
|
162
|
-
receiverEmailList.push({
|
|
163
|
-
email: receiverEmail,
|
|
164
|
-
locale: user?.locale || 'en',
|
|
165
|
-
did: receiverDid,
|
|
166
|
-
fullName: user?.fullName,
|
|
167
|
-
avatar: user?.avatar,
|
|
168
|
-
});
|
|
169
|
-
} catch (error) {
|
|
170
|
-
logger.error(`Skip invalid email receiver: ${receiverEmail}`, { error });
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
notEnabledEmailReceiverList.push(receiverDid);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (Array.isArray(webhooks)) {
|
|
177
|
-
webhookList.push(...webhooks.filter((x) => x.type && x.url));
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
receiverAppDidList.length === 0 &&
|
|
183
|
-
receiverEmailList.length === 0 &&
|
|
184
|
-
receiverPushDidList.length === 0 &&
|
|
185
|
-
webhookList.length === 0
|
|
186
|
-
) {
|
|
187
|
-
throw new Error('Invalid receiver');
|
|
188
|
-
}
|
|
113
|
+
const teamDid = sender.appDid;
|
|
189
114
|
|
|
190
115
|
const nodeInfo = await node.getNodeInfo({ useCache: true });
|
|
191
116
|
|
|
192
|
-
const isServer = teamDid === nodeInfo.did;
|
|
193
|
-
|
|
194
117
|
if (nodeInfo.mode !== NODE_MODES.DEBUG) {
|
|
195
|
-
|
|
118
|
+
try {
|
|
119
|
+
await validateNotification(notification);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
logger.error('Failed to validate notification', { error });
|
|
122
|
+
// 抛出错误,阻止后续执行
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
196
125
|
}
|
|
197
126
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
// parse notification
|
|
202
|
-
const notifications = parseNotification(notification, senderInfo);
|
|
203
|
-
|
|
204
|
-
// uniq receivers
|
|
205
|
-
receiverPushDidList = uniq(receiverPushDidList);
|
|
206
|
-
receiverAppDidList = uniq(receiverAppDidList);
|
|
207
|
-
receiverEmailList = uniqBy(receiverEmailList, 'email');
|
|
208
|
-
webhookList = uniqBy(webhookList, 'url');
|
|
209
|
-
|
|
210
|
-
notEnabledAppReceiverList = uniq(notEnabledAppReceiverList);
|
|
211
|
-
notEnabledPushReceiverList = uniq(notEnabledPushReceiverList);
|
|
212
|
-
notEnabledEmailReceiverList = uniq(notEnabledEmailReceiverList);
|
|
213
|
-
|
|
214
|
-
const disabledChannelReceivers = [
|
|
215
|
-
[notEnabledAppReceiverList, 'wallet'],
|
|
216
|
-
[notEnabledPushReceiverList, 'pushKit'],
|
|
217
|
-
[notEnabledEmailReceiverList, 'email'],
|
|
218
|
-
];
|
|
219
|
-
|
|
220
|
-
let wallet;
|
|
221
|
-
|
|
222
|
-
if (sender.type !== 'server') {
|
|
223
|
-
const blockletInfo = await getBlockletInfo({ did: teamDid, node });
|
|
224
|
-
wallet = blockletInfo.wallet;
|
|
127
|
+
if (!sender.token) {
|
|
128
|
+
throw new Error('Invalid sender: token empty');
|
|
225
129
|
}
|
|
226
130
|
|
|
227
|
-
const
|
|
131
|
+
const notifications = Array.isArray(notification) ? notification : [notification];
|
|
228
132
|
|
|
229
|
-
// send notification
|
|
230
133
|
await Promise.all(
|
|
231
|
-
notifications.map(
|
|
232
|
-
|
|
233
|
-
const isSaveSkipped = data.type?.toLowerCase() === 'passthrough';
|
|
234
|
-
if (data.id && !isSaveSkipped) {
|
|
235
|
-
doc = await node.getNotificationById({
|
|
236
|
-
teamDid: _teamDid,
|
|
237
|
-
id: data.id,
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
if (!data.id && !isServer && sender.type !== 'server' && !isSaveSkipped) {
|
|
241
|
-
doc = await node.createNotification({
|
|
242
|
-
teamDid,
|
|
243
|
-
...data,
|
|
244
|
-
receiver,
|
|
245
|
-
componentDid: sender.componentDid,
|
|
246
|
-
// 这两个字段用于 socket 通知
|
|
247
|
-
entityType: 'blocklet',
|
|
248
|
-
entityId: sender.appDid,
|
|
249
|
-
source: 'component',
|
|
250
|
-
ignorePush: true,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// 为消息添加一个ID,wallet钱包接受消息会使用这个字段
|
|
255
|
-
data.id = data.id || doc?.id || nanoid();
|
|
256
|
-
const commonParams = {
|
|
257
|
-
node,
|
|
258
|
-
teamDid: _teamDid,
|
|
259
|
-
notificationId: doc?.id,
|
|
260
|
-
};
|
|
134
|
+
notifications.map((_notification) => {
|
|
135
|
+
const pushOnly = ['passthrough', 'connect', 'hi'].includes(_notification.type?.toLowerCase());
|
|
261
136
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
137
|
+
return node.createNotification({
|
|
138
|
+
teamDid,
|
|
139
|
+
notification: _notification,
|
|
140
|
+
receiver: rawDid,
|
|
141
|
+
componentDid: sender.componentDid,
|
|
142
|
+
// 这两个字段用于 socket 通知
|
|
143
|
+
entityType: notification.entityType || 'blocklet',
|
|
144
|
+
entityId: notification.entityId || sender.appDid,
|
|
145
|
+
source: notification.source || 'component',
|
|
146
|
+
channels,
|
|
147
|
+
sender,
|
|
148
|
+
options: { ...rest },
|
|
149
|
+
pushOnly,
|
|
272
150
|
});
|
|
273
|
-
|
|
274
|
-
// 发送钱包消息
|
|
275
|
-
if (channels.includes('app')) {
|
|
276
|
-
for (const receiverDid of receiverAppDidList) {
|
|
277
|
-
broadcast(wsServer, receiverDid, EVENTS.MESSAGE, data, async (count) => {
|
|
278
|
-
if (count <= 0 && keepForOfflineUser) {
|
|
279
|
-
logger.error('Online client was not found', { userDid: receiverDid });
|
|
280
|
-
await states.message.insert({ did: receiverDid, event: EVENTS.MESSAGE, data });
|
|
281
|
-
updateNotificationSendStatus({
|
|
282
|
-
...commonParams,
|
|
283
|
-
receivers: [receiverDid],
|
|
284
|
-
channel: 'wallet',
|
|
285
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
286
|
-
failedReason: NOTIFICATION_SEND_FAILED_REASON.NOT_ONLINE,
|
|
287
|
-
});
|
|
288
|
-
} else {
|
|
289
|
-
updateNotificationSendStatus({
|
|
290
|
-
...commonParams,
|
|
291
|
-
receivers: [receiverDid],
|
|
292
|
-
channel: 'wallet',
|
|
293
|
-
status: NOTIFICATION_SEND_STATUS.SENT,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
} else {
|
|
299
|
-
updateNotificationSendStatus({
|
|
300
|
-
...commonParams,
|
|
301
|
-
receivers: receiverAppDidList,
|
|
302
|
-
channel: 'wallet',
|
|
303
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
304
|
-
failedReason: NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (channels.includes('push')) {
|
|
309
|
-
// 发送 pushKit
|
|
310
|
-
// 目前保持发送消息跟钱包能收到的消息是一致的(会包含组件的启停通知)
|
|
311
|
-
sendPush(receiverPushDidList, data, { teamDid, node })
|
|
312
|
-
.then((res) => {
|
|
313
|
-
updateNotificationSendStatus({
|
|
314
|
-
...commonParams,
|
|
315
|
-
receivers: receiverPushDidList,
|
|
316
|
-
channel: 'pushKit',
|
|
317
|
-
status: res ? NOTIFICATION_SEND_STATUS.SENT : NOTIFICATION_SEND_STATUS.FAILED,
|
|
318
|
-
failedReason: res ? null : NOTIFICATION_SEND_FAILED_REASON.CHANNEL_UNAVAILABLE,
|
|
319
|
-
});
|
|
320
|
-
})
|
|
321
|
-
.catch((err) => {
|
|
322
|
-
// 即使失败也不应该导致程序异常,还是需要发送其他渠道
|
|
323
|
-
logger.error('Failed to send pushKit', { error: err });
|
|
324
|
-
updateNotificationSendStatus({
|
|
325
|
-
...commonParams,
|
|
326
|
-
receivers: receiverPushDidList,
|
|
327
|
-
channel: 'pushKit',
|
|
328
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
329
|
-
failedReason: err.message,
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
} else {
|
|
333
|
-
updateNotificationSendStatus({
|
|
334
|
-
...commonParams,
|
|
335
|
-
receivers: receiverPushDidList,
|
|
336
|
-
channel: 'pushKit',
|
|
337
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
338
|
-
failedReason: NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED,
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// Do not send email for component activities
|
|
343
|
-
// server 的通知暂不支持发送邮箱
|
|
344
|
-
// 不建议通过这种方式禁止发送消息,要根据传入的 channel 判断
|
|
345
|
-
if (data.source !== 'app' && sender.type !== 'server') {
|
|
346
|
-
// 发送邮件消息
|
|
347
|
-
// NOTICE: 目前只有 notification 的通知能够发送邮件,并且 type 可能为 undefined
|
|
348
|
-
if (channels.includes('email')) {
|
|
349
|
-
if ([undefined, NOTIFICATION_TYPES.NOTIFICATION].includes(data.type)) {
|
|
350
|
-
const limit = pLimit(10);
|
|
351
|
-
const sendEmailList = receiverEmailList.map((receiverItem) => {
|
|
352
|
-
return limit(async () => {
|
|
353
|
-
try {
|
|
354
|
-
const now = Math.floor(Date.now() / 1000);
|
|
355
|
-
const userDid = receiverItem?.did;
|
|
356
|
-
const unsubscribeToken = userDid
|
|
357
|
-
? JWT.signV2(wallet.address, wallet.secretKey, {
|
|
358
|
-
userDid,
|
|
359
|
-
channel: 'email',
|
|
360
|
-
// 30 days
|
|
361
|
-
exp: String(now + 30 * 24 * 60 * 60),
|
|
362
|
-
})
|
|
363
|
-
: null;
|
|
364
|
-
const res = await sendEmail(receiverItem.email, data, {
|
|
365
|
-
teamDid,
|
|
366
|
-
node,
|
|
367
|
-
locale: receiverItem.locale,
|
|
368
|
-
unsubscribeToken,
|
|
369
|
-
userInfo: {
|
|
370
|
-
did: userDid,
|
|
371
|
-
fullName: receiverItem.fullName,
|
|
372
|
-
// NOTICE: 将来可能还需要头像,先保留该代码
|
|
373
|
-
// avatar: getUserAvatarUrl(receiverItem.avatar, blocklet),
|
|
374
|
-
},
|
|
375
|
-
});
|
|
376
|
-
updateNotificationSendStatus({
|
|
377
|
-
...commonParams,
|
|
378
|
-
receivers: [userDid],
|
|
379
|
-
channel: 'email',
|
|
380
|
-
status: res ? NOTIFICATION_SEND_STATUS.SENT : NOTIFICATION_SEND_STATUS.FAILED,
|
|
381
|
-
failedReason: res ? null : NOTIFICATION_SEND_FAILED_REASON.CHANNEL_UNAVAILABLE,
|
|
382
|
-
});
|
|
383
|
-
} catch (error) {
|
|
384
|
-
logger.error('Failed to send email');
|
|
385
|
-
updateNotificationSendStatus({
|
|
386
|
-
...commonParams,
|
|
387
|
-
receivers: [receiverItem?.did],
|
|
388
|
-
channel: 'email',
|
|
389
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
390
|
-
failedReason: error.message,
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
});
|
|
394
|
-
});
|
|
395
|
-
Promise.all(sendEmailList);
|
|
396
|
-
}
|
|
397
|
-
} else {
|
|
398
|
-
updateNotificationSendStatus({
|
|
399
|
-
...commonParams,
|
|
400
|
-
receivers: receiverEmailList.map((item) => item.did),
|
|
401
|
-
channel: 'email',
|
|
402
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
403
|
-
failedReason: NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED,
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
if (channels.includes('webhook') && !isSaveSkipped) {
|
|
408
|
-
// 发送 webhook
|
|
409
|
-
for (const webhook of webhookList) {
|
|
410
|
-
let webhookSender = webhookSenders.get(webhook.type);
|
|
411
|
-
if (!webhookSender) {
|
|
412
|
-
webhookSender = node.getMessageSender(webhook.type);
|
|
413
|
-
webhookSenders.set(webhook.type, webhookSender);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
const webhookParams = {
|
|
417
|
-
[webhook.url]: {
|
|
418
|
-
type: webhook.type ?? 'api',
|
|
419
|
-
sendAt: new Date(),
|
|
420
|
-
},
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
webhookSender
|
|
424
|
-
.sendNotification(webhook.url, data)
|
|
425
|
-
.then((res) => {
|
|
426
|
-
webhookParams[webhook.url] = {
|
|
427
|
-
...webhookParams[webhook.url],
|
|
428
|
-
status: res ? NOTIFICATION_SEND_STATUS.SENT : NOTIFICATION_SEND_STATUS.FAILED,
|
|
429
|
-
failedReason: res ? '' : NOTIFICATION_SEND_FAILED_REASON.CHANNEL_UNAVAILABLE,
|
|
430
|
-
};
|
|
431
|
-
updateNotificationSendStatus({
|
|
432
|
-
...commonParams,
|
|
433
|
-
receivers: receivers.map((item) => item.did),
|
|
434
|
-
channel: 'webhook',
|
|
435
|
-
webhookParams,
|
|
436
|
-
});
|
|
437
|
-
})
|
|
438
|
-
.catch((err) => {
|
|
439
|
-
logger.error('Failed to send webhook', { error: err });
|
|
440
|
-
webhookParams[webhook.url] = {
|
|
441
|
-
...webhookParams[webhook.url],
|
|
442
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
443
|
-
failedReason: err.message,
|
|
444
|
-
};
|
|
445
|
-
updateNotificationSendStatus({
|
|
446
|
-
...commonParams,
|
|
447
|
-
receivers: receivers.map((item) => item.did),
|
|
448
|
-
channel: 'webhook',
|
|
449
|
-
webhookParams,
|
|
450
|
-
});
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
} else {
|
|
454
|
-
// eslint-disable-next-line no-lonely-if
|
|
455
|
-
if (webhookList.length > 0) {
|
|
456
|
-
const webhookParams = {};
|
|
457
|
-
for (const webhook of webhookList) {
|
|
458
|
-
webhookParams[webhook.url] = {
|
|
459
|
-
type: webhook.type ?? 'url',
|
|
460
|
-
sendAt: new Date(),
|
|
461
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
462
|
-
failedReason: NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED,
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
updateNotificationSendStatus({
|
|
466
|
-
...commonParams,
|
|
467
|
-
receivers: receivers.map((item) => item.did),
|
|
468
|
-
channel: 'webhook',
|
|
469
|
-
webhookParams,
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
} else {
|
|
474
|
-
updateNotificationSendStatus({
|
|
475
|
-
...commonParams,
|
|
476
|
-
receivers: receiverEmailList.map((item) => item.did),
|
|
477
|
-
channel: 'email',
|
|
478
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
479
|
-
failedReason: NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED,
|
|
480
|
-
});
|
|
481
|
-
if (webhookList.length > 0) {
|
|
482
|
-
const webhookParams = {};
|
|
483
|
-
for (const webhook of webhookList) {
|
|
484
|
-
webhookParams[webhook.url] = {
|
|
485
|
-
type: webhook.type ?? 'url',
|
|
486
|
-
sendAt: new Date(),
|
|
487
|
-
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
488
|
-
failedReason: NOTIFICATION_SEND_FAILED_REASON.CHANNEL_DISABLED,
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
updateNotificationSendStatus({
|
|
492
|
-
...commonParams,
|
|
493
|
-
receivers: receivers.map((item) => item.did),
|
|
494
|
-
channel: 'webhook',
|
|
495
|
-
webhookParams,
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
151
|
})
|
|
500
152
|
);
|
|
501
153
|
};
|
|
502
154
|
|
|
503
155
|
// server send notification to app
|
|
504
|
-
const sendToAppDid = async ({ event, sender, notification, receiver, appDid, data, node, wsServer }) => {
|
|
156
|
+
const sendToAppDid = async ({ event, sender, notification, receiver, appDid, data, node, options, wsServer }) => {
|
|
505
157
|
if (notification && sender) {
|
|
158
|
+
const { keepForOfflineUser = true } = options || {};
|
|
506
159
|
const teamDid = sender.appDid;
|
|
507
160
|
const { id } = notification;
|
|
161
|
+
if (Array.isArray(receiver)) {
|
|
162
|
+
throw new Error('Invalid receiver: 1 receiver each time');
|
|
163
|
+
}
|
|
164
|
+
if (Array.isArray(notification)) {
|
|
165
|
+
throw new Error('Invalid notification: 1 message each time');
|
|
166
|
+
}
|
|
508
167
|
const nodeInfo = await node.getNodeInfo({ useCache: true });
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
168
|
+
// parse notification
|
|
169
|
+
const senderInfo = await ensureSenderApp({ sender, node, nodeInfo });
|
|
170
|
+
// parse notification
|
|
171
|
+
const [payload] = parseNotification({ ...notification }, senderInfo);
|
|
172
|
+
|
|
173
|
+
wsServer.broadcast(receiver, EVENTS.MESSAGE, payload, {}, async ({ count } = {}) => {
|
|
174
|
+
updateNotificationSendStatus({
|
|
175
|
+
node,
|
|
176
|
+
teamDid,
|
|
177
|
+
notificationId: id,
|
|
178
|
+
receivers: [receiver],
|
|
179
|
+
channel: NOTIFICATION_SEND_CHANNEL.WALLET,
|
|
180
|
+
status: count > 0 ? NOTIFICATION_SEND_STATUS.SENT : NOTIFICATION_SEND_STATUS.FAILED,
|
|
181
|
+
failedReason: count > 0 ? null : NOTIFICATION_SEND_FAILED_REASON.NOT_ONLINE,
|
|
182
|
+
});
|
|
183
|
+
if (count <= 0 && keepForOfflineUser) {
|
|
523
184
|
logger.error('Online client was not found', { userDid: receiver });
|
|
185
|
+
await states.message.insert({ did: receiver, event: EVENTS.MESSAGE, data: payload });
|
|
524
186
|
}
|
|
525
187
|
});
|
|
526
188
|
return;
|
|
@@ -625,6 +287,7 @@ const sendToWebhook = async ({ sender, receiver, notification, node }) => {
|
|
|
625
287
|
const teamDid = sender.appDid;
|
|
626
288
|
const { id, appInfo, ...rest } = notification;
|
|
627
289
|
const webhooks = appInfo?.webhooks ?? [];
|
|
290
|
+
const receivers = Array.isArray(receiver) ? receiver : [receiver];
|
|
628
291
|
if (!webhooks.length) {
|
|
629
292
|
throw new Error('Invalid webhook: empty');
|
|
630
293
|
}
|
|
@@ -643,67 +306,71 @@ const sendToWebhook = async ({ sender, receiver, notification, node }) => {
|
|
|
643
306
|
const notifications = parseNotification({ id, ...rest }, senderInfo);
|
|
644
307
|
const webhookSenderMap = new Map();
|
|
645
308
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
309
|
+
// eslint-disable-next-line no-unreachable-loop
|
|
310
|
+
for (const webhook of webhooks) {
|
|
311
|
+
let webhookSender = webhookSenderMap.get(webhook.type);
|
|
312
|
+
if (!webhookSender) {
|
|
313
|
+
webhookSender = node.getMessageSender(webhook.type);
|
|
314
|
+
webhookSenderMap.set(webhook.type, webhookSender);
|
|
315
|
+
}
|
|
316
|
+
const webhookParams = {
|
|
317
|
+
[webhook.url]: {
|
|
318
|
+
type: webhook.type ?? 'api',
|
|
319
|
+
sendAt: new Date(),
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
try {
|
|
323
|
+
// eslint-disable-next-line no-await-in-loop
|
|
324
|
+
const res = await webhookSender.sendNotification(webhook.url, notifications[0]);
|
|
325
|
+
webhookParams[webhook.url] = {
|
|
326
|
+
...webhookParams[webhook.url],
|
|
327
|
+
status: res ? NOTIFICATION_SEND_STATUS.SENT : NOTIFICATION_SEND_STATUS.FAILED,
|
|
328
|
+
failedReason: res ? '' : NOTIFICATION_SEND_FAILED_REASON.CHANNEL_UNAVAILABLE,
|
|
658
329
|
};
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
err.details = error;
|
|
692
|
-
throw err;
|
|
693
|
-
}
|
|
694
|
-
})
|
|
695
|
-
);
|
|
330
|
+
// eslint-disable-next-line no-await-in-loop
|
|
331
|
+
await updateNotificationSendStatus({
|
|
332
|
+
node,
|
|
333
|
+
teamDid,
|
|
334
|
+
notificationId: id,
|
|
335
|
+
receivers,
|
|
336
|
+
channel: NOTIFICATION_SEND_CHANNEL.WEBHOOK,
|
|
337
|
+
webhookParams,
|
|
338
|
+
});
|
|
339
|
+
return res;
|
|
340
|
+
} catch (error) {
|
|
341
|
+
logger.error('Failed to send webhook', { error });
|
|
342
|
+
webhookParams[webhook.url] = {
|
|
343
|
+
...webhookParams[webhook.url],
|
|
344
|
+
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
345
|
+
failedReason: error.message,
|
|
346
|
+
};
|
|
347
|
+
// eslint-disable-next-line no-await-in-loop
|
|
348
|
+
await updateNotificationSendStatus({
|
|
349
|
+
node,
|
|
350
|
+
teamDid,
|
|
351
|
+
notificationId: id,
|
|
352
|
+
receivers,
|
|
353
|
+
channel: NOTIFICATION_SEND_CHANNEL.WEBHOOK,
|
|
354
|
+
webhookParams,
|
|
355
|
+
});
|
|
356
|
+
const err = new Error('Failed to send webhook');
|
|
357
|
+
err.details = error;
|
|
358
|
+
throw err;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return undefined;
|
|
696
362
|
};
|
|
697
363
|
|
|
698
364
|
/**
|
|
699
365
|
* app send email to user
|
|
366
|
+
* receiver: email
|
|
700
367
|
*/
|
|
701
368
|
const emailSchema = Joi.string().email().required();
|
|
702
369
|
const sendToMail = async ({ sender, receiver, notification, options, node }) => {
|
|
703
370
|
const teamDid = sender.appDid;
|
|
704
371
|
const { id, appInfo, ...rest } = notification;
|
|
705
372
|
|
|
706
|
-
const receiverDid = appInfo
|
|
373
|
+
const { receiverDid, receivers: sameEmailReceivers = [], unsubscribeToken, userInfo = {} } = appInfo || {};
|
|
707
374
|
|
|
708
375
|
const receivers = uniq(Array.isArray(receiver) ? receiver : [receiver]).filter(Boolean);
|
|
709
376
|
if (receivers.length === 0) {
|
|
@@ -722,7 +389,7 @@ const sendToMail = async ({ sender, receiver, notification, options, node }) =>
|
|
|
722
389
|
if (!notification.title) {
|
|
723
390
|
throw new Error('Invalid notification: title empty');
|
|
724
391
|
}
|
|
725
|
-
if (!notification.body && notification.type !==
|
|
392
|
+
if (!notification.body && notification.type !== 'feed') {
|
|
726
393
|
throw new Error('Invalid notification: body empty');
|
|
727
394
|
}
|
|
728
395
|
|
|
@@ -745,21 +412,26 @@ const sendToMail = async ({ sender, receiver, notification, options, node }) =>
|
|
|
745
412
|
teamDid: sender.appDid,
|
|
746
413
|
node,
|
|
747
414
|
locale,
|
|
415
|
+
...(unsubscribeToken ? { unsubscribeToken } : {}),
|
|
416
|
+
...(userInfo ? { userInfo } : {}),
|
|
748
417
|
});
|
|
749
418
|
})
|
|
750
419
|
);
|
|
751
420
|
return results.map((item) => {
|
|
752
|
-
if (!isServer && receiverDid) {
|
|
421
|
+
if (!isServer && (receiverDid || sameEmailReceivers.length > 0)) {
|
|
753
422
|
updateNotificationSendStatus({
|
|
754
423
|
node,
|
|
755
424
|
teamDid,
|
|
756
425
|
notificationId: id,
|
|
757
|
-
receivers: [receiverDid],
|
|
758
|
-
channel:
|
|
426
|
+
receivers: sameEmailReceivers.length > 0 ? sameEmailReceivers : [receiverDid],
|
|
427
|
+
channel: NOTIFICATION_SEND_CHANNEL.EMAIL,
|
|
759
428
|
status: item.status === 'rejected' ? NOTIFICATION_SEND_STATUS.FAILED : NOTIFICATION_SEND_STATUS.SENT,
|
|
760
429
|
...(item.status === 'rejected'
|
|
761
430
|
? {
|
|
762
|
-
failedReason:
|
|
431
|
+
failedReason:
|
|
432
|
+
item.reason instanceof Error
|
|
433
|
+
? item.reason?.message
|
|
434
|
+
: item.reason || NOTIFICATION_SEND_FAILED_REASON.CHANNEL_UNAVAILABLE,
|
|
763
435
|
}
|
|
764
436
|
: {}),
|
|
765
437
|
});
|
|
@@ -800,7 +472,7 @@ const sendToPush = async ({ sender, receiver, notification, options, node }) =>
|
|
|
800
472
|
|
|
801
473
|
const senderInfo = await ensureSenderApp({ sender, node, nodeInfo });
|
|
802
474
|
|
|
803
|
-
const notifications = parseNotification(notification, senderInfo);
|
|
475
|
+
const notifications = parseNotification({ ...notification }, senderInfo);
|
|
804
476
|
|
|
805
477
|
const { locale = 'en' } = options || {};
|
|
806
478
|
return sendPush(receivers, notifications[0], {
|
|
@@ -815,7 +487,7 @@ const sendToPush = async ({ sender, receiver, notification, options, node }) =>
|
|
|
815
487
|
teamDid,
|
|
816
488
|
notificationId: id,
|
|
817
489
|
receivers,
|
|
818
|
-
channel:
|
|
490
|
+
channel: NOTIFICATION_SEND_CHANNEL.PUSH,
|
|
819
491
|
status: res ? NOTIFICATION_SEND_STATUS.SENT : NOTIFICATION_SEND_STATUS.FAILED,
|
|
820
492
|
failedReason: res ? null : NOTIFICATION_SEND_FAILED_REASON.CHANNEL_UNAVAILABLE,
|
|
821
493
|
});
|
|
@@ -829,7 +501,7 @@ const sendToPush = async ({ sender, receiver, notification, options, node }) =>
|
|
|
829
501
|
teamDid,
|
|
830
502
|
notificationId: id,
|
|
831
503
|
receivers,
|
|
832
|
-
channel:
|
|
504
|
+
channel: NOTIFICATION_SEND_CHANNEL.PUSH,
|
|
833
505
|
status: NOTIFICATION_SEND_STATUS.FAILED,
|
|
834
506
|
failedReason: err.message,
|
|
835
507
|
});
|
|
@@ -846,4 +518,5 @@ module.exports = {
|
|
|
846
518
|
sendToPush,
|
|
847
519
|
emailSchema,
|
|
848
520
|
sendToWebhook,
|
|
521
|
+
updateNotificationSendStatus,
|
|
849
522
|
};
|