/** 微信服务号数字订阅目录(仅限服务号客服消息推送)。 */ export const WECHAT_PUSH_SUBSCRIPTION_PREFIX = 'wechat_push'; export const LEGACY_MORNING_SOURCE = 'subscribe_morning_reminder'; export const PUSH_SUBSCRIPTION_ITEMS = Object.freeze([ { id: 1, key: 'morning', emoji: '☀️', label: '早安问候', defaultHour: 8, defaultMinute: 0, aliases: ['早安', '问候'], deliveryReady: true, }, { id: 2, key: 'news', emoji: '📰', label: '每日新闻早报', defaultHour: 7, defaultMinute: 30, aliases: ['新闻', '早报', '新闻早报'], deliveryReady: true, }, { id: 3, key: 'weather', emoji: '🌤', label: '每日天气', defaultHour: 7, defaultMinute: 0, aliases: ['天气'], deliveryReady: true, requiresOptions: ['city'], }, { id: 4, key: 'finance', emoji: '💰', label: '财经市场', defaultHour: 8, defaultMinute: 30, aliases: ['财经', '股市', '市场'], deliveryReady: true, }, { id: 5, key: 'tech', emoji: '🤖', label: 'AI / 科技早报', defaultHour: 8, defaultMinute: 0, aliases: ['科技', 'AI', 'ai'], deliveryReady: true, }, { id: 6, key: 'knowledge', emoji: '📚', label: '每日知识', defaultHour: 12, defaultMinute: 0, aliases: ['知识'], deliveryReady: true, }, { id: 7, key: 'quote', emoji: '💡', label: '每日金句', defaultHour: 7, defaultMinute: 30, aliases: ['金句', '名言'], deliveryReady: true, }, { id: 8, key: 'health', emoji: '🏃', label: '健康提醒', defaultHour: 10, defaultMinute: 0, aliases: ['健康'], deliveryReady: true, }, { id: 9, key: 'night', emoji: '🌙', label: '晚安总结', defaultHour: 22, defaultMinute: 0, aliases: ['晚安'], deliveryReady: true, }, { id: 10, key: 'surprise', emoji: '🎁', label: '每日惊喜', defaultHour: 18, defaultMinute: 0, aliases: ['惊喜'], deliveryReady: true, }, ]); const byId = new Map(PUSH_SUBSCRIPTION_ITEMS.map((item) => [item.id, item])); const byKey = new Map(PUSH_SUBSCRIPTION_ITEMS.map((item) => [item.key, item])); export function pushSubscriptionMetadataSource(key) { return `${WECHAT_PUSH_SUBSCRIPTION_PREFIX}:${String(key ?? '').trim()}`; } export function getPushSubscriptionById(id) { const num = Number(id); if (!Number.isInteger(num)) return null; return byId.get(num) ?? null; } export function getPushSubscriptionByKey(key) { const normalized = String(key ?? '').trim().toLowerCase(); if (!normalized) return null; return byKey.get(normalized) ?? null; } export function resolvePushSubscriptionFromMetadataSource(source) { const raw = String(source ?? '').trim(); if (!raw) return null; if (raw === LEGACY_MORNING_SOURCE) { return getPushSubscriptionByKey('morning'); } const prefix = `${WECHAT_PUSH_SUBSCRIPTION_PREFIX}:`; if (!raw.startsWith(prefix)) return null; return getPushSubscriptionByKey(raw.slice(prefix.length)); } export function resolvePushSubscriptionFromAlias(text) { const compact = String(text ?? '').replace(/\s+/g, ''); if (!compact) return null; for (const item of PUSH_SUBSCRIPTION_ITEMS) { for (const alias of item.aliases) { if (compact.includes(alias)) return item; } } return null; } export function formatPushSubscriptionTimeLabel(hour, minute) { const safeHour = Number(hour); const safeMinute = Number(minute ?? 0); return `${String(safeHour).padStart(2, '0')}:${String(safeMinute).padStart(2, '0')}`; } export function formatPushSubscriptionMenuLine(item) { const timeLabel = formatPushSubscriptionTimeLabel(item.defaultHour, item.defaultMinute); return `${item.id} ${item.emoji} ${item.label} 默认 ${timeLabel}`; } export function buildPushSubscriptionMenuLines() { const lines = [ '', '📬 每日推送订阅(仅限本服务号)', '回复数字即可开通,例如「2」或「2 7点」:', ...PUSH_SUBSCRIPTION_ITEMS.map((item) => formatPushSubscriptionMenuLine(item)), '', '· 查状态:回复「我的订阅」', '· 改时间:回复「2改到7点」', '· 取消:回复「取消2」', '· 天气城市:回复「3 北京」或「3改城市上海」', '· 帮助:回复「订阅帮助」', ]; return lines; } export function isPushSubscriptionEnabled(env = process.env) { const explicit = env.H5_WECHAT_MP_PUSH_SUBSCRIPTION_ENABLED; if (explicit != null && String(explicit).trim() !== '') { return String(explicit).trim() !== '0'; } return String(env.H5_WECHAT_MP_SUBSCRIBE_MORNING_REMINDER_ENABLED ?? '1').trim() !== '0'; }