Files
memind/notification-dispatcher.mjs
T
john 830f8a4011
Memind CI / Test, build, and release guards (push) Successful in 5m36s
feat(wechat): add service-account push subscriptions and news morning cover delivery
Ship the 10-item numeric subscription loop on WeChat MP, wire schedule delivery
for news/weather/quote/health/finance/tech/knowledge/night/surprise pushes, and
extend news morning draft cover generation plus a one-shot draft push script.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 16:15:15 +08:00

69 lines
2.2 KiB
JavaScript

export const WECHAT_SCHEDULE_NOTIFICATION_NOT_SENT =
'WECHAT_SCHEDULE_NOTIFICATION_NOT_SENT';
export function resolveWechatDispatchSent(result) {
if (result && typeof result === 'object') {
return result.sent !== false && !result.deferred && !result.skipped;
}
return result !== false;
}
export async function deliverWechatScheduleNotification(
sendScheduleNotification,
payload,
) {
const result = await sendScheduleNotification({
...payload,
verifiedHtmlUrls: Array.isArray(payload?.verifiedHtmlUrls) ? payload.verifiedHtmlUrls : [],
});
if (!resolveWechatDispatchSent(result)) {
const err = new Error('微信提醒发送未完成(deferred、skipped 或未绑定)');
err.code = WECHAT_SCHEDULE_NOTIFICATION_NOT_SENT;
throw err;
}
}
export function createNotificationDispatcher({ sendWechatTextToUser, logger = console } = {}) {
const sendWechat = async (userId, text, options = {}) => {
if (typeof sendWechatTextToUser !== 'function') return false;
const result = await sendWechatTextToUser(userId, text, options);
return resolveWechatDispatchSent(result);
};
return {
async sendRechargeSuccess({ userId, title, body, dedupeKey = null }) {
const sent = await sendWechat(userId, `${title}\n${body}`.trim());
logger.info?.('Notification dispatch:', {
type: 'recharge_success',
userId,
dedupeKey,
sent,
});
return sent;
},
async sendScheduleNotification({ userId, text, verifiedHtmlUrls = [] }) {
const sent = await sendWechat(userId, text, { verifiedHtmlUrls });
logger.info?.('Notification dispatch:', {
type: 'schedule_notification',
userId,
dedupeKey: null,
sent,
verifiedHtmlCount: verifiedHtmlUrls.length,
});
return sent;
},
async sendHealthEventNotification({ userId, title, body, eventId = null, severity = 'alert' }) {
const text = `${title}\n${body}`.trim();
const sent = await sendWechat(userId, text);
logger.info?.('Notification dispatch:', {
type: 'health_event_notification',
userId,
dedupeKey: eventId,
severity,
sent,
});
return sent;
},
};
}