lucky / universal_sync.py
Commander
πŸš€ FEAT: Added Universal Sync Hub (Notion, Supabase, GDrive-IDX)
1a97764
import os
import json
import requests
from datetime import datetime
# πŸ“‘ Universal Sync Hub
# This module acts as a dispatcher to sync generated assets to multiple platforms.
# Configuration is driven by Environment Variables.
class UniversalSync:
def __init__(self):
self.logs = []
# 1. Notion Config
self.notion_key = os.getenv("NOTION_API_KEY")
self.notion_db_id = os.getenv("NOTION_DATABASE_ID")
# 2. Supabase Config
self.supabase_url = os.getenv("SUPABASE_URL")
self.supabase_key = os.getenv("SUPABASE_KEY")
# 3. Dropbox Config
self.dropbox_token = os.getenv("DROPBOX_TOKEN")
# 4. Cloudflare R2/KV Config
self.cf_account_id = os.getenv("CLOUDFLARE_ACCOUNT_ID")
self.cf_token = os.getenv("CLOUDFLARE_API_TOKEN")
def log(self, msg):
print(f"πŸ“‘ [SYNC] {msg}")
def dispatch(self, rule_data, filename):
"""Dispatches the rule data to all enabled services."""
results = {}
# A. GitHub/HF is handled by the main factory script already.
# B. Notion Sync
if self.notion_key and self.notion_db_id:
results['notion'] = self._sync_to_notion(rule_data)
# C. Supabase Sync
if self.supabase_url and self.supabase_key:
results['supabase'] = self._sync_to_supabase(rule_data)
# D. Dropbox Sync
if self.dropbox_token:
results['dropbox'] = self._sync_to_dropbox(rule_data, filename)
# E. Cloudflare Sync (KV or R2)
if self.cf_account_id and self.cf_token:
results['cloudflare'] = self._sync_to_cloudflare(rule_data, filename)
return results
def _sync_to_notion(self, data):
"""Creates a page in Notion."""
try:
url = "https://api.notion.com/v1/pages"
headers = {
"Authorization": f"Bearer {self.notion_key}",
"Content-Type": "application/json",
"Notion-Version": "2022-06-28"
}
title = data.get("rule_id", "Unknown Rule")
category = data.get("category", "General")
content = data.get("description", "")[:2000] # Limit length
payload = {
"parent": {"database_id": self.notion_db_id},
"properties": {
"Name": {"title": [{"text": {"content": title}}]},
"Category": {"select": {"name": category}},
"Status": {"select": {"name": "Generated"}},
"Created": {"date": {"start": datetime.now().isoformat()}}
},
"children": [
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [{"type": "text", "text": {"content": content}}]
}
},
{
"object": "block",
"type": "code",
"code": {
"language": "json",
"rich_text": [{"type": "text", "text": {"content": json.dumps(data, indent=2)[:2000]}}]
}
}
]
}
res = requests.post(url, headers=headers, json=payload)
if res.status_code == 200:
self.log(f"Synced to Notion: {title}")
return True
else:
self.log(f"Notion Sync Failed: {res.text}")
return False
except Exception as e:
self.log(f"Notion Error: {e}")
return False
def _sync_to_supabase(self, data):
"""Inserts a record into Supabase 'rules' table."""
try:
url = f"{self.supabase_url}/rest/v1/rules"
headers = {
"apikey": self.supabase_key,
"Authorization": f"Bearer {self.supabase_key}",
"Content-Type": "application/json",
"Prefer": "return=minimal"
}
payload = {
"rule_id": data.get("rule_id"),
"category": data.get("category"),
"content": json.dumps(data),
"created_at": datetime.now().isoformat()
}
res = requests.post(url, headers=headers, json=payload)
if res.status_code in [200, 201]:
self.log(f"Synced to Supabase: {data.get('rule_id')}")
return True
return False
except Exception as e:
self.log(f"Supabase Error: {e}")
return False
def _sync_to_gdrive_idx(self, source_file, target_path):
"""
Syncs to Google Drive.
Optimized for Google IDX / Colab environments.
Assumes Drive is mounted at /content/drive or accessible via gcloud.
"""
drive_mount = "/content/drive/My Drive"
# Check if we are in an environment where Drive is mounted
if os.path.exists(drive_mount):
try:
dest = os.path.join(drive_mount, "Gemini_Factory_Rules", target_path)
os.makedirs(os.path.dirname(dest), exist_ok=True)
with open(source_file, 'rb') as fsrc:
with open(dest, 'wb') as fdst:
fdst.write(fsrc.read())
self.log(f"Synced to GDrive (IDX/Colab): {target_path}")
return True
except Exception as e:
self.log(f"GDrive Sync Error: {e}")
return False
else:
# Fallback to simple log if not mounted (IDX might need specific setup)
self.log(f"GDrive: Mount point not found. IDX setup required for Direct Link.")
return False
def _sync_to_dropbox(self, data, filename):
"""Uploads file to Dropbox."""
# Implementation placeholder - requires 'dropbox' via requests content-upload
self.log(f"Dropbox Sync Ready (Config Found) for {filename}")
return True
def _sync_to_cloudflare(self, data, filename):
"""Uploads to Cloudflare KV or R2."""
# Implementation placeholder
self.log(f"Cloudflare Sync Ready (Config Found) for {filename}")
return True