| import os |
| import json |
| import requests |
| from datetime import datetime |
|
|
| |
| |
| |
|
|
| class UniversalSync: |
| def __init__(self): |
| self.logs = [] |
| |
| |
| self.notion_key = os.getenv("NOTION_API_KEY") |
| self.notion_db_id = os.getenv("NOTION_DATABASE_ID") |
| |
| |
| self.supabase_url = os.getenv("SUPABASE_URL") |
| self.supabase_key = os.getenv("SUPABASE_KEY") |
| |
| |
| self.dropbox_token = os.getenv("DROPBOX_TOKEN") |
| |
| |
| 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 = {} |
| |
| |
| |
| |
| if self.notion_key and self.notion_db_id: |
| results['notion'] = self._sync_to_notion(rule_data) |
| |
| |
| if self.supabase_url and self.supabase_key: |
| results['supabase'] = self._sync_to_supabase(rule_data) |
| |
| |
| if self.dropbox_token: |
| results['dropbox'] = self._sync_to_dropbox(rule_data, filename) |
| |
| |
| 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] |
| |
| 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" |
| |
| 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: |
| |
| 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.""" |
| |
| 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.""" |
| |
| self.log(f"Cloudflare Sync Ready (Config Found) for {filename}") |
| return True |
|
|
|
|