- สร้างระบบ 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)
239 lines
8.0 KiB
Python
239 lines
8.0 KiB
Python
#!/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()
|