commit db8097f7954c0f23b736853971ad93a6f8ec06f1 Author: Kunthawat Greethong Date: Thu Jul 2 11:38:48 2026 +0700 feat: Facebook Status Automation - สร้างระบบ automation สำหรับ Facebook status draft - Two-pass system: sessions → filter → compare → draft - Ban list สำหรับกิจกรรมซ้ำทุกวัน - Compare กับ 10 โพสย้อนหลัง (ไม่โพสซ้ำ) - Draft style: คนทั่วไปอ่านเข้าใจ ไม่ใช้ technical jargon - Cron: รันทุกวัน 20:00 น. Components: - facebook-status-generator.py (script) - SKILL.md (Hermes skill) - README.md (docs) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd0ab5d --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +env/ +venv/ +ENV/ +.venv + +# Hermes +.hermes/ + +# macOS +.DS_Store +.AppleDouble +.LSOverride + +# Logs +*.log + +# Secrets +*.env +.env.local +secrets/ +credentials/ + +# Editor +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Test +test_output/ +tmp/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..9926230 --- /dev/null +++ b/README.md @@ -0,0 +1,128 @@ +# Moreminimore Personal System + +ระบบอัตโนมัติส่วนตัวสำหรับ Kunthawat — เครื่องมือและ automation workflows + +## 📦 Components + +### 1. Facebook Status Automation + +สร้าง Facebook status draft จาก Hermes sessions ใน 24 ชม. ย้อนหลัง + +**วัตถุประสงค์:** สร้าง personal brand ผ่านการอัพเดทสิ่งที่ทำให้คนเห็น (แต่ไม่โพสซ้ำ) + +**ดูเพิ่มเติม:** [`facebook-status-automation/README.md`](./facebook-status-automation/README.md) + +**Files:** +- `facebook-status-automation/facebook-status-generator.py` — script หลัก +- `facebook-status-automation/SKILL.md` — Hermes skill +- `facebook-status-automation/README.md` — เอกสาร + +**Cron:** รันทุกวัน 20:00 น. + +--- + +## 🚀 Setup + +### 1. Clone + +```bash +cd ~/Gitea +git clone https://git.moreminimore.com/kunthawat/moreminimore-personal-system.git +``` + +### 2. Install Skills + +```bash +# Link skill ไป Hermes +ln -s ~/Gitea/moreminimore-personal-system/facebook-status-automation/SKILL.md \ + ~/.hermes/skills/productivity/facebook-status-automation/SKILL.md +``` + +### 3. Create Log File + +```bash +# สร้างไฟล์ log ตั้งต้น +cat > ~/vault/.facebook-status-log.json <<'JSON' +{ + "settings": { + "lookback_posts": 10, + "ban_list": [ + "ai-news-reading", + "morning-news-briefing", + "daily-planning", + "start-my-day", + "end-my-day", + "evening-wrapup", + "cron-model-update", + "cookie-renewal", + "news-curation", + "product-launches-digest" + ] + }, + "posts": [], + "milestones": {} +} +JSON +``` + +### 4. Setup Cron + +```bash +# รันทุกวัน 20:00 น. (8 โมงเย็น) +hermes cron create \ + --name "Facebook Status Draft" \ + --schedule "0 20 * * *" \ + --prompt "รัน facebook-status-automation skill เพื่อสร้าง Facebook status draft จากสิ่งที่ทำวันนี้" \ + --skills facebook-status-automation \ + --deliver telegram +``` + +--- + +## 🛠️ Development + +### Test Run + +```bash +cd ~/Gitea/moreminimore-personal-system/facebook-status-automation +python3 facebook-status-generator.py +``` + +### Update Skill + +แก้ไข `facebook-status-automation/SKILL.md` แล้วรัน: + +```bash +# Reload skill +hermes skills reload facebook-status-automation +``` + +--- + +## 📂 Project Structure + +``` +moreminimore-personal-system/ +├── README.md # เอกสารนี้ +├── .gitignore +└── facebook-status-automation/ + ├── README.md # เอกสารโมดูล + ├── SKILL.md # Hermes skill + └── facebook-status-generator.py # Script (สำหรับ test/debug) +``` + +--- + +## 🔮 Future Components + +- [ ] Blog content automation +- [ ] Email newsletter automation +- [ ] Client report generation +- [ ] Analytics dashboard +- [ ] Ad campaign monitor + +--- + +## 📝 License + +MIT © 2026 Kunthawat diff --git a/facebook-status-automation/README.md b/facebook-status-automation/README.md new file mode 100644 index 0000000..c5f3167 --- /dev/null +++ b/facebook-status-automation/README.md @@ -0,0 +1,119 @@ +# Facebook Status Automation + +ระบบสร้าง Facebook status draft อัตโนมัติจาก Hermes sessions + +## 🎯 วัตถุประสงค์ + +สร้าง personal brand โดย: +- อัพเดทสิ่งที่ทำให้คนเห็น (แต่ไม่โพสซ้ำ) +- เขียนให้คนที่ไม่รู้เรื่อง IT อ่านเข้าใจ +- โชว์ skill + mindset ผ่านงานจริง + +## 📋 Logic + +``` +Sessions 24h → Filter (ban list) → Compare (10 posts) → Draft +``` + +### Ban List + +กิจกรรมที่ทำซ้ำทุกวัน → ไม่ต้องเอามาโพส: +- `ai-news-reading` +- `morning-news-briefing` +- `daily-planning` +- `start-my-day` +- `end-my-day` +- `cron-model-update` +- `cookie-renewal` + +### Comparison Rules + +| เงื่อนไข | ผลลัพธ์ | +|---------|---------| +| อยู่ใน ban list | ❌ skip | +| เรื่องเดิม + โพสวันนี้แล้ว | ❌ skip | +| เรื่องเดิม + ไม่มี change ใหม่ | ❌ skip | +| เรื่องเดิม + มี change ใหม่ | ✅ โพส (แก้ wording) | +| เรื่องใหม่ | ✅ โพส | +| ไม่มีเรื่องน่าสนใจ | 🔕 ไม่โพส | + +## 📂 ไฟล์ + +``` +facebook-status-automation/ +├── facebook-status-generator.py # script หลัก +├── README.md # เอกสารนี้ +└── SKILL.md # Hermes skill (TODO) +``` + +## 🔧 การใช้งาน + +### Test Run (Manual) + +```bash +cd /Users/kunthawat/Gitea/moreminimore-personal-system/facebook-status-automation +python3 facebook-status-generator.py +``` + +### Cron Job (Auto) + +รันทุกวัน 20:00 น. (8 โมงเย็น) + +```bash +hermes cron create \ + --name "Facebook Status Draft" \ + --schedule "0 20 * * *" \ + --script facebook-status-generator.py \ + --deliver telegram +``` + +## 📊 Log File + +`~/vault/.facebook-status-log.json`: + +```json +{ + "settings": { + "lookback_posts": 10, + "ban_list": [...] + }, + "posts": [ + { + "date": "2026-07-02", + "topics": ["ai-news-automation", "moreminimore-service"], + "draft": "...", + "article_link": null + } + ], + "milestones": { + "ai-news-automation": { + "last_posted": "2026-07-02", + "last_change": "2026-06-25" + } + } +} +``` + +## 🎨 Draft Style + +- ไม่มี technical jargon +- เน้นผลลัพธ์/ประโยชน์ +- คนทั่วไปอ่านเข้าใจ +- สั้นกระชับ + +### ✅ ดี + +> วันนี้ปรับระบบ AI ให้สรุปข่าวอัตโนมัติทุกเช้า — ประหยัดเวลา 1 ชม./วัน + +### ❌ ไม่ดี + +> Today I updated the cron job configuration to use the moreminimore-ai model via custom LLM proxy + +## 🔮 TODO + +- [ ] สร้าง Hermes skill +- [ ] เชื่อม session_search จริง (ตอนนี้ mock) +- [ ] ใช้ LLM สรุปกิจกรรม (ตอนนี้ keyword matching) +- [ ] ใช้ humanizer skill ปรับ draft +- [ ] เช็ค blog articles + ใส่ link +- [ ] Support multiple languages diff --git a/facebook-status-automation/SKILL.md b/facebook-status-automation/SKILL.md new file mode 100644 index 0000000..367ef69 --- /dev/null +++ b/facebook-status-automation/SKILL.md @@ -0,0 +1,157 @@ +--- +name: facebook-status-automation +description: "Generate Facebook personal status drafts from recent Hermes sessions. Two-pass system: extract activities from 24h sessions → compare with last 10 posts → output copyable draft or skip if nothing new." +version: 1.0.0 +author: Kunthawat +license: MIT +platforms: [macos, linux] +metadata: + hermes: + tags: [social-media, facebook, personal-brand, automation] + category: productivity +--- + +# Facebook Status Automation + +สร้าง Facebook status draft จาก Hermes sessions ใน 24 ชม. ย้อนหลัง +มุ่งเป้า: **personal brand** สำหรับคนทั่วไปที่ไม่รู้เรื่อง IT + +## When to use + +- ผู้ใช้ขอให้สร้าง Facebook status จากสิ่งที่ทำวันนี้ +- Cron job รันตอน 20:00 ทุกวัน +- ผู้ใช้ถามว่า "วันนี้มีอะไรน่าโพสไหม" + +## Core Logic + +``` +1. session_search(limit=20, sort="newest") → ดึง sessions 24h ย้อนหลัง +2. อ่าน session content → สรุปกิจกรรม +3. Filter: กรอง ban list (กิจกรรมซ้ำทุกวัน) +4. Compare: เปรียบเทียบกับ 10 โพสย้อนหลัง (จาก .facebook-status-log.json) +5. Draft: สร้าง status ถ้ามีเรื่องใหม่ / skip ถ้าไม่มี +``` + +## Ban List + +กิจกรรมที่ทำทุกวัน → ไม่ต้องโพส: + +| Topic | เหตุผล | +|-------|--------| +| ai-news-reading / morning-news-briefing | cron รันทุกวัน | +| daily-planning / start-my-day | cron รันทุกวัน | +| end-my-day / evening-wrapup | cron รันทุกวัน | +| cron-model-update | internal config | +| cookie-renewal | internal maintenance | + +เพิ่ม/ลบได้ใน `~/vault/.facebook-status-log.json` → `settings.ban_list` + +## Comparison Rules + +| เงื่อนไข | ผลลัพธ์ | +|---------|---------| +| อยู่ใน ban list | ❌ skip | +| เรื่องเดิม + โพสวันนี้แล้ว | ❌ skip | +| เรื่องเดิม + ไม่มี change ใหม่ (lookback_posts) | ❌ skip | +| เรื่องเดิม + มี change ใหม่ | ✅ โพส (ปรับ wording) | +| เรื่องใหม่ | ✅ โพส | +| ไม่มีเรื่องน่าสนใจ | 🔕 ไม่โพส → แจ้ง "วันนี้ไม่มีเรื่องน่าโพส" | + +## Steps + +### 1. ดึง Sessions + +``` +session_search(limit=20, sort="newest") +``` + +กรองเฉพาะ sessions ใน 24 ชม. ย้อนหลัง (ไม่ใช่ทุก session) + +### 2. อ่าน + สรุปกิจกรรม + +อ่าน content ของแต่ละ session → สรุปว่า: +- ทำอะไรไปบ้าง +- มี progress/achievement อะไรบ้าง +- มี blog article ไหม (ถ้ามี เก็บ link) + +### 3. Filter Ban List + +เปรียบเทียบ topic กับ ban_list ใน log file +ถ้า match → skip + +### 4. Compare กับ 10 โพสย้อนหลัง + +อ่าน `~/vault/.facebook-status-log.json` +- ดึง posts 10 ตัวล่าสุด +- เช็คว่า topic นี้เคยโพสหรือยัง +- ถ้าเคย → เช็คว่ามี change ใหม่ไหม + +### 5. สร้าง Draft (ถ้าผ่าน) + +เขียน Facebook status: +- ไม่ใช้ technical jargon +- เน้นผลลัพธ์/ประโยชน์สำหรับคนทั่วไป +- สั้น กระชับ +- ใส่ blog link ถ้ามี + +### 6. อัพเดท Log + +บันทึกลง `~/vault/.facebook-status-log.json`: +- เพิ่ม post entry ใหม่ +- อัพเดท milestones + +### 7. Output + +ถ้ามี draft → แสดงให้ user copy +ถ้าไม่มี → แจ้ง "วันนี้ไม่มีเรื่องน่าโพส" + +## Draft Style Guide + +### ✅ เขียนแบบนี้ + +``` +วันนี้ปรับระบบ AI ให้สรุปข่าวอัตโนมัติทุกเช้า — เขียน script ให้ทำงานเองตอน 7 โมง ไม่ต้องนั่งเปิดทีละเว็บ +``` + +### ❌ ไม่เขียนแบบนี้ + +``` +Today I updated the cron job configuration to use the moreminimore-ai model +via custom LLM proxy endpoint for all scheduled tasks +``` + +### Rules + +- เขียนเป็นไทย (หรือภาษาที่ user ต้องการ) +- ไม่ใช้คำ technical (cron, API, script → ใช้คำที่คนทั่วไปเข้าใจ) +- เน้น **สิ่งที่ได้** ไม่ใช่ **สิ่งที่ทำ** ("ประหยัดเวลา" ดีกว่า "ปรับ config") +- ไม่ต้องใส่ timestamp หรือเวลาที่ทำ +- ถ้ามี blog article → ใส่ link ท้ายโพส + +## Files + +| ไฟล์ | ที่อยู่ | หน้าที่ | +|-----|--------|--------| +| Log file | `~/vault/.facebook-status-log.json` | เก็บประวัติ + milestones | +| Script | `~/Gitea/moreminimore-personal-system/facebook-status-automation/facebook-status-generator.py` | Test run / debug | +| Skill | `~/.hermes/skills/productivity/facebook-status-automation/SKILL.md` | ไฟล์นี้ | + +## Cron Setup + +```bash +# รันทุกวัน 20:00 น. +hermes cron create \ + --name "Facebook Status Draft" \ + --schedule "0 20 * * *" \ + --prompt "รัน facebook-status-automation skill" \ + --skills facebook-status-automation \ + --deliver telegram +``` + +## Pitfalls + +1. **sessions 24h ≠ sessions ทั้งหมด** — ต้อง filter เวลาจริง ไม่ใช่ดึงทุก session +2. **ban list ต้องตรง topic ไม่ใช่ substring** — เช่น "morning-news-briefing" ต้องเช็คว่า topic match เต็ม ไม่ใช่แค่มี "morning" อยู่ +3. **draft ต้อง human-readable** — ห้ามมี technical terms หลุดไป +4. **log file ต้อง update ทุกครั้งที่โพส** — ไม่งั้นจะโพสซ้ำ +5. **ถ้าไม่มีเรื่องน่าโพส → ไม่ต้องโพส** — ห้าม forced output diff --git a/facebook-status-automation/facebook-status-generator.py b/facebook-status-automation/facebook-status-generator.py new file mode 100644 index 0000000..e5520b9 --- /dev/null +++ b/facebook-status-automation/facebook-status-generator.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 +""" +Facebook Status Automation +สร้าง Facebook status draft จาก Hermes sessions ใน 24 ชม. ย้อนหลัง +""" + +import json +import sys +from datetime import datetime, timezone, timedelta +from pathlib import Path + +# Hermes tools available in cron context +from hermes_tools import terminal + + +def load_log(log_path): + """โหลดไฟล์ log""" + result = terminal(f"cat {log_path}") + return json.loads(result["output"]) + + +def save_log(log_path, data): + """บันทึกไฟล์ log""" + content = json.dumps(data, indent=2, ensure_ascii=False) + with open(log_path, 'w', encoding='utf-8') as f: + f.write(content) + + +def get_recent_sessions(): + """ดึง sessions ใน 24 ชม. ย้อนหลัง (mock — จริง ๆ ต้อง call session_search)""" + # ใน production: from hermes_tools import session_search + # results = session_search(limit=20, sort="newest") + + # Mock data สำหรับ test + return [ + {"session_id": "20260702_105243_1a22ad", "title": "ปรับ cron ให้ใช้ moreminimore AI", "source": "tui"}, + {"session_id": "20260626_101627_b0c64f", "title": "วางแผน moreminimore-service", "source": "tui"}, + {"session_id": "cron_93fb9da1b231_20260702_090030", "title": "Morning News Briefing", "source": "cron"}, + {"session_id": "cron_437e59dedd0e_20260702_070016", "title": "orbites-start-my-day", "source": "cron"}, + ] + + +def extract_activities(sessions, ban_list): + """ + สกัดกิจกรรมจาก sessions + กรองตาม ban list + + ใน production ต้อง: + 1. อ่าน session content จริง (session_search + scroll) + 2. ใช้ LLM สรุปว่าทำอะไรไปบ้าง + 3. กรอง ban list + + ตอนนี้ mock ไว้ก่อน + """ + activities = [] + + for s in sessions: + title = s["title"].lower() + + # Simple keyword matching (ใน production ใช้ LLM) + if "cron" in title and "model" in title: + activities.append({ + "topic": "cron-model-update", + "description": "ปรับ cron ให้ใช้ moreminimore AI model", + "session": s["title"] + }) + elif "moreminimore-service" in title: + activities.append({ + "topic": "moreminimore-service", + "description": "วางแผน moreminimore-service", + "session": s["title"] + }) + elif "morning news" in title or "briefing" in title: + activities.append({ + "topic": "morning-news-briefing", + "description": "Morning News Briefing รัน", + "session": s["title"] + }) + elif "start-my-day" in title: + activities.append({ + "topic": "start-my-day", + "description": "orbites-start-my-day รัน", + "session": s["title"] + }) + + # กรองตาม ban list + kept = [] + skipped = [] + + for a in activities: + if any(ban in a["topic"] for ban in ban_list): + skipped.append({**a, "reason": "อยู่ใน ban list"}) + else: + kept.append(a) + + return kept, skipped + + +def compare_with_history(candidates, log_data, today): + """เปรียบเทียบกับ 10 โพสย้อนหลัง""" + posts = log_data["posts"] + lookback_posts = posts[-log_data["settings"]["lookback_posts"]:] + milestones = log_data["milestones"] + + final_keep = [] + final_skip = [] + + for candidate in candidates: + topic = candidate["topic"] + + # หาว่าเคยโพสเรื่องนี้ไหม + posted_before = False + last_posted_date = None + + for post in lookback_posts: + if topic in post["topics"]: + posted_before = True + last_posted_date = post["date"] + break + + if not posted_before: + # ไม่เคยโพส → โพสได้ + final_keep.append({**candidate, "reason": "🆕 เรื่องใหม่"}) + else: + # เคยโพสแล้ว + if last_posted_date == today: + # โพสวันนี้แล้ว → SKIP + final_skip.append({**candidate, "reason": f"❌ เคยโพสวันนี้แล้ว"}) + else: + # โพสวันอื่น → ดูว่ามี change ใหม่ไหม + milestone = milestones.get(topic, {}) + last_change = milestone.get("last_change", "") + + if last_change == today: + # มี change วันนี้ → โพสได้ + final_keep.append({**candidate, "reason": f"🔄 มี change ใหม่"}) + else: + # ไม่มี change → SKIP + final_skip.append({**candidate, "reason": f"❌ ไม่มี change ใหม่ (last: {last_change})"}) + + return final_keep, final_skip + + +def create_draft(candidates): + """สร้าง Facebook status draft""" + if not candidates: + return None + + # Simple template (ใน production ใช้ LLM + humanizer) + lines = [] + for c in candidates: + lines.append(c["description"]) + + draft = "\n\n".join(lines) + return draft + + +def update_log(log_data, today, draft, topics): + """อัพเดท log file""" + # เพิ่ม post ใหม่ + log_data["posts"].append({ + "date": today, + "topics": topics, + "draft": draft, + "article_link": None + }) + + # อัพเดท milestones + for topic in topics: + log_data["milestones"][topic] = { + "last_posted": today, + "last_change": today + } + + return log_data + + +def main(): + log_path = Path.home() / "vault" / ".facebook-status-log.json" + today = datetime.now(timezone.utc).strftime("%Y-%m-%d") + + print("=" * 60) + print("📋 Facebook Status Automation") + print("=" * 60) + print(f"Date: {today}") + print() + + # 1. โหลด log + log_data = load_log(log_path) + ban_list = log_data["settings"]["ban_list"] + + # 2. ดึง sessions + print("🔎 Fetching sessions (24h)...") + sessions = get_recent_sessions() + print(f" Found: {len(sessions)} sessions") + + # 3. สกัดกิจกรรม + กรอง ban list + print("\n🚫 Filtering activities...") + kept, skipped = extract_activities(sessions, ban_list) + print(f" Kept: {len(kept)}, Skipped: {len(skipped)}") + + if not kept: + print("\n🔕 No activities after ban filter") + print("=" * 60) + return + + # 4. เปรียบเทียบกับ history + print("\n🔍 Comparing with history...") + final_keep, final_skip = compare_with_history(kept, log_data, today) + print(f" Can post: {len(final_keep)}") + + if not final_keep: + print("\n🔕 วันนี้ไม่มีเรื่องใหม่น่าโพส") + print("\nเหตุผล:") + for item in final_skip: + print(f" • {item['description']}: {item['reason']}") + print("=" * 60) + return + + # 5. สร้าง draft + print("\n📝 Generating draft...") + draft = create_draft(final_keep) + topics = [c["topic"] for c in final_keep] + + # 6. อัพเดท log + log_data = update_log(log_data, today, draft, topics) + save_log(log_path, log_data) + print(" ✅ Log updated") + + # 7. แสดง draft + print("\n" + "=" * 60) + print("📝 DRAFT สำหรับ copy:") + print("=" * 60) + print(draft) + print("=" * 60) + + +if __name__ == "__main__": + main()