Files
yidaima_tools/step2.py

193 lines
7.5 KiB
Python
Raw Permalink 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.

from __future__ import annotations
import os
import subprocess
from typing import Optional, Callable
from config_loader import get_config
from image_uploader import get_wechat_access_token, process_html_images
from md_to_wechat import convert_markdown_to_wechat
from wechat_publisher import publish_to_wechat
from markdown_editor import WechatMarkdownEditor, ThemeManager
def _now_datestr() -> str:
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d")
def get_clipboard_text() -> str:
"""获取剪贴板文本内容"""
result = subprocess.run(
["powershell", "-command", "Get-Clipboard"],
capture_output=True
)
try:
return result.stdout.decode('utf-8').strip()
except UnicodeDecodeError:
try:
return result.stdout.decode('gbk').strip()
except UnicodeDecodeError:
return result.stdout.decode('gb2312', errors='ignore').strip()
class Step2Converter:
"""
Step 2: 获取剪贴板内容,转换为公众号格式,推送到草稿箱
参考: docs/step2.md
"""
def __init__(self, log_callback: Optional[Callable[[str], None]] = None, css_scheme_id: Optional[str] = None, project_name: Optional[str] = None):
"""
初始化 Step2Converter
Args:
log_callback: 日志回调函数,用于将日志输出到 GUI
css_scheme_id: CSS 样式方案 ID可选
project_name: 项目名称,可选,用于生成文章标题
"""
self.log_callback = log_callback
self.css_scheme_id = css_scheme_id
self.project_name = project_name
self.theme_manager = ThemeManager()
def _log(self, message: str):
"""输出日志,支持回调到 GUI"""
print(message)
if self.log_callback:
self.log_callback(message)
def run(self) -> bool:
"""执行 Step 2 流程,成功返回 True"""
# 1) 获取剪贴板内容
self._log("[Step2] 正在获取剪贴板内容...")
md_content = get_clipboard_text()
if not md_content:
self._log("[Step2] 警告:剪贴板为空,无法继续")
return False
self._log(f"[Step2] 获取到 Markdown 内容,长度: {len(md_content)} 字符")
# 2) 转换为公众号文章格式
self._log("[Step2] 正在转换为公众号 HTML 格式...")
# 如果指定了 CSS 方案,先应用
if self.css_scheme_id:
scheme = self.theme_manager.get_css_scheme(self.css_scheme_id)
if scheme:
self._log(f"[Step2] 应用 CSS 方案: {scheme.name}")
self.theme_manager.apply_css_scheme(self.css_scheme_id)
else:
self._log(f"[Step2] 警告CSS 方案 {self.css_scheme_id} 不存在,使用默认设置")
# 使用 Markdown 编辑器进行转换(与编辑器中的方式一致)
# 创建编辑器实例,它会自动加载当前配置(包括已应用的 CSS 方案)
editor = WechatMarkdownEditor()
html_content = editor.render(md_content)
# 提取标题(从 HTML 内容中提取 h1 标签)
import re
title_match = re.search(r'<h1[^>]*>(.*?)</h1>', html_content)
title = title_match.group(1) if title_match else "无标题"
# 如果提供了项目名称,使用项目名称去掉编号作为标题,并添加作者
if self.project_name:
# 去掉编号,如"【A167】xxx" -> "xxx"
match = re.search(r'】(.+)', self.project_name)
if match:
title = match.group(1)
else:
title = self.project_name
# 添加作者 - 通过 publish_to_wechat 传入
html_content = re.sub(r'\n\s*\n+', '\n', html_content)
html_content = re.sub(r'>\s*\n\s*<', '><', html_content)
self._log(f"[Step2] 转换完成,标题: {title}")
self._log(f"[Step2] HTML 内容长度: {len(html_content)} 字符")
# 3) 处理图片 - 将外部图片上传到微信并替换 URL
cover_image_url: Optional[str] = None
config = get_config()
if config.wechat_appid and config.wechat_appsecret:
self._log("[Step2] 正在处理图片,将外部图片上传到微信服务器...")
access_token = get_wechat_access_token(config.wechat_appid, config.wechat_appsecret)
if access_token:
html_content, cover_image_url = process_html_images(html_content, access_token, external_domain="yidaima.cn")
self._log("[Step2] 图片处理完成")
if cover_image_url:
self._log(f"[Step2] 封面图: {cover_image_url}")
else:
self._log("[Step2] 警告:无法获取微信 access_token跳过图片上传")
# 4) 保存 HTML 到文件
html_dir = os.path.join(".", "data", "html")
os.makedirs(html_dir, exist_ok=True)
html_file = os.path.join(html_dir, "wechat.html")
with open(html_file, "w", encoding="utf-8") as f:
f.write(html_content)
self._log(f"[Step2] HTML 已保存到: {html_file}")
# 5) 推送到公众号草稿箱
self._log("[Step2] 准备推送到公众号草稿箱...")
wechat_appid = config.wechat_appid
wechat_appsecret = config.wechat_appsecret
if wechat_appid and wechat_appsecret:
self._log("[Step2] 正在推送到公众号草稿箱...")
# 优先使用第二张图片作为封面,否则使用默认封面
if cover_image_url:
self._log(f"[Step2] 使用第二张图片作为封面: {cover_image_url}")
success = publish_to_wechat(
title=title,
content=html_content,
appid=wechat_appid,
appsecret=wechat_appsecret,
thumb_image_url=cover_image_url,
author="南音"
)
else:
# 使用默认封面图片
thumb_path = r"c:\Users\南音\Desktop\yidaima\assets\img\bg.jpg"
self._log(f"[Step2] 使用默认封面图片: {thumb_path}")
success = publish_to_wechat(
title=title,
content=html_content,
appid=wechat_appid,
appsecret=wechat_appsecret,
thumb_image_path=thumb_path,
author="南音"
)
if success:
self._log("[Step2] 公众号草稿推送成功!")
else:
self._log("[Step2] 公众号草稿推送失败!")
else:
self._log("[Step2] 提示:未配置微信公众号,跳过公众号推送")
self._log("[Step2] 如需推送,请编辑 config.yaml 文件:")
self._log("[Step2] wechat:")
self._log("[Step2] appid: \"your_appid\"")
self._log("[Step2] appsecret: \"your_appsecret\"")
self._log("[Step2] 或使用环境变量覆盖:")
self._log("[Step2] set WECHAT_APPID=your_appid")
self._log("[Step2] set WECHAT_APPSECRET=your_appsecret")
return True
def main():
"""单独运行 Step2"""
step2 = Step2Converter()
try:
step2.run()
print("[INFO] Step2 执行成功!")
except Exception as e:
print(f"[ERROR] Step2 执行失败: {e}")
if __name__ == "__main__":
main()