Add Slack platform adapter and comprehensive platform skills system
Major Features: - Implemented full Slack channel-bot adapter with Socket Mode - Added 35+ Mastodon platform skills across 7 categories - Created constitution publishing system for Mastodon Slack Adapter (NEW): - Full PlatformAdapter implementation (1071 lines) - Socket Mode for real-time events - 16 channel-scoped governance skills - User group management as channel "roles" - Channel access control and management - Message pinning and moderation - Platform limitations documentation - Comprehensive setup guide (SLACK_SETUP.md) Mastodon Platform Skills (ENHANCED): - Account Moderation (9 skills): suspend, silence, disable, mark sensitive, delete status - Account Management (4 skills): approve, reject, delete data, create account - Report Management (4 skills): assign, unassign, resolve, reopen - Federation Management (4 skills): block/unblock domains, allow/disallow federation - Security Management (4 skills): block IP/email domains - Constitution Management (2 skills): publish constitution, update profile - Documented web-only limitations (role management requires tootctl) Constitution Publishing: - Publish constitution as pinned Mastodon thread - Automatic deprecation of previous versions - Version control with change summaries - Thread splitting for long documents - CLI tool: scripts/publish_constitution.py - Documentation: CONSTITUTION_PUBLISHING.md Configuration & Integration: - Added SlackConfig model with bot_token, app_token, channel_id - Updated PlatformConfig to support type: slack - Added slack-sdk>=3.33.0 dependency - Bot.py now routes to Slack adapter - Updated example config with Slack section Documentation: - SLACK_SETUP.md: Complete Slack setup guide - PLATFORM_SKILLS.md: All 35+ Mastodon skills documented - CONSTITUTION_PUBLISHING.md: Constitution publishing guide - Updated README.md: Merged QUICKSTART, added Slack to supported platforms - Updated PLATFORMS.md: Slack marked as implemented with examples - Updated .gitignore: Added instance-specific state files Security: - All sensitive files properly gitignored - Instance-specific state (.constitution_post_id) excluded - Credentials properly handled in config Breaking Changes: None Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
104
scripts/publish_constitution.py
Executable file
104
scripts/publish_constitution.py
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Helper script to publish constitution to Mastodon.
|
||||
|
||||
Usage:
|
||||
python scripts/publish_constitution.py [--summary "What changed"]
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
# Add src to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from src.govbot.utils.config import load_config
|
||||
from src.govbot.platforms.mastodon import MastodonAdapter
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Publish constitution to Mastodon")
|
||||
parser.add_argument(
|
||||
"--summary",
|
||||
"-s",
|
||||
default="Constitution updated",
|
||||
help="Summary of changes made"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--constitution",
|
||||
"-c",
|
||||
default="constitution.md",
|
||||
help="Path to constitution file (default: constitution.md)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--config",
|
||||
default="config/config.yaml",
|
||||
help="Path to config file (default: config/config.yaml)"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Load constitution
|
||||
constitution_path = Path(args.constitution)
|
||||
if not constitution_path.exists():
|
||||
print(f"❌ Constitution file not found: {constitution_path}")
|
||||
sys.exit(1)
|
||||
|
||||
constitution_text = constitution_path.read_text()
|
||||
print(f"📜 Loaded constitution from {constitution_path} ({len(constitution_text)} chars)")
|
||||
|
||||
# Load config
|
||||
try:
|
||||
config = load_config(args.config)
|
||||
except FileNotFoundError:
|
||||
print(f"❌ Config file not found: {args.config}")
|
||||
print(" Copy config/config.example.yaml to config/config.yaml and configure")
|
||||
sys.exit(1)
|
||||
|
||||
# Connect to Mastodon
|
||||
print(f"🔌 Connecting to {config.platform.mastodon.instance_url}...")
|
||||
|
||||
adapter = MastodonAdapter(config.platform.mastodon.model_dump())
|
||||
|
||||
if not adapter.connect():
|
||||
print("❌ Failed to connect to Mastodon")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"✅ Connected as @{adapter.bot_username}")
|
||||
|
||||
# Publish constitution
|
||||
print(f"\n📤 Publishing constitution...")
|
||||
print(f" Change summary: {args.summary}")
|
||||
|
||||
result = adapter.execute_skill(
|
||||
skill_name="publish_constitution",
|
||||
parameters={
|
||||
"constitution_text": constitution_text,
|
||||
"change_summary": args.summary,
|
||||
},
|
||||
actor="@admin"
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
print(f"\n✅ {result['message']}")
|
||||
print(f"\n📊 Details:")
|
||||
print(f" - Thread length: {result['data']['thread_length']} posts")
|
||||
print(f" - First post ID: {result['data']['first_post_id']}")
|
||||
if result['data'].get('previous_post_id'):
|
||||
print(f" - Previous post ID: {result['data']['previous_post_id']} (deprecated)")
|
||||
|
||||
# Generate profile URL
|
||||
profile_url = f"{adapter.instance_url}/@{adapter.bot_username}"
|
||||
print(f"\n🔗 View at: {profile_url}")
|
||||
else:
|
||||
print(f"\n❌ Failed: {result['message']}")
|
||||
sys.exit(1)
|
||||
|
||||
# Disconnect
|
||||
adapter.disconnect()
|
||||
print("\n✨ Done!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user