- subscribe: 用户订阅/取消订阅/查询订阅状态 - daily-push: 定时查询订阅用户、生成运势、发送订阅消息 - push-test: 推送调试云函数 - 定时触发器配置,每日 7:00/12:00/18:00 推送
142 lines
4.2 KiB
JavaScript
142 lines
4.2 KiB
JavaScript
// 云函数:dailyPush
|
||
// 每日定时推送运势通知
|
||
// 定时触发器:cron: 0 0 7 * * * *(每日 07:00)
|
||
// 或每分钟扫描:cron: 0 * * * * * *(支持用户自定义时间)
|
||
|
||
const cloud = require('wx-server-sdk')
|
||
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||
const db = cloud.database()
|
||
|
||
// 引入共享算法包(需在云函数部署时安装)
|
||
// 由于云函数环境限制,算法代码会内联到本文件
|
||
// 参见 _algorithm.js 文件
|
||
|
||
const _ = require('./_algorithm')
|
||
|
||
exports.main = async (event, context) => {
|
||
const now = new Date()
|
||
const todayStr = now.toISOString().slice(0, 10)
|
||
const currentHour = now.getHours()
|
||
const currentMinute = now.getMinutes()
|
||
|
||
console.log(`[dailyPush] Triggered at ${now.toISOString()}`)
|
||
|
||
try {
|
||
// 查询所有已开启推送的订阅
|
||
const { data: subscriptions } = await db.collection('subscriptions')
|
||
.where({
|
||
pushEnabled: true,
|
||
})
|
||
.get()
|
||
|
||
console.log(`[dailyPush] Found ${subscriptions.length} active subscriptions`)
|
||
|
||
let pushCount = 0
|
||
let skipCount = 0
|
||
let errorCount = 0
|
||
|
||
for (const sub of subscriptions) {
|
||
try {
|
||
// 检查是否已达到推送时间
|
||
const [pushHour, pushMinute] = (sub.pushTime || '07:00').split(':').map(Number)
|
||
if (currentHour !== pushHour || currentMinute !== pushMinute) {
|
||
skipCount++
|
||
continue
|
||
}
|
||
|
||
// 检查是否已推送过(防重复)
|
||
if (sub.lastPushDate === todayStr) {
|
||
skipCount++
|
||
continue
|
||
}
|
||
|
||
// 生成运势内容
|
||
const fortune = _.generatePushContent(sub.birthInfo, now)
|
||
|
||
// 格式化推送内容
|
||
const pushData = {
|
||
touser: sub.openid,
|
||
templateId: sub.templateId,
|
||
page: '/pages/fortune/index', // 点击跳转到运势页面
|
||
data: {
|
||
date1: { value: formatDate(now) },
|
||
thing2: { value: `综合运势评分${fortune.overallScore}分,等级:${fortune.overallLuck}` },
|
||
thing3: { value: formatFortuneSummary(fortune) },
|
||
thing4: { value: `幸运色:${fortune.luckyColor} 幸运数字:${fortune.luckyNumber}` },
|
||
},
|
||
}
|
||
|
||
// 发送微信订阅消息
|
||
await cloud.openapi.subscribeMessage.send(pushData)
|
||
|
||
// 更新最后推送日期
|
||
await db.collection('subscriptions').doc(sub._id).update({
|
||
data: { lastPushDate: todayStr },
|
||
})
|
||
|
||
pushCount++
|
||
console.log(`[dailyPush] Pushed to ${sub.openid}`)
|
||
} catch (err) {
|
||
errorCount++
|
||
console.error(`[dailyPush] Failed for ${sub.openid}:`, err.message)
|
||
}
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
summary: {
|
||
total: subscriptions.length,
|
||
pushed: pushCount,
|
||
skipped: skipCount,
|
||
errors: errorCount,
|
||
},
|
||
}
|
||
} catch (err) {
|
||
console.error('[dailyPush] Fatal error:', err)
|
||
return { success: false, error: err.message }
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 格式化日期为中文显示
|
||
*/
|
||
function formatDate(date) {
|
||
const year = date.getFullYear()
|
||
const month = date.getMonth() + 1
|
||
const day = date.getDate()
|
||
const weekdays = ['日', '一', '二', '三', '四', '五', '六']
|
||
const weekday = weekdays[date.getDay()]
|
||
return `${year}年${month}月${day}日 星期${weekday}`
|
||
}
|
||
|
||
/**
|
||
* 格式化运势摘要
|
||
*/
|
||
function formatFortuneSummary(fortune) {
|
||
const parts = []
|
||
if (fortune.careerAdvice) {
|
||
const brief = fortune.careerAdvice.length > 10
|
||
? fortune.careerAdvice.slice(0, 10) + '…'
|
||
: fortune.careerAdvice
|
||
parts.push(`事业:${brief}`)
|
||
}
|
||
if (fortune.wealthAdvice) {
|
||
const brief = fortune.wealthAdvice.length > 10
|
||
? fortune.wealthAdvice.slice(0, 10) + '…'
|
||
: fortune.wealthAdvice
|
||
parts.push(`财运:${brief}`)
|
||
}
|
||
if (fortune.relationshipAdvice) {
|
||
const brief = fortune.relationshipAdvice.length > 10
|
||
? fortune.relationshipAdvice.slice(0, 10) + '…'
|
||
: fortune.relationshipAdvice
|
||
parts.push(`感情:${brief}`)
|
||
}
|
||
if (fortune.healthAdvice) {
|
||
const brief = fortune.healthAdvice.length > 10
|
||
? fortune.healthAdvice.slice(0, 10) + '…'
|
||
: fortune.healthAdvice
|
||
parts.push(`健康:${brief}`)
|
||
}
|
||
return parts.join(' ')
|
||
} |