igny8-wp int
This commit is contained in:
@@ -818,6 +818,11 @@ class ContentViewSet(SiteSectorModelViewSet):
|
||||
request=request
|
||||
)
|
||||
|
||||
# OPTIMISTIC UPDATE: Set status to published immediately for better UX
|
||||
# The Celery task will update external_id and external_url when WordPress responds
|
||||
content.status = 'published'
|
||||
content.save(update_fields=['status', 'updated_at'])
|
||||
|
||||
# Queue publishing task (same as automated flow)
|
||||
try:
|
||||
result = publish_content_to_wordpress.delay(
|
||||
@@ -825,28 +830,123 @@ class ContentViewSet(SiteSectorModelViewSet):
|
||||
site_integration_id=site_integration.id
|
||||
)
|
||||
|
||||
logger.info(f"[ContentViewSet.publish] Queued Celery task {result.id} for content {content.id}")
|
||||
logger.info(f"[ContentViewSet.publish] Queued Celery task {result.id} for content {content.id}, status set to 'published'")
|
||||
|
||||
return success_response(
|
||||
data={
|
||||
'content_id': content.id,
|
||||
'task_id': result.id,
|
||||
'status': 'queued',
|
||||
'status': 'published',
|
||||
'message': 'Publishing queued - content will be published to WordPress shortly'
|
||||
},
|
||||
message='Content publishing queued successfully',
|
||||
message='Content status updated to published and queued for WordPress',
|
||||
request=request,
|
||||
status_code=status.HTTP_202_ACCEPTED
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[ContentViewSet.publish] Error queuing publish task: {str(e)}", exc_info=True)
|
||||
# Revert status on error
|
||||
content.status = 'review'
|
||||
content.save(update_fields=['status', 'updated_at'])
|
||||
return error_response(
|
||||
error=f"Failed to queue publishing task: {str(e)}",
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
|
||||
@action(detail=True, methods=['get'], url_path='wordpress_status', url_name='wordpress_status')
|
||||
def wordpress_status(self, request, pk=None):
|
||||
"""
|
||||
Get WordPress post status for published content.
|
||||
Calls WordPress REST API to get current status.
|
||||
|
||||
GET /api/v1/writer/content/{id}/wordpress_status/
|
||||
Returns: {
|
||||
'wordpress_status': 'publish'|'draft'|'pending'|null,
|
||||
'external_id': 123,
|
||||
'external_url': 'https://...',
|
||||
'last_checked': '2025-11-30T...'
|
||||
}
|
||||
"""
|
||||
import requests
|
||||
from django.utils import timezone
|
||||
from igny8_core.business.integration.models import SiteIntegration
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
content = self.get_object()
|
||||
|
||||
if not content.external_id:
|
||||
return success_response(
|
||||
data={
|
||||
'wordpress_status': None,
|
||||
'external_id': None,
|
||||
'external_url': None,
|
||||
'message': 'Content not published to WordPress yet'
|
||||
},
|
||||
request=request
|
||||
)
|
||||
|
||||
# Get WordPress integration for this content's site
|
||||
try:
|
||||
site_integration = SiteIntegration.objects.filter(
|
||||
site=content.site,
|
||||
platform='wordpress',
|
||||
is_active=True
|
||||
).first()
|
||||
|
||||
if not site_integration:
|
||||
return error_response(
|
||||
error='No active WordPress integration found',
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
request=request
|
||||
)
|
||||
|
||||
# Call WordPress REST API to get post status
|
||||
wordpress_url = f"{site_integration.site_url}/wp-json/igny8/v1/post-status/{content.external_id}/"
|
||||
headers = {
|
||||
'X-IGNY8-API-KEY': site_integration.api_key,
|
||||
}
|
||||
|
||||
response = requests.get(wordpress_url, headers=headers, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
wp_data = response.json().get('data', {})
|
||||
return success_response(
|
||||
data={
|
||||
'wordpress_status': wp_data.get('post_status'),
|
||||
'external_id': content.external_id,
|
||||
'external_url': content.external_url,
|
||||
'post_title': wp_data.get('post_title'),
|
||||
'post_modified': wp_data.get('post_modified'),
|
||||
'last_checked': timezone.now().isoformat()
|
||||
},
|
||||
request=request
|
||||
)
|
||||
else:
|
||||
logger.error(f"WordPress API error: {response.status_code} - {response.text}")
|
||||
return error_response(
|
||||
error=f'Failed to get WordPress status: {response.status_code}',
|
||||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||||
request=request
|
||||
)
|
||||
|
||||
except requests.RequestException as e:
|
||||
logger.error(f"Request to WordPress failed: {str(e)}")
|
||||
return error_response(
|
||||
error=f'Connection to WordPress failed: {str(e)}',
|
||||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||||
request=request
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting WordPress status: {str(e)}", exc_info=True)
|
||||
return error_response(
|
||||
error=str(e),
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
request=request
|
||||
)
|
||||
|
||||
@action(detail=True, methods=['post'], url_path='unpublish', url_name='unpublish', permission_classes=[IsAuthenticatedAndActive, IsEditorOrAbove])
|
||||
def unpublish(self, request, pk=None):
|
||||
"""
|
||||
|
||||
@@ -58,6 +58,51 @@ def publish_content_to_wordpress(self, content_id: int, site_integration_id: int
|
||||
if len(content.content_html) > 150:
|
||||
excerpt += '...'
|
||||
|
||||
# Get taxonomy terms from ContentTaxonomyMap
|
||||
from igny8_core.business.content.models import ContentTaxonomyMap
|
||||
taxonomy_maps = ContentTaxonomyMap.objects.filter(content=content).select_related('taxonomy')
|
||||
|
||||
# Build categories and tags arrays from taxonomy mappings
|
||||
categories = []
|
||||
tags = []
|
||||
for mapping in taxonomy_maps:
|
||||
tax = mapping.taxonomy
|
||||
if tax:
|
||||
# Add taxonomy term name to categories (will be mapped in WordPress)
|
||||
categories.append(tax.name)
|
||||
|
||||
# Get images from Images model
|
||||
from igny8_core.modules.writer.models import Images
|
||||
featured_image_url = None
|
||||
gallery_images = []
|
||||
|
||||
images = Images.objects.filter(content=content).order_by('position')
|
||||
for image in images:
|
||||
if image.image_type == 'featured' and image.image_url:
|
||||
featured_image_url = image.image_url
|
||||
elif image.image_type == 'in_article' and image.image_url:
|
||||
gallery_images.append({
|
||||
'url': image.image_url,
|
||||
'alt': image.alt_text or '',
|
||||
'position': image.position
|
||||
})
|
||||
|
||||
# Add primary and secondary keywords as tags
|
||||
if content.primary_keyword:
|
||||
tags.append(content.primary_keyword)
|
||||
|
||||
if content.secondary_keywords:
|
||||
if isinstance(content.secondary_keywords, list):
|
||||
tags.extend(content.secondary_keywords)
|
||||
elif isinstance(content.secondary_keywords, str):
|
||||
import json
|
||||
try:
|
||||
keywords = json.loads(content.secondary_keywords)
|
||||
if isinstance(keywords, list):
|
||||
tags.extend(keywords)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
pass
|
||||
|
||||
content_data = {
|
||||
'content_id': content.id,
|
||||
'task_id': task_id,
|
||||
@@ -75,15 +120,18 @@ def publish_content_to_wordpress(self, content_id: int, site_integration_id: int
|
||||
'seo_description': content.meta_description or '',
|
||||
'primary_keyword': content.primary_keyword or '',
|
||||
'secondary_keywords': content.secondary_keywords or [],
|
||||
# Content model has no featured_image field
|
||||
'featured_image_url': None,
|
||||
# Send featured image URL from Images model
|
||||
'featured_image_url': featured_image_url,
|
||||
'gallery_images': gallery_images,
|
||||
# Send cluster and sector IDs (Content has ForeignKey to cluster, not many-to-many)
|
||||
'cluster_id': content.cluster.id if content.cluster else None,
|
||||
'sector_id': content.sector.id if content.sector else None,
|
||||
# Content model has no direct sectors/clusters array or tags
|
||||
# Send categories and tags from taxonomy mappings and keywords
|
||||
'categories': categories,
|
||||
'tags': tags,
|
||||
# Keep for backward compatibility
|
||||
'sectors': [],
|
||||
'clusters': [],
|
||||
'tags': []
|
||||
'clusters': []
|
||||
}
|
||||
|
||||
# Call WordPress REST API
|
||||
|
||||
Reference in New Issue
Block a user