auto: sync OpenClaw config 2026-08-27 11:17

This commit is contained in:
2026-08-27 11:17:10 +08:00
parent 0269b99815
commit 7a5ca9f1a7
94 changed files with 4497 additions and 2088 deletions
@@ -0,0 +1,156 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""从钉邮周报 eml 文件批量解析并归档到 weekly-reports 目录与 SQLite 数据库"""
import glob
import os
import re
import sqlite3
import sys
from datetime import datetime, date
from email import policy
from email.parser import BytesParser
BASE = "/home/yangxuan/.openclaw/workspace-resume/weekly-reports"
INBOUND = "/home/yangxuan/.openclaw/media/inbound"
DB = os.path.join(BASE, "weekly_reports.db")
ARCHIVE_DIR = os.path.join(BASE, "2026")
# 问题标题之后的签名词,用于截断
SIGN_TERMS = ("best regards", "杨轩", "地址", "手机", "邮箱", "yangxuan@")
def decode_b64_part(part):
payload = part.get_payload(decode=True)
if payload is None:
return ""
charset = part.get_content_charset() or "utf-8"
try:
return payload.decode(charset)
except Exception:
return payload.decode("utf-8", errors="replace")
def parse_eml(path):
with open(path, "rb") as f:
msg = BytesParser(policy=policy.default).parse(f)
plain = ""
for part in msg.walk():
if part.get_content_type() == "text/plain":
plain = decode_b64_part(part)
break
return plain, str(msg["Subject"] or "")
def extract_weekly_data(plain):
"""返回 (project, main_task, days, problems)"""
days = {} # key: (yyyy,mm,dd) -> list[item]; 按 ymd 排序
project = ""
main_task = ""
problems = []
cur_ymd = None
in_problem = False
for raw in plain.splitlines():
line = raw.strip()
if not line:
continue
# 项目名称
if line.startswith("项目名称"):
project = re.sub(r"^[📅]*\s*项目名称[:]?\s*", "", line).strip()
continue
if line.startswith("主要任务"):
main_task = re.sub(r"^[📅]*\s*主要任务[:]?\s*", "", line).strip()
continue
# 存在问题 标题
if "存在问题" in line or re.match(r"^\s*问题", line):
in_problem = True
cur_ymd = None
continue
# 其他小标题(下周计划 等)退出问题区(避免误匹配正文,如"本周..."
if re.match(r"^(下周计划|下周计划:|备注[::]|说明[::]|下月计划)", line):
in_problem = False
cur_ymd = None
continue
# 签名开始,停止一切处理
low = line.lower()
if any(s in low for s in SIGN_TERMS):
break
# 日期行:可带 emoji、可带/不带年份
m = re.match(r"^[📅🔹•]?\s*(周一|周二|周三|周四|周五|周六|周日)[((]\s*(\d{4})-(\d{2})-(\d{2})\s*[)]", line)
if not m:
m = re.match(r"^[📅🔹•]?\s*(周一|周二|周三|周四|周五|周六|周日)[((]\s*(\d{2})-(\d{2})\s*[)]", line)
if m:
wd = m.group(1)
if len(m.groups()) == 4:
y, mm, dd = int(m.group(2)), m.group(3), m.group(4)
else:
# 需要年份,用文件主题中的年份,这里用 2026 占位,调用方按主题校正
y = 2026; mm, dd = m.group(2), m.group(3)
cur_ymd = (y, mm, dd, wd)
days.setdefault(cur_ymd, [])
in_problem = False
continue
# 每日明细内容:* 与文字可能被拆成两行,故 cur_ymd 有效时任何非签名行都归入
if in_problem:
# 问题区(仅"存在问题"标题之后)
if line not in ("", "暂无", "None", ""):
problems.append(re.sub(r"^[-*·●▪◦]\s*", "", line).strip())
elif cur_ymd:
item = re.sub(r"^[-*·●▪◦]\s*", "", line).strip()
if item:
days[cur_ymd].append(item)
return project, main_task, days, problems
def main():
files = sorted(glob.glob(os.path.join(INBOUND, "*.eml")))
if not files:
print("未找到 eml 文件")
return
results = []
for path in files:
fname = os.path.basename(path)
m = re.search(r"(\d{4}-\d{2}-\d{2})_(\d{4}-\d{2}-\d{2})", fname)
if not m:
print(f"{fname}: 文件名不含日期,跳过")
continue
start, end = m.group(1), m.group(2)
plain, subject = parse_eml(path)
project, main_task, days, problems = extract_weekly_data(plain)
y0 = int(start[:4])
from datetime import date as _d
iso = _d.fromisoformat(start).isocalendar()
wnum = iso[1]
fn = os.path.join(ARCHIVE_DIR, f"2026-W{wnum:02d}-周报.md")
# 根据项目名确定标题项目代号
proj_code = "G5"
if "G6" in project or "G6" in fname:
proj_code = "G6"
# 构建 Markdown
lines = [f"# {proj_code} 开发周报 (2026-W{wnum:02d})", "",
f"**日期范围:** {start} ~ {end}", "",
"## 基本信息", f"项目名称: {project or '维云智造G5'}", f"主要任务: {main_task}", "",
"## 本周工作内容", ""]
for (y, mm, dd, wd) in sorted(days.keys(), key=lambda x: (x[0], int(x[1]), int(x[2]))):
ymd = f"{y}-{mm}-{dd}"
lines.append(f"{wd}{ymd}")
for item in days[(y, mm, dd, wd)]:
lines.append(f" - {item}")
lines.append("")
lines += ["## 存在问题"]
if problems:
for p in problems:
lines.append(f" - {p}")
else:
lines.append("")
lines += ["", "---", f"*归档时间:{datetime.now().strftime('%Y-%m-%d %H:%M')}*",
"*来源:解析周报邮件 eml 文件*", ""]
md = "\n".join(lines)
os.makedirs(ARCHIVE_DIR, exist_ok=True)
with open(fn, "w") as f:
f.write(md)
# 清理空问题条目(*
print(f"✅ 2026-W{wnum:02d} | {fname[:38]}...")
print(f" 项目={project} | 任务={main_task[:30]} | 天={len(days)} | 问题={problems}")
results.append((wnum, start, end, project, main_task, len(days), len(problems)))
print("\n===== 汇总 =====")
for r in results:
print(f" W{r[0]:02d} ({r[1]}~{r[2]}) | {r[3]} | 天{r[5]} 问题{r[6]}")
if __name__ == "__main__":
main()