Files
ALwrity/ToBeMigrated/integrations/platform_adapters/wix.py
2025-08-06 16:29:49 +05:30

327 lines
11 KiB
Python

"""
Wix platform adapter implementation.
"""
from io import BytesIO
from typing import Dict, Any, Optional, List
from datetime import datetime
import logging
from pathlib import Path
import requests
from .base import PlatformAdapter
from lib.integrations.wix.wix_api_client import WixAPIClient
logger = logging.getLogger(__name__)
class WixAdapter(PlatformAdapter):
"""Wix platform adapter."""
def __init__(self, config: Dict[str, Any]):
"""Initialize Wix adapter with configuration."""
super().__init__(config)
self._validate_config()
self._initialize_client()
def _initialize_client(self) -> None:
"""Initialize Wix API client."""
try:
self.client = WixAPIClient(
api_key=self.config.get('api_key'),
refresh_token=self.config.get('refresh_token'),
site_id=self.config.get('site_id')
)
logger.info("Successfully initialized Wix API client")
except Exception as e:
raise Exception(f"Failed to initialize Wix client: {str(e)}")
async def publish_content(
self,
content: Dict[str, Any],
schedule_time: Optional[datetime] = None
) -> Dict[str, Any]:
"""Publish content to Wix blog."""
try:
# Validate content
validation = await self.validate_content(content)
if not validation.get('success'):
return validation
# Prepare blog post data
post_data = {
'title': content.get('title', ''),
'content': content.get('content', ''),
'excerpt': content.get('excerpt', ''),
'slug': content.get('slug', ''),
'tags': content.get('tags', []),
'categories': content.get('categories', []),
'seo': content.get('seo', {}),
'publish_date': schedule_time.isoformat() if schedule_time else None
}
# Handle media attachments
media_ids = []
if 'media' in content:
for media in content['media']:
media_id = await self._upload_media(media)
if media_id:
media_ids.append(media_id)
# Create blog post
post = self.client.create_post(post_data)
# Add media to post if any
if media_ids:
self.client.add_media_to_post(post['id'], media_ids)
return self._format_success_response({
'id': post['id'],
'title': post['title'],
'url': post['url'],
'created_at': post['created_at']
})
except Exception as e:
return self._format_error_response(
e,
{'content': content, 'schedule_time': schedule_time}
)
async def get_content_status(
self,
content_id: str
) -> Dict[str, Any]:
"""Get status of a blog post."""
try:
post = self.client.get_post(content_id)
return self._format_success_response({
'id': post['id'],
'title': post['title'],
'status': post['status'],
'url': post['url'],
'created_at': post['created_at'],
'updated_at': post['updated_at'],
'published_at': post.get('published_at')
})
except Exception as e:
return self._format_error_response(
e,
{'content_id': content_id}
)
async def delete_content(
self,
content_id: str
) -> Dict[str, Any]:
"""Delete a blog post."""
try:
self.client.delete_post(content_id)
return self._format_success_response({
'id': content_id,
'deleted': True
})
except Exception as e:
return self._format_error_response(
e,
{'content_id': content_id}
)
async def update_content(
self,
content_id: str,
updates: Dict[str, Any]
) -> Dict[str, Any]:
"""Update a blog post."""
try:
post = self.client.update_post(content_id, updates)
return self._format_success_response({
'id': post['id'],
'title': post['title'],
'url': post['url'],
'updated_at': post['updated_at']
})
except Exception as e:
return self._format_error_response(
e,
{
'content_id': content_id,
'updates': updates
}
)
async def get_analytics(
self,
content_id: str,
start_date: Optional[datetime] = None,
end_date: Optional[datetime] = None
) -> Dict[str, Any]:
"""Get analytics for a blog post."""
try:
analytics = self.client.get_post_analytics(
content_id,
start_date,
end_date
)
return self._format_success_response({
'id': content_id,
'metrics': {
'views': analytics.get('views', 0),
'unique_visitors': analytics.get('unique_visitors', 0),
'average_time_on_page': analytics.get('average_time_on_page', 0),
'bounce_rate': analytics.get('bounce_rate', 0)
}
})
except Exception as e:
return self._format_error_response(
e,
{
'content_id': content_id,
'start_date': start_date,
'end_date': end_date
}
)
async def validate_content(
self,
content: Dict[str, Any]
) -> Dict[str, Any]:
"""Validate content before publishing."""
try:
# Check required fields
required_fields = ['title', 'content']
missing_fields = [
field for field in required_fields
if field not in content
]
if missing_fields:
return self._format_error_response(
ValueError(f"Missing required fields: {', '.join(missing_fields)}"),
{'content': content}
)
# Check content length
if len(content['content']) > 100000: # Wix limit
return self._format_error_response(
ValueError("Content exceeds maximum length of 100,000 characters"),
{'content': content}
)
# Check media attachments
media = content.get('media', [])
if len(media) > 20: # Wix limit
return self._format_error_response(
ValueError("Maximum 20 media attachments allowed"),
{'content': content}
)
return self._format_success_response({
'valid': True,
'content': content
})
except Exception as e:
return self._format_error_response(
e,
{'content': content}
)
async def get_optimal_publish_time(
self,
content_type: str,
target_audience: Optional[Dict[str, Any]] = None
) -> datetime:
"""Get optimal publish time for content."""
# Implement optimal time calculation based on:
# - Content type
# - Target audience timezone
# - Historical engagement data
# For now, return current time
return datetime.now()
async def get_platform_limits(
self
) -> Dict[str, Any]:
"""Get Wix platform limits."""
return self._format_success_response({
'content_length': 100000,
'media_attachments': 20,
'tags_per_post': 50,
'categories_per_post': 10,
'rate_limits': {
'posts_per_day': 100,
'media_uploads_per_day': 1000
}
})
async def get_supported_content_types(
self
) -> List[str]:
"""Get list of supported content types."""
return ['BLOG_POST', 'PAGE', 'COLLECTION_ITEM']
async def get_platform_metrics(
self
) -> Dict[str, Any]:
"""Get Wix platform metrics."""
try:
site_stats = self.client.get_site_statistics()
return self._format_success_response({
'total_posts': site_stats.get('total_posts', 0),
'total_views': site_stats.get('total_views', 0),
'total_comments': site_stats.get('total_comments', 0),
'average_engagement': site_stats.get('average_engagement', 0)
})
except Exception as e:
return self._format_error_response(e)
async def _upload_media(
self,
media: Dict[str, Any]
) -> Optional[str]:
"""Upload media to Wix."""
try:
if 'url' in media:
# Download media from URL
response = requests.get(media['url'])
media_file = BytesIO(response.content)
filename = media.get('filename', 'media')
elif 'file' in media:
# Use local file
file_path = Path(media['file'])
media_file = open(file_path, 'rb')
filename = file_path.name
else:
return None
# Upload media
media_id = self.client.upload_media(
file=media_file,
filename=filename,
mime_type=media.get('mime_type')
)
return media_id
except Exception as e:
logger.error(f"Failed to upload media: {str(e)}")
return None
@classmethod
def get_required_config_fields(cls) -> List[str]:
"""Get list of required configuration fields."""
return [
'api_key',
'refresh_token',
'site_id'
]
@classmethod
def get_platform_description(cls) -> str:
"""Get platform description."""
return "Wix platform adapter for managing blog posts and content"
@classmethod
def get_platform_version(cls) -> str:
"""Get platform adapter version."""
return "1.0.0"