155 lines
4.7 KiB
Python
Executable File
155 lines
4.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""check_cares.py — 牵挂检查与飞书提醒
|
||
|
||
用法:
|
||
python3 check_cares.py # 检查并推送今天到期的牵挂
|
||
python3 check_cares.py --list # 仅列出,不推送
|
||
python3 check_cares.py --daily # 每日21:00日报模式:列出所有pending
|
||
|
||
依赖:soulful_core.py(同目录)
|
||
"""
|
||
import sys, os
|
||
for _ in (sys.stdout, sys.stderr):
|
||
try: _.reconfigure(encoding='utf-8', errors='replace')
|
||
except Exception: pass
|
||
|
||
import json, urllib.request, urllib.error
|
||
from datetime import datetime, timezone
|
||
|
||
HERMES = os.path.expanduser("~/.hermes")
|
||
D = HERMES + "/soulful"
|
||
|
||
FEISHU_WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/446db983-e392-4d2c-bfb8-f9060e5df3ad"
|
||
|
||
|
||
def send_feishu(title: str, content: str, color: str = "green"):
|
||
"""发送飞书消息"""
|
||
color_key = color if color in ("green", "yellow", "red", "blue", "purple") else "blue"
|
||
card_obj = {
|
||
"header": {
|
||
"title": {"tag": "plain_text", "content": f"🎗️ {title}"},
|
||
"template": color_key,
|
||
},
|
||
"elements": [
|
||
{"tag": "markdown", "content": content},
|
||
],
|
||
}
|
||
payload = {
|
||
"msg_type": "interactive",
|
||
"card": json.dumps(card_obj, ensure_ascii=False),
|
||
}
|
||
data = json.dumps(payload, ensure_ascii=True).encode("utf-8")
|
||
req = urllib.request.Request(FEISHU_WEBHOOK, data=data, headers={"Content-Type": "application/json; charset=utf-8"})
|
||
try:
|
||
with urllib.request.urlopen(req, timeout=10) as resp:
|
||
return json.loads(resp.read())
|
||
except Exception as e:
|
||
print(f" 飞书发送失败: {e}")
|
||
return None
|
||
|
||
|
||
def generate_warm_text(care: dict, index: int = 1) -> str:
|
||
"""为牵挂生成温暖的自然语言描述"""
|
||
content = care.get("content", "")
|
||
context = care.get("context", "")
|
||
reminder_count = care.get("reminder_count", 0)
|
||
follow_up_date = care.get("follow_up_date", "")
|
||
tags = care.get("tags", [])
|
||
|
||
if reminder_count == 0:
|
||
opener = "你之前说过"
|
||
elif reminder_count == 1:
|
||
opener = "上次提醒过一次了,还是想问一下"
|
||
else:
|
||
opener = f"已经提醒 {reminder_count} 次了,这件重要的事"
|
||
|
||
tag_hints = {
|
||
"工作": "关于工作的事",
|
||
"生活": "生活里的小事",
|
||
"学习": "学习方面",
|
||
"健康": "身体是革命的本钱",
|
||
}
|
||
tag_hint = ""
|
||
for t in tags:
|
||
if t in tag_hints:
|
||
tag_hint = tag_hints[t]
|
||
break
|
||
|
||
parts = [opener]
|
||
if tag_hint:
|
||
parts.append(tag_hint)
|
||
parts.append(f"「{content}」")
|
||
if context and len(context) > 5:
|
||
parts.append(f"(你说的是:{context[:40]})")
|
||
if reminder_count > 0:
|
||
parts.append("——依然放在心上")
|
||
|
||
return ",".join(parts)
|
||
|
||
|
||
def format_daily_report(cares: list) -> str:
|
||
"""格式化每日牵挂清单"""
|
||
if not cares:
|
||
return '今天没有待提醒的牵挂 ✓\n\n你可以说"记得提醒我做XXX",我会帮你记住并准时提醒。'
|
||
|
||
lines = [f"📋 今天有 **{len(cares)}** 件牵挂:\n"]
|
||
for i, c in enumerate(cares, 1):
|
||
follow_up = c.get("follow_up_date", "")
|
||
content = c.get("content", "")
|
||
context = c.get("context", "")
|
||
lines.append(f"{i}. **{content}**")
|
||
if context:
|
||
lines.append(f" 💬 {context[:50]}")
|
||
lines.append(f"\n完成记得告诉我,我会帮你划掉。")
|
||
lines.append('\n_说"做完XXX"即可,我会帮你记录。_')
|
||
return "\n".join(lines)
|
||
|
||
|
||
def main():
|
||
list_only = "--list" in sys.argv
|
||
daily = "--daily" in sys.argv
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
from soulful_core import CaresQueue
|
||
|
||
cq = CaresQueue()
|
||
|
||
if daily:
|
||
pending = cq.pending()
|
||
if not pending:
|
||
print("无 pending 牵挂")
|
||
return
|
||
|
||
report = format_daily_report(pending)
|
||
print(report)
|
||
if not list_only:
|
||
send_feishu("今日牵挂清单", report, "blue")
|
||
return
|
||
|
||
due = cq.today_check()
|
||
|
||
if not due:
|
||
print("没有今天到期的牵挂 ✓")
|
||
return
|
||
|
||
print(f"发现 {len(due)} 条到期牵挂:")
|
||
for i, c in enumerate(due, 1):
|
||
print(f" {i}. [{c['id']}] {c['content']}")
|
||
|
||
if list_only:
|
||
return
|
||
|
||
for care in due:
|
||
text = generate_warm_text(care)
|
||
print(f"\n推送: {text[:60]}...")
|
||
result = send_feishu("你有一件事一直放在心上", text, "purple")
|
||
if result and result.get("code") == 0:
|
||
cq.snooze(care["id"], days=0)
|
||
print(" ✓ 已推送")
|
||
else:
|
||
print(f" ✗ 推送失败: {result}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main() |