Initial commit: igny8 project

This commit is contained in:
igny8
2025-11-09 10:27:02 +00:00
commit 60b8188111
27265 changed files with 4360521 additions and 0 deletions

View File

@@ -0,0 +1,218 @@
"""
WordPress Integration Service
Handles communication with WordPress sites via REST API
"""
import logging
import requests
from typing import Dict, Any, Optional
from django.conf import settings
logger = logging.getLogger(__name__)
class WordPressClient:
"""
WordPress REST API client for content publishing and sync.
"""
def __init__(self, site_url: str, username: str = None, app_password: str = None):
"""
Initialize WordPress client.
Args:
site_url: WordPress site URL (e.g., https://example.com)
username: WordPress username or application password username
app_password: WordPress application password
"""
self.site_url = site_url.rstrip('/')
self.api_base = f"{self.site_url}/wp-json/wp/v2"
self.igny8_api_base = f"{self.site_url}/wp-json/igny8/v1" # Custom IGNY8 endpoints
self.username = username
self.app_password = app_password
self.session = requests.Session()
# Set up authentication if provided
if username and app_password:
self.session.auth = (username, app_password)
def test_connection(self) -> Dict[str, Any]:
"""
Test connection to WordPress site.
Returns:
Dict with 'success', 'message', 'wp_version'
"""
try:
response = self.session.get(f"{self.api_base}/")
if response.status_code == 200:
data = response.json()
return {
'success': True,
'message': 'Connection successful',
'wp_version': data.get('version', 'Unknown'),
}
return {
'success': False,
'message': f"HTTP {response.status_code}",
'wp_version': None,
}
except Exception as e:
logger.error(f"WordPress connection test failed: {e}")
return {
'success': False,
'message': str(e),
'wp_version': None,
}
def create_post(
self,
title: str,
content: str,
status: str = 'draft',
featured_image_url: Optional[str] = None,
**kwargs
) -> Dict[str, Any]:
"""
Create a new WordPress post.
Args:
title: Post title
content: Post content (HTML or blocks)
status: Post status ('draft', 'publish', 'pending')
featured_image_url: URL of featured image (must be uploaded first)
**kwargs: Additional post fields (excerpt, categories, etc.)
Returns:
Dict with 'success', 'post_id', 'url', 'error'
"""
try:
post_data = {
'title': title,
'content': content,
'status': status,
**kwargs
}
if featured_image_url:
# Convert URL to media ID if needed
media_id = self._get_media_id_from_url(featured_image_url)
if media_id:
post_data['featured_media'] = media_id
response = self.session.post(f"{self.api_base}/posts", json=post_data)
if response.status_code in [200, 201]:
data = response.json()
return {
'success': True,
'post_id': data.get('id'),
'url': data.get('link'),
'error': None,
}
return {
'success': False,
'post_id': None,
'url': None,
'error': f"HTTP {response.status_code}: {response.text}",
}
except Exception as e:
logger.error(f"WordPress post creation failed: {e}")
return {
'success': False,
'post_id': None,
'url': None,
'error': str(e),
}
def upload_image(self, image_url: str, filename: str = None) -> Dict[str, Any]:
"""
Upload an image to WordPress media library.
Args:
image_url: URL of image to upload
filename: Optional filename
Returns:
Dict with 'success', 'media_id', 'url', 'error'
"""
try:
# Download image
img_response = requests.get(image_url)
if img_response.status_code != 200:
return {
'success': False,
'media_id': None,
'url': None,
'error': f"Failed to download image: HTTP {img_response.status_code}",
}
# Upload to WordPress
files = {
'file': (filename or 'image.jpg', img_response.content, img_response.headers.get('content-type', 'image/jpeg'))
}
response = self.session.post(f"{self.api_base}/media", files=files)
if response.status_code in [200, 201]:
data = response.json()
return {
'success': True,
'media_id': data.get('id'),
'url': data.get('source_url'),
'error': None,
}
return {
'success': False,
'media_id': None,
'url': None,
'error': f"HTTP {response.status_code}: {response.text}",
}
except Exception as e:
logger.error(f"WordPress image upload failed: {e}")
return {
'success': False,
'media_id': None,
'url': None,
'error': str(e),
}
def _get_media_id_from_url(self, url: str) -> Optional[int]:
"""Helper to get media ID from URL (if already uploaded)."""
# TODO: Implement media lookup by URL
return None
def sync_settings(self, settings_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Sync settings to WordPress via custom IGNY8 endpoint.
Args:
settings_data: Settings dictionary to sync
Returns:
Dict with 'success', 'message', 'error'
"""
try:
response = self.session.post(
f"{self.igny8_api_base}/sync-settings",
json=settings_data
)
if response.status_code == 200:
return {
'success': True,
'message': 'Settings synced successfully',
'error': None,
}
return {
'success': False,
'message': None,
'error': f"HTTP {response.status_code}: {response.text}",
}
except Exception as e:
logger.error(f"WordPress settings sync failed: {e}")
return {
'success': False,
'message': None,
'error': str(e),
}