You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

320 lines
8.4 KiB

/**
* Daily Horoscope & Fortune Analysis
*
* 查询每日星座运势,结合黄历和八字分析
* 为桐哥 Agent 提供每日运势推送功能
*/
const https = require('https');
// 王院长生辰信息
const USER_BIRTH_INFO = {
name: '王院长',
birthday: '1984-05-16',
birthTime: '23:00-24:00', // 子时
lunarBirthday: '甲子年 四月十六',
zodiac: '鼠',
westernZodiac: '金牛座',
bazi: {
year: '甲子',
month: '己巳',
day: '丙午',
hour: '戊子',
dayMaster: '丙火' // 日主
}
};
// 十二星座
const ZODIAC_SIGNS = [
'白羊座', '金牛座', '双子座', '巨蟹座',
'狮子座', '处女座', '天秤座', '天蝎座',
'射手座', '摩羯座', '水瓶座', '双鱼座'
];
/**
* 使用 Tavily 搜索运势信息
*/
async function searchHoroscope(date, sign) {
const tomorrow = new Date(date);
tomorrow.setDate(tomorrow.getDate() + 1);
const dateStr = tomorrow.toISOString().split('T')[0];
const query = `${dateStr} ${sign} 运势 星座运程`;
// 调用 Tavily API
const tavilyApiKey = process.env.TAVILY_API_KEY || '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';
return new Promise((resolve, reject) => {
const postData = JSON.stringify({
query: query,
search_depth: 'basic',
include_answer: true,
max_results: 3,
topic: 'general'
});
const options = {
hostname: 'api.tavily.com',
port: 443,
path: '/search',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData),
'Authorization': `Bearer ${tavilyApiKey}`
}
};
const req = https.request(options, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => {
try {
const result = JSON.parse(data);
resolve(result);
} catch (e) {
reject(e);
}
});
});
req.on('error', reject);
req.write(postData);
req.end();
});
}
/**
* 查询黄历
*/
async function queryAlmanac(date) {
// 调用 chinese-almanac skill
const almanacPath = '/root/.openclaw/workspace/skills/chinese-almanac/almanac.js';
try {
const almanac = require(almanacPath);
const result = await almanac.queryAlmanac(date);
return result;
} catch (e) {
console.error('黄历查询失败:', e.message);
// Fallback: 基础信息
return {
success: false,
date: date,
lunarDate: '查询失败',
yi: [],
ji: [],
chong: ''
};
}
}
/**
* 八字分析 - 根据日主和明日五行
*/
function analyzeBazi(targetDate, userBazi) {
const date = new Date(targetDate);
const dayMaster = userBazi.dayMaster; // 丙火
// 简化的五行分析(实际应该用更精确的干支计算)
const dayOfWeek = date.getDay();
const elements = ['金', '木', '水', '火', '土'];
const tomorrowElement = elements[dayOfWeek % 5];
// 五行生克关系
const shengKe = {
'丙火': {
'金': '火克金 - 财星,利于求财',
'木': '木生火 - 印星,贵人相助',
'水': '水克火 - 官杀,压力较大',
'火': '火比和 - 兄弟,竞争激烈',
'土': '火生土 - 食伤,才华展现'
}
};
const analysis = shengKe[dayMaster]?.[tomorrowElement] || '五行平衡';
// 根据分析生成建议
const suggestions = {
'财星': {
lucky: ['商务谈判', '投资决策', '签订合同'],
avoid: ['大额支出', '冒险投资']
},
'印星': {
lucky: ['学习新知', '拜访长辈', '规划未来'],
avoid: ['独自决策', '匆忙行动']
},
'官杀': {
lucky: ['处理公务', '解决问题', '锻炼身体'],
avoid: ['与人争执', '高风险活动']
},
'比和': {
lucky: ['团队合作', '朋友聚会', '交流沟通'],
avoid: ['单打独斗', '固执己见']
},
'食伤': {
lucky: ['创意工作', '表达展示', '休闲娱乐'],
avoid: ['批评他人', '过度消费']
}
};
const key = Object.keys(suggestions).find(k => analysis.includes(k)) || '比和';
return {
dayMaster: dayMaster,
tomorrowElement: tomorrowElement,
analysis: analysis,
suggestions: suggestions[key]
};
}
/**
* 生成运势报告
*/
async function generateFortuneReport(targetDate) {
const tomorrow = new Date(targetDate);
tomorrow.setDate(tomorrow.getDate() + 1);
const dateStr = tomorrow.toISOString().split('T')[0];
console.log(`[Horoscope] 查询 ${dateStr} 的运势...`);
// 1. 查询黄历
const almanac = await queryAlmanac(dateStr);
console.log('[Horoscope] 黄历查询完成');
// 2. 搜索金牛座运势(王院长是金牛座)
let horoscopeText = '';
try {
const horoscopeResult = await searchHoroscope(dateStr, '金牛座');
if (horoscopeResult.answer) {
horoscopeText = horoscopeResult.answer;
} else if (horoscopeResult.results && horoscopeResult.results.length > 0) {
horoscopeText = horoscopeResult.results[0].content;
}
} catch (e) {
console.error('星座运势搜索失败:', e.message);
horoscopeText = '今日金牛座运势平稳,保持积极心态。';
}
console.log('[Horoscope] 星座运势查询完成');
// 3. 八字分析
const baziAnalysis = analyzeBazi(dateStr, USER_BIRTH_INFO.bazi);
console.log('[Horoscope] 八字分析完成');
// 4. 生成综合报告
const report = {
date: dateStr,
user: USER_BIRTH_INFO.name,
zodiac: USER_BIRTH_INFO.westernZodiac,
chineseZodiac: USER_BIRTH_INFO.zodiac,
almanac: almanac,
horoscope: {
text: horoscopeText,
source: 'Tavily AI Search'
},
bazi: baziAnalysis,
overallLuck: calculateOverallLuck(almanac, baziAnalysis)
};
return report;
}
/**
* 计算整体运势指数
*/
function calculateOverallLuck(almanac, bazi) {
let score = 3; // 基础 3 星
// 黄历加分项
if (almanac.yi && almanac.yi.length > 3) score += 0.5;
if (almanac.chong && !almanac.chong.includes('鼠')) score += 0.5;
// 八字加分项
if (baziAnalysis.analysis.includes('贵人') || baziAnalysis.analysis.includes('财星')) {
score += 0.5;
}
const stars = Math.min(5, Math.max(1, Math.round(score)));
return '★'.repeat(stars) + '☆'.repeat(5 - stars);
}
/**
* 格式化运势报告为消息
*/
function formatFortuneMessage(report) {
const { date, user, zodiac, almanac, horoscope, bazi, overallLuck } = report;
let message = `📅 **${user} · 明日运势**\n`;
message += `${date} | ${almanac.lunarDate || '农历查询中'}\n\n`;
message += `✨ **整体运势**: ${overallLuck}\n\n`;
message += `🗓 **黄历宜忌**\n`;
message += `宜:${almanac.yi?.join('、') || '查询中'}\n`;
message += `忌:${almanac.ji?.join('、') || '查询中'}\n`;
if (almanac.chong) {
message += `冲煞:${almanac.chong}\n`;
}
message += '\n';
message += `♉ **${zodiac}运势**\n`;
message += `${horoscope.text}\n\n`;
message += `🔮 **八字分析**\n`;
message += `日主:${bazi.dayMaster}\n`;
message += `明日五行:${bazi.tomorrowElement}\n`;
message += `${bazi.analysis}\n\n`;
message += `💡 **趋吉避凶建议**\n`;
message += `✅ 宜:${bazi.suggestions?.lucky?.join('、') || '顺其自然'}\n`;
message += `❌ 忌:${bazi.suggestions?.avoid?.join('、') || '谨慎行事'}\n\n`;
message += `_桐哥祝您明日顺利!_ 🌟`;
return message;
}
/**
* 主函数 - 获取明日运势
*/
async function getDailyHoroscope(options = {}) {
const targetDate = options.date || new Date().toISOString().split('T')[0];
try {
const report = await generateFortuneReport(targetDate);
const message = formatFortuneMessage(report);
return {
success: true,
report: report,
message: message
};
} catch (e) {
console.error('运势查询失败:', e);
return {
success: false,
error: e.message,
message: '⚠ 运势查询暂时失败,请稍后再试。'
};
}
}
// 导出函数
module.exports = {
getDailyHoroscope,
generateFortuneReport,
formatFortuneMessage,
searchHoroscope,
queryAlmanac,
analyzeBazi,
USER_BIRTH_INFO,
ZODIAC_SIGNS
};
// 测试运行
if (require.main === module) {
getDailyHoroscope().then(result => {
console.log('\n=== 运势报告 ===\n');
console.log(result.message);
});
}