feat: multi-platform generation + custom confirm modal + per-platform tabs
Backend: - /generate now returns array of posts (one per platform selected) - Each post generated with platform-specific LLM prompt and char limits - Monthly counter incremented by number of platforms Frontend: - ConfirmModal: reusable Editorial Fresh modal replaces ugly browser confirm() - ContentPage: platform tabs when multiple posts, switch between variants - ContentPage: generatedPosts array state replaces single generated - ContentArchive: uses ConfirmModal for delete confirmation - Platform chips filtered by plan (Freemium: IG/FB only) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,14 +45,13 @@ def _get_setting(db: Session, key: str, user_id: int = None) -> str | None:
|
||||
return setting.value
|
||||
|
||||
|
||||
@router.post("/generate", response_model=PostResponse)
|
||||
@router.post("/generate", response_model=list[PostResponse])
|
||||
def generate_content(
|
||||
request: GenerateContentRequest,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""Generate content for a character using LLM."""
|
||||
# Validate character belongs to user
|
||||
"""Generate content for a character using LLM. One post per platform."""
|
||||
character = (
|
||||
db.query(Character)
|
||||
.filter(Character.id == request.character_id, Character.user_id == current_user.id)
|
||||
@@ -61,6 +60,9 @@ def generate_content(
|
||||
if not character:
|
||||
raise HTTPException(status_code=404, detail="Character not found")
|
||||
|
||||
# Determine platforms to generate for
|
||||
platforms = request.platforms if request.platforms else [request.platform]
|
||||
|
||||
# Check monthly post limit
|
||||
first_of_month = date.today().replace(day=1)
|
||||
if current_user.posts_reset_date != first_of_month:
|
||||
@@ -68,11 +70,20 @@ def generate_content(
|
||||
current_user.posts_reset_date = first_of_month
|
||||
db.commit()
|
||||
|
||||
allowed, msg = check_limit(current_user, "posts_per_month", current_user.posts_generated_this_month or 0)
|
||||
current_count = current_user.posts_generated_this_month or 0
|
||||
allowed, msg = check_limit(current_user, "posts_per_month", current_count)
|
||||
if not allowed:
|
||||
raise HTTPException(status_code=403, detail={"message": msg, "upgrade_required": True})
|
||||
|
||||
# Get LLM settings (user-specific first, then global)
|
||||
# Also check if we have room for all platforms
|
||||
allowed_after, msg_after = check_limit(current_user, "posts_per_month", current_count + len(platforms) - 1)
|
||||
if not allowed_after:
|
||||
raise HTTPException(status_code=403, detail={
|
||||
"message": f"Non hai abbastanza post rimanenti per generare su {len(platforms)} piattaforme. {msg_after}",
|
||||
"upgrade_required": True,
|
||||
})
|
||||
|
||||
# Get LLM settings
|
||||
provider_name = request.provider or _get_setting(db, "llm_provider", current_user.id)
|
||||
api_key = _get_setting(db, "llm_api_key", current_user.id)
|
||||
model = request.model or _get_setting(db, "llm_model", current_user.id)
|
||||
@@ -94,7 +105,6 @@ def generate_content(
|
||||
},
|
||||
)
|
||||
|
||||
# Build character dict for content service
|
||||
char_dict = {
|
||||
"name": character.name,
|
||||
"niche": character.niche,
|
||||
@@ -102,22 +112,11 @@ def generate_content(
|
||||
"tone": character.tone or "professional",
|
||||
}
|
||||
|
||||
# Create LLM provider and generate text
|
||||
base_url = _get_setting(db, "llm_base_url", current_user.id)
|
||||
llm = get_llm_provider(provider_name, api_key, model, base_url=base_url)
|
||||
text = generate_post_text(
|
||||
character=char_dict,
|
||||
llm_provider=llm,
|
||||
platform=request.effective_platform,
|
||||
topic_hint=request.topic_hint,
|
||||
brief=request.brief,
|
||||
)
|
||||
|
||||
# Generate hashtags
|
||||
hashtags = generate_hashtags(text, llm, request.effective_platform)
|
||||
|
||||
# Handle affiliate links
|
||||
affiliate_links_used: list[dict] = []
|
||||
# Preload affiliate links once
|
||||
affiliate_link_dicts: list[dict] = []
|
||||
if request.include_affiliates:
|
||||
links = (
|
||||
db.query(AffiliateLink)
|
||||
@@ -128,39 +127,51 @@ def generate_content(
|
||||
)
|
||||
.all()
|
||||
)
|
||||
if links:
|
||||
link_dicts = [
|
||||
{
|
||||
"url": link.url,
|
||||
"label": link.name,
|
||||
"keywords": link.topics or [],
|
||||
}
|
||||
for link in links
|
||||
]
|
||||
affiliate_link_dicts = [
|
||||
{"url": link.url, "label": link.name, "keywords": link.topics or []}
|
||||
for link in links
|
||||
]
|
||||
|
||||
# Generate one post per platform
|
||||
posts_created: list[Post] = []
|
||||
for platform in platforms:
|
||||
text = generate_post_text(
|
||||
character=char_dict,
|
||||
llm_provider=llm,
|
||||
platform=platform,
|
||||
topic_hint=request.topic_hint,
|
||||
brief=request.brief,
|
||||
)
|
||||
|
||||
hashtags = generate_hashtags(text, llm, platform)
|
||||
|
||||
affiliate_links_used: list[dict] = []
|
||||
if affiliate_link_dicts:
|
||||
text, affiliate_links_used = inject_affiliate_links(
|
||||
text, link_dicts, character.topics or []
|
||||
text, affiliate_link_dicts, character.topics or []
|
||||
)
|
||||
|
||||
# Create post record
|
||||
post = Post(
|
||||
character_id=character.id,
|
||||
user_id=current_user.id,
|
||||
content_type=request.content_type,
|
||||
text_content=text,
|
||||
hashtags=hashtags,
|
||||
affiliate_links_used=affiliate_links_used,
|
||||
llm_provider=provider_name,
|
||||
llm_model=model,
|
||||
platform_hint=request.platform,
|
||||
status="draft",
|
||||
)
|
||||
db.add(post)
|
||||
post = Post(
|
||||
character_id=character.id,
|
||||
user_id=current_user.id,
|
||||
content_type=request.content_type,
|
||||
text_content=text,
|
||||
hashtags=hashtags,
|
||||
affiliate_links_used=affiliate_links_used,
|
||||
llm_provider=provider_name,
|
||||
llm_model=model,
|
||||
platform_hint=platform,
|
||||
status="draft",
|
||||
)
|
||||
db.add(post)
|
||||
posts_created.append(post)
|
||||
|
||||
# Increment monthly counter
|
||||
current_user.posts_generated_this_month = (current_user.posts_generated_this_month or 0) + 1
|
||||
# Increment monthly counter by number of posts generated
|
||||
current_user.posts_generated_this_month = current_count + len(platforms)
|
||||
db.commit()
|
||||
db.refresh(post)
|
||||
return post
|
||||
for post in posts_created:
|
||||
db.refresh(post)
|
||||
return posts_created
|
||||
|
||||
|
||||
@router.post("/generate-image", response_model=PostResponse)
|
||||
|
||||
Reference in New Issue
Block a user