feat: 军事科技每日资讯推送系统 - Docker部署 + 日志系统 + 数据目录重组

This commit is contained in:
poiuy
2026-07-12 20:01:02 +08:00
commit 54ca4b1b6a
267 changed files with 47047 additions and 0 deletions
+154
View File
@@ -0,0 +1,154 @@
# -*- 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)