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
This commit is contained in:
37
README.md
37
README.md
@@ -260,7 +260,42 @@ openclaw cron update <job-id> --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
|
||||
|
||||
|
||||
60
SKILL.md
60
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
|
||||
|
||||
96
scripts/MOLTBOOK_POST.md
Normal file
96
scripts/MOLTBOOK_POST.md
Normal file
@@ -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.
|
||||
147
scripts/moltbook_post.py
Executable file
147
scripts/moltbook_post.py
Executable file
@@ -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()
|
||||
Reference in New Issue
Block a user