Files
my-daily/scripts/modules/pusher.py
T

155 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
推送模块:企业微信 Webhook + 飞书 Webhook
支持推送文本消息、图片消息、文件消息
"""
import json
import base64
import requests
from pathlib import Path
from .logger import get_logger
logger = get_logger()
WECHAT_WEBHOOK_BASE = "https://qyapi.weixin.qq.com/cgi-bin/webhook"
def _send_wechat_message(payload, webhook_key, target):
url = f"{WECHAT_WEBHOOK_BASE}/send?key={webhook_key}"
if target:
payload["chatid"] = target
try:
resp = requests.post(url, json=payload, timeout=(5, 15))
resp.raise_for_status()
result = resp.json()
if result.get("errcode") == 0:
logger.info("企业微信推送成功")
return True
else:
logger.warning("企业微信推送失败: errcode=%s, errmsg=%s",
result.get("errcode"), result.get("errmsg"))
return False
except requests.exceptions.ConnectionError:
logger.warning("企业微信推送失败:无法连接到服务器")
return False
except requests.exceptions.Timeout:
logger.warning("企业微信推送失败:请求超时")
return False
except requests.exceptions.HTTPError as e:
logger.warning("企业微信推送失败:HTTP错误 %s", e)
return False
except (ValueError, requests.exceptions.JSONDecodeError):
logger.warning("企业微信推送失败:服务器返回非JSON响应")
return False
except Exception as e:
logger.warning("企业微信推送异常: %s", e)
return False
def push_wechat_text(content, webhook_key, target):
payload = {
"msgtype": "text",
"text": {"content": content}
}
return _send_wechat_message(payload, webhook_key, target)
def push_wechat_image(image_path, webhook_key, target):
if not Path(image_path).exists():
logger.warning("图片文件不存在,跳过推送: %s", image_path)
return False
with open(image_path, "rb") as f:
img_b64 = base64.b64encode(f.read()).decode("utf-8")
img_md5 = __import__("hashlib").md5(
base64.b64decode(img_b64)
).hexdigest()
payload = {
"msgtype": "image",
"image": {"base64": img_b64, "md5": img_md5}
}
return _send_wechat_message(payload, webhook_key, target)
def push_wechat_markdown(content, webhook_key, target):
payload = {
"msgtype": "markdown",
"markdown": {"content": content}
}
return _send_wechat_message(payload, webhook_key, target)
def push_feishu_text(content, webhook_url):
if not webhook_url:
logger.info("飞书 webhook 未配置,跳过推送")
return False
try:
payload = {"msg_type": "text", "content": {"text": content}}
resp = requests.post(webhook_url, json=payload, timeout=(5, 15))
resp.raise_for_status()
result = resp.json()
if result.get("code") == 0:
logger.info("飞书推送成功")
return True
else:
logger.warning("飞书推送失败: code=%s, msg=%s",
result.get("code"), result.get("msg"))
return False
except requests.exceptions.ConnectionError:
logger.warning("飞书推送失败:无法连接到飞书服务器")
return False
except requests.exceptions.Timeout:
logger.warning("飞书推送失败:请求超时")
return False
except requests.exceptions.HTTPError as e:
logger.warning("飞书推送失败:HTTP错误 %s", e)
return False
except (ValueError, requests.exceptions.JSONDecodeError):
logger.warning("飞书推送失败:服务器返回非JSON响应")
return False
except Exception as e:
logger.warning("飞书推送异常: %s", e)
return False
def send_daily_push(now, date_str, total_count, top3_articles, output_dir, push_config):
webhook_key = push_config.get("wechat_key", "")
target = push_config.get("wechat_target", "")
enable_wechat = push_config.get("enable_wechat_push", False)
enable_feishu = push_config.get("enable_feishu_push", False)
feishu_url = push_config.get("feishu_webhook", "")
if not enable_wechat and not enable_feishu:
logger.info("未启用任何推送渠道,跳过")
return
if not webhook_key and not feishu_url:
logger.info("推送已启用但均未配置 webhook")
return
date_label = now.strftime("%m月%d日")
# 文本摘要
summary_lines = [
f"🪖 军事科技每日摘报 — {date_label}",
f"📊 今日共 {total_count} 篇精选文章",
"",
"🔥 今日必看 TOP3",
]
for i, a in enumerate(top3_articles, 1):
title = a.get("translated_title") or a.get("title", "")[:40]
score = a.get("final_score", 0)
summary_lines.append(f" {i}. [{score:.1f}] {title}")
summary_lines.append("")
summary_lines.append(f"📄 完整报告已生成,包含装备动态/地区冲突/战略政策三分类深度洞察。")
text_content = "\n".join(summary_lines)
if enable_wechat and webhook_key:
push_wechat_text(text_content, webhook_key, target)
webzine_image = output_dir / f"military_webzine_{date_str}.png"
push_wechat_image(str(webzine_image), webhook_key, target)
if enable_feishu and feishu_url:
push_feishu_text(text_content, feishu_url)