feat: image generation integrated into content creation flow
Backend: - When content_types includes "image", generate image via configured image provider (DALL-E, Replicate) after text generation - Image prompt built from character niche + topic + visual style - Graceful fallback: if image generation fails, post is text-only - Post content_type set to "text+image" when image is attached Frontend: - ContentPage preview shows generated image above text when present - Image displayed with full width and border Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -171,12 +171,35 @@ def generate_content(
|
|||||||
text, affiliate_link_dicts, character.topics or []
|
text, affiliate_link_dicts, character.topics or []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Generate image if requested
|
||||||
|
image_url = None
|
||||||
|
content_types = request.content_types if request.content_types else [request.content_type]
|
||||||
|
if "image" in content_types:
|
||||||
|
img_provider_name = _get_setting(db, "image_provider", current_user.id)
|
||||||
|
img_api_key = _get_setting(db, "image_api_key", current_user.id)
|
||||||
|
if img_provider_name and img_api_key:
|
||||||
|
try:
|
||||||
|
img_provider = get_image_provider(img_provider_name, img_api_key)
|
||||||
|
visual_style = character.visual_style or {}
|
||||||
|
style_desc = visual_style.get("description", "")
|
||||||
|
img_prompt = (
|
||||||
|
f"Social media image for a {character.niche} content creator. "
|
||||||
|
f"Topic: {request.topic_hint or text[:100]}. "
|
||||||
|
f"Style: {style_desc} professional, clean, engaging.".strip()
|
||||||
|
)
|
||||||
|
image_url = img_provider.generate(img_prompt, size="1024x1024")
|
||||||
|
except Exception:
|
||||||
|
pass # Image generation failed, continue with text only
|
||||||
|
|
||||||
|
effective_type = "text+image" if image_url else "text"
|
||||||
|
|
||||||
post = Post(
|
post = Post(
|
||||||
batch_id=batch_id,
|
batch_id=batch_id,
|
||||||
character_id=character.id,
|
character_id=character.id,
|
||||||
user_id=current_user.id,
|
user_id=current_user.id,
|
||||||
content_type=request.content_type,
|
content_type=effective_type,
|
||||||
text_content=text,
|
text_content=text,
|
||||||
|
image_url=image_url,
|
||||||
hashtags=hashtags,
|
hashtags=hashtags,
|
||||||
affiliate_links_used=affiliate_links_used,
|
affiliate_links_used=affiliate_links_used,
|
||||||
llm_provider=provider_name,
|
llm_provider=provider_name,
|
||||||
|
|||||||
@@ -442,6 +442,10 @@ export default function ContentPage() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ padding: '1rem', backgroundColor: 'var(--cream)', marginBottom: '1rem' }}>
|
<div style={{ padding: '1rem', backgroundColor: 'var(--cream)', marginBottom: '1rem' }}>
|
||||||
|
{generated.image_url && (
|
||||||
|
<img src={generated.image_url} alt="Immagine generata"
|
||||||
|
style={{ width: '100%', marginBottom: '0.75rem', border: '1px solid var(--border)' }} />
|
||||||
|
)}
|
||||||
<p style={{ fontSize: '0.875rem', whiteSpace: 'pre-wrap', lineHeight: 1.7, color: 'var(--ink)', margin: 0 }}>
|
<p style={{ fontSize: '0.875rem', whiteSpace: 'pre-wrap', lineHeight: 1.7, color: 'var(--ink)', margin: 0 }}>
|
||||||
{generated.text_content}
|
{generated.text_content}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user