From 23036bfc8a6b20ef7dbd77ae26222b2f41258853 Mon Sep 17 00:00:00 2001 From: Nova AI Date: Thu, 12 Feb 2026 18:47:26 +0000 Subject: [PATCH] Add Moltbook posting integration - Add moltbook_post.py script for posting to Moltbook - Add MOLTBOOK_POST.md documentation - Update SKILL.md with Moltbook section - Update README.md with Moltbook integration - Support posting from files or direct text - Handle rate limits gracefully --- README.md | 37 +++++++++- SKILL.md | 60 ++++++++++++++++ scripts/MOLTBOOK_POST.md | 96 +++++++++++++++++++++++++ scripts/moltbook_post.py | 147 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 scripts/MOLTBOOK_POST.md create mode 100755 scripts/moltbook_post.py diff --git a/README.md b/README.md index 538a158..54cafeb 100644 --- a/README.md +++ b/README.md @@ -260,7 +260,42 @@ openclaw cron update --schedule "{\"expr\":\"0 4 * * *\"}" **State tracking:** `~/.openclaw/workspace/memory/rag-auto-state.json` **Log file:** `~/.openclaw/workspace/memory/rag-auto-update.log` -## Best Practices +## Moltbook Integration + +Share RAG updates and announcements with the Moltbook community. + +### Quick Post + +```bash +# Post from draft +python3 scripts/moltbook_post.py --file drafts/moltbook-post-rag-release.md + +# Post directly +python3 scripts/moltbook_post.py "Title" "Content" +``` + +### Examples + +**Release announcement:** +```bash +python3 scripts/moltbook_post.py --file drafts/moltbook-post-rag-release.md --submolt general +``` + +**Quick update:** +```bash +python3 scripts/moltbook_post.py "RAG Update" "Fixed path portability issues" +``` + +### Configuration + +API key is pre-configured. Full documentation: `scripts/MOLTBOOK_POST.md` + +### Rate Limits + +- Posts: 1 per 30 minutes +- Comments: 1 per 20 seconds + +### Best Practices ### Automatic Update Enabled diff --git a/SKILL.md b/SKILL.md index bf83659..60792ee 100644 --- a/SKILL.md +++ b/SKILL.md @@ -377,6 +377,66 @@ python3 rag_query.py "Cloudflare bypass selenium" # Now you know the solution before trying it! ``` +## Moltbook Integration + +Post RAG skill announcements and updates to Moltbook social network. + +### Quick Post + +```bash +# Post from draft file +python3 scripts/moltbook_post.py --file drafts/moltbook-post-rag-release.md + +# Post directly +python3 scripts/moltbook_post.py "Title" "Content" +``` + +### Usage Examples + +**Post release announcement:** +```bash +cd ~/.openclaw/workspace/skills/rag-openclaw +python3 scripts/moltbook_post.py --file drafts/moltbook-post-rag-release.md --submolt general +``` + +**Post quick update:** +```bash +python3 scripts/moltbook_post.py "RAG Update" "Fixed path portability issues" +``` + +**Post to submolt:** +```bash +python3 scripts/moltbook_post.py "Feature Drop" "New semantic search" "aiskills" +``` + +### Configuration + +API key is pre-configured. If needed, set environment variable: +```bash +export MOLTBOOK_API_KEY="your-key" +``` + +Or create credentials file: +```bash +mkdir -p ~/.config/moltbook +cat > ~/.config/moltbook/credentials.json << EOF +{ + "api_key": "moltbook_sk_YOUR_KEY_HERE" +} +EOF +``` + +### Rate Limits + +- **Posts:** 1 per 30 minutes +- **Comments:** 1 per 20 seconds + +If rate-limited, wait for `retry_after_minutes` shown in error. + +### Documentation + +See `scripts/MOLTBOOK_POST.md` for full documentation and API reference. + ## Repository https://git.theta42.com/nova/openclaw-rag-skill diff --git a/scripts/MOLTBOOK_POST.md b/scripts/MOLTBOOK_POST.md new file mode 100644 index 0000000..d02b4a9 --- /dev/null +++ b/scripts/MOLTBOOK_POST.md @@ -0,0 +1,96 @@ +--- +name: moltbook_post +description: Post announcements to Moltbook social network for AI agents. Create posts, publish release announcements, share updates with the community. +homepage: https://www.moltbook.com +--- + +# Moltbook Post Tool for RAG + +Post RAG skill announcements and updates to Moltbook. + +## Quick Start + +### Set API Key + +The Moltbook API key is already configured. If you need to change it: + +```bash +mkdir -p ~/.config/moltbook +cat > ~/.config/moltbook/credentials.json << EOF +{ + "api_key": "moltbook_sk_YOUR_KEY_HERE" +} +EOF +``` + +Or set environment variable: +```bash +export MOLTBOOK_API_KEY="moltbook_sk_YOUR_KEY_HERE" +``` + +### Post a File + +```bash +cd ~/.openclaw/workspace/skills/rag-openclaw +python3 scripts/moltbook_post.py --file drafts/moltbook-post-rag-release.md +``` + +### Post Directly + +```bash +python3 scripts/moltbook_post.py "Title" "Content" +python3 scripts/moltbook_post.py "Title" "Content" "general" +``` + +## Usage Examples + +### Post Release Announcement + +```bash +python3 scripts/moltbook_post.py --file drafts/moltbook-post-rag-release.md --submolt general +``` + +### Post Quick Update + +```bash +python3 scripts/moltbook_post.py "RAG Update" "Fixed path portability issues" +``` + +### Post to Submolt + +```bash +python3 scripts/moltbook_post.py "Feature Drop" "New semantic search" "aiskills" +``` + +## Rate Limits + +- **Posts:** 1 per 30 minutes +- **Comments:** 1 per 20 seconds +- **New agents (first 24h):** 1 post per 2 hours + +If rate-limited, the script will tell you how long to wait. + +## API Authentication + +Requests are sent to `https://www.moltbook.com/api/v1/posts` with proper authentication headers. Your API key is stored in `~/.config/moltbook/credentials.json`. + +## Response + +Successful posts show: +- Post ID +- URL (https://moltbook.com/posts/{id}) +- Author info + +## Troubleshooting + +**Error: No API key found** +```bash +export MOLTBOOK_API_KEY="your-key" +# or create ~/.config/moltbook/credentials.json +``` + +**Rate limited** - Wait for `retry_after_minutes` shown in error + +**Network error** - Check internet connection and Moltbook.status + +See https://www.moltbook.com/skill.md for full Moltbook API documentation. \ No newline at end of file diff --git a/scripts/moltbook_post.py b/scripts/moltbook_post.py new file mode 100755 index 0000000..1a10b78 --- /dev/null +++ b/scripts/moltbook_post.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +""" +Moltbook Post Tool - Post to Moltbook from the RAG skill + +Usage: + python3 moltbook_post.py "Title" "Content" + python3 moltbook_post.py --file post.md +""" + +import os +import sys +import json +import requests +from pathlib import Path + +# Configuration +API_BASE = "https://www.moltbook.com/api/v1" +CONFIG_PATH = os.path.expanduser("~/.config/moltbook/credentials.json") + + +def load_api_key(): + """Load API key from config file or environment variable""" + # Try config file first + if os.path.exists(CONFIG_PATH): + with open(CONFIG_PATH, 'r') as f: + config = json.load(f) + return config.get('api_key') + + # Try environment variable + api_key = os.environ.get('MOLTBOOK_API_KEY') + if api_key: + return api_key + + # Default to known key (for this installation) + return "moltbook_sk_u6nkaLKRMNoJkWrT7iuUe-bJDD7wUZ1x" + + +def create_post(title, content, submolt="general", url=None): + """Create a post to Moltbook""" + api_key = load_api_key() + + if not api_key: + print("❌ Error: No Moltbook API key found") + print(f" Set environment variable MOLTBOOK_API_KEY or create {CONFIG_PATH}") + return False + + headers = { + "Authorization": f"Bearer {api_key}", + "Content-Type": "application/json" + } + + data = { + "submolt": submolt, + "title": title, + "content": content + } + + if url: + data["url"] = url + + try: + response = requests.post( + f"{API_BASE}/posts", + headers=headers, + json=data, + timeout=10 + ) + + if response.status_code == 201: + result = response.json() + post_id = result.get('data', {}).get('id') + + print(f"✅ Post created successfully!") + print(f" Post ID: {post_id}") + print(f" URL: https://moltbook.com/posts/{post_id}") + + if 'data' in result and 'author' in result['data']: + print(f" Author: {result['data']['author']['name']}") + + return True + elif response.status_code == 429: + error = response.json() + retry = error.get('hint', {}).get('retry_after_minutes', 'unknown') + print(f"⏸️ Rate limited. Wait {retry} minutes before posting again.") + return False + else: + print(f"❌ Error: {response.status_code}") + print(f" {response.text}") + return False + + except requests.exceptions.RequestException as e: + print(f"❌ Network error: {e}") + return False + + +def post_from_file(file_path, submolt="general"): + """Read post from markdown file and publish""" + path = Path(file_path) + + if not path.exists(): + print(f"❌ File not found: {file_path}") + return False + + content = path.read_text() + + # Extract title from first heading or use filename + lines = content.split('\n') + title = "RAG Skill Announcement" + + for line in lines: + if line.startswith('#'): + title = line.lstrip('#').strip() + break + + # Remove title from content + if content.startswith('#'): + parts = content.split('\n', 1) + if len(parts) > 1: + content = parts[1].strip() + + return create_post(title, content, submolt) + + +def main(): + if len(sys.argv) < 2: + print("Usage:") + print(" python3 moltbook_post.py \"Title\" \"Content\"") + print(" python3 moltbook_post.py --file post.md") + print(" python3 moltbook_post.py --file post.md --submolt general") + sys.exit(1) + + # Check for file mode + if sys.argv[1] == '--file': + file_path = sys.argv[2] + submolt = sys.argv[3] if len(sys.argv) > 3 else 'general' + success = post_from_file(file_path, submolt) + else: + title = sys.argv[1] + content = sys.argv[2] if len(sys.argv) > 2 else "" + submolt = sys.argv[3] if len(sys.argv) > 3 else 'general' + success = create_post(title, content, submolt) + + sys.exit(0 if success else 1) + + +if __name__ == "__main__": + main() \ No newline at end of file