Home
Softono
wechat-daily-report-bot

wechat-daily-report-bot

Open source MIT Python
21
Stars
1
Forks
2
Issues
0
Watchers
1 week
Last Commit

About wechat-daily-report-bot

Automate a WeChat group's daily work-report roll-call — start, chase non-submitters, and LLM-summarize for the manager. wxauto + FastAPI + hot-reloadable rules.

Platforms

Web Self-hosted

Languages

Python

Links

WeChat Daily-Report Bot

Automated daily work-report collection for a WeChat work group — post the roll-call → chase non-submitters → AI-summarize for the manager, fully unattended on workdays, and triggerable on demand by a chat command.

CI Python FastAPI Platform LLM License

中文文档见 README.zh-CN.md

Note This is an anonymized portfolio version of a real, in-production project. All company names, department names, people, factories, customers and M&A project names have been replaced with fictional placeholders, and all secrets removed.

Demo

DRY-RUN demo

BOT_DRY_RUN=true — the full start → remind → summarize flow running with no real WeChat (names anonymized).


The problem

A team posts a daily work report every workday using WeChat's native "接龙" (roll-call / chain sign-up) feature. Three chores were done by hand every day:

  1. Start the roll-call at a fixed time.
  2. Chase whoever hasn't submitted (excluding the manager, the bot, and people on leave).
  3. Summarize ten people's raw entries into a clean, management-grade report and send it privately to the manager.

This bot automates all three — accurately, on time, and with a hot-reloadable rule set driving the AI summary.

Features

  • 🚀 Native roll-call — drives WeChat's real #接龙 → edit table → launch flow (not a fake text message), so entries keep their auto-numbering and names.
  • Workday scheduling16:30 start · 17:10 chase · 17:35 summarize, skipping public holidays via chinese-calendar.
  • 🎯 Accurate roll-call parsing — locates the day's roll-call by searching its date (avoids collapsed cards & stale history), parses participants, diffs against the roster.
  • 🙋 Leave-aware chasing — merges all non-submitters into a single multi-@ message; never chases the manager, the bot, or anyone who declared leave before the cutoff.
  • 🧠 LLM summary with hot-reloadable rules — the summarization prompt lives in an external rules file that is re-read on every run; edit the rules and the next summary uses them, no restart/redeploy.
  • 🔁 Model fallback chaingpt-5.4 → gpt-5.4-mini → deepseek-chat-v3 with transient-error retries and region-unavailable fallback.
  • 🔌 Three trigger paths — workday timer, remote control from Telegram via OpenClaw, and an HTTP API (/jielong /cuiban /huizong /status).
  • 🧪 DRY-RUN mode — exercise the API/logic without touching real WeChat. remind and summarize run end-to-end, while start intentionally degrades to a no-op failure because the dry-run stub has no native WeChat roll-call input box (ChatBox.editbox).

Architecture

A clean five-layer separation of concerns:

flowchart TD
    PH["Telegram - you, anywhere"]
    OC["OpenClaw agent - same PC as the bot"]
    T1["Timer - workdays 16:30 / 17:10 / 17:35"]
    T3["HTTP API - /jielong /cuiban /huizong /status"]
    R["openclaw_command_router.py - start / remind / summarize / status"]
    A["api_server.py - FastAPI + scheduler"]
    C["bot_core.py - start / remind / summarize"]
    W["wxauto / wxautox4 - WeChat GUI automation"]
    M["llm_summary.py - hot-reload rules to LLM"]
    RULES[("summary rules: md + txt")]
    LLM[("OpenRouter / DeepSeek")]
    WX[("PC WeChat - group + manager DM")]
    CFG[("config.py - roster / times / copy")]
    PH --> OC
    OC -->|bash wrapper| R
    T1 --> A
    T3 --> A
    R --> A
    A --> C
    C --> W
    C --> M
    M -->|reads each run| RULES
    M --> LLM
    W --> WX
    CFG -->|config| C
    classDef trig fill:#1f6feb,color:#ffffff,stroke:#1f6feb;
    class PH,OC,T1,T3 trig;

Daily flow

sequenceDiagram
    autonumber
    participant S as Trigger
    participant B as bot_core
    participant W as WeChat
    participant L as LLM
    participant M as Manager
    S->>B: 16:30 start
    B->>W: post native roll-call and at-everyone
    S->>B: 17:10 remind
    B->>W: read roll-call, diff vs roster
    B->>W: at-mention pending, merged and leave-aware
    S->>B: 17:35 summarize
    B->>W: extract latest roll-call
    B->>L: roll-call plus hot-reloaded rules
    L-->>B: management-grade summary
    B-->>M: send summary privately
    B->>W: post done receipt to group

Layers map to files: openclaw_command_router.py (command) · api_server.py (API + timer) · bot_core.py (business) · llm_summary.py (model) · wxauto/wxautox4 (WeChat). Full write-up: docs/ARCHITECTURE.md.

Engineering highlights

The interesting part of this project is the robustness work behind GUI automation. A few examples (full list in docs/PITFALLS.md):

  • Force WeChat to the foreground using AttachThreadInput to bypass Windows' foreground-lock — otherwise hotkeys/clicks land on the wrong window.
  • Read collapsed roll-call cards by opening the chat-history search, querying the date, and double-clicking to copy the full text — instead of fragile scroll-and-scrape.
  • Four-level @everyone fallback (native AtAll → simulated input + candidate pick → SendMsg(at=...) → plain text) across WeChat versions.
  • Multi-@ message fix: when @-ing many people, the text would get inserted between names — fixed by sending the mentions with a placeholder, then the message separately.
  • Private-send safety: the summary is sent with a forced who= target so a session-switch glitch can never leak it to the group.
  • Data-driven prompt engineering: the summary rules were distilled by comparing the manager's manual summary (ground truth) against the model's output, day after day — see docs/SUMMARY_RULES.md.

Tech stack

Python 3.10+ · FastAPI · uvicorn · schedule · chinese-calendar · pyautogui · pyperclip · uiautomation · OpenRouter/DeepSeek (LLM) · wxauto/wxautox4 (WeChat backend).

Project structure

wechat-daily-report-bot/
├── api_server.py                # entry point: backend init, FastAPI, timer thread
├── bot_core.py                  # core: start / chase / summarize + all WeChat I/O & robustness
├── llm_summary.py               # LLM summary: provider resolve, rule hot-reload, model fallback
├── config.py                    # config: group, roster, name map, times, copy
├── openclaw_command_router.py   # CLI: Chinese command → core functions → JSON
├── summary_rules.txt            # supplementary rules (hot-updatable)
├── rules/
│   └── summary_fixed_rules.md   # fixed summary rules (hot-reloaded as the LLM system prompt)
├── scripts/                     # OpenClaw remote-trigger patch (Telegram commands)
├── docs/                        # architecture, pitfalls, summary-rule methodology
├── tests/                       # unit tests for the pure parsing/diff functions
├── requirements.txt
└── .env.example

Quick start

# 1) install
pip install -r requirements.txt

# 2) configure (never commit your real .env)
cp .env.example .env      # Windows: copy .env.example .env
#   set OPENROUTER_API_KEY=...   ; keep BOT_DRY_RUN=true to test without real WeChat

# 3) run
python api_server.py
#   → API docs at http://localhost:8000/docs

On a real run, log into PC WeChat first and keep its window visible (this is GUI automation). For full functionality on WeChat 4.x, use the wxautox4 backend.

Triggering

Method How
Timer Auto on workdays: 16:30 start · 17:10 chase · 17:35 summarize
HTTP API GET /jielong · /cuiban · /huizong · /status ; POST /send_msg ; GET/POST /rules
CLI python openclaw_command_router.py start\|remind\|summarize\|status [--json]
Remote (Telegram → OpenClaw) Send start / remind / summarize / status to your OpenClaw assistant from Telegram → it runs on the bot's PC (setup: scripts/repatch_openclaw_no_prefix.ps1)

Remote control (Telegram → OpenClaw)

The bot runs unattended on a Windows PC, but it is driven from a phone:

  1. From Telegram, send a one-word command — start / remind / summarize / status — to OpenClaw, a local AI-assistant agent running on the same PC as the bot.
  2. scripts/repatch_openclaw_no_prefix.ps1 registers those words in OpenClaw and maps each to a bash wrapper that runs python openclaw_command_router.py <action> --json.
  3. The router calls bot_core directly to drive WeChat, and the JSON result flows back to you in Telegram.

So the workday timer covers the routine, while Telegram + OpenClaw gives off-site, on-demand control — fire the summary early, or re-run a chase on a holiday. OpenClaw is an external, optional component; the timer, CLI and HTTP API all work without it.

Updating the summary rules

Edit rules/summary_fixed_rules.md (or summary_rules.txt) — the next summary picks it up automatically; no restart. Point LLM_FIXED_RULES_FILE at any local .md/.txt/.docx.

Tests

pip install pytest
pytest        # unit tests for parsing / roster-diff / message-slicing (no WeChat needed)

Security & disclaimer

  • No secrets are stored in the repo; provide your own via .env (git-ignored).
  • This is GUI automation (RPA) for personal/educational use. Automating IM clients may conflict with the platform's Terms of Service — use responsibly and at your own risk.
  • All business identifiers in this repo are fictional (anonymized from the original project).

License

MIT