story writer backend migration complete, Blog writer SEO and story writer backend migration complete, Blog writer SEO and story writer frontend migration complete

This commit is contained in:
ajaysi
2025-11-13 16:14:26 +05:30
parent 7191c7e7f0
commit 3b9356e2c8
124 changed files with 20055 additions and 1208 deletions

View File

@@ -26,7 +26,7 @@ class OAuthTokenMonitoringTask(Base):
platform = Column(String(50), nullable=False) # 'gsc', 'bing', 'wordpress', 'wix'
# Task Status
status = Column(String(50), default='active') # 'active', 'failed', 'paused'
status = Column(String(50), default='active') # 'active', 'failed', 'paused', 'needs_intervention'
# Execution Tracking
last_check = Column(DateTime, nullable=True)
@@ -34,6 +34,10 @@ class OAuthTokenMonitoringTask(Base):
last_failure = Column(DateTime, nullable=True)
failure_reason = Column(Text, nullable=True)
# Failure Pattern Tracking
consecutive_failures = Column(Integer, default=0) # Count of consecutive failures
failure_pattern = Column(JSON, nullable=True) # JSON storing failure analysis
# Scheduling
next_check = Column(DateTime, nullable=True, index=True) # Next scheduled check time

View File

@@ -27,7 +27,7 @@ class PlatformInsightsTask(Base):
site_url = Column(String(500), nullable=True) # Optional: specific site URL
# Task Status
status = Column(String(50), default='active') # 'active', 'failed', 'paused'
status = Column(String(50), default='active') # 'active', 'failed', 'paused', 'needs_intervention'
# Execution Tracking
last_check = Column(DateTime, nullable=True)
@@ -35,6 +35,10 @@ class PlatformInsightsTask(Base):
last_failure = Column(DateTime, nullable=True)
failure_reason = Column(Text, nullable=True)
# Failure Pattern Tracking
consecutive_failures = Column(Integer, default=0) # Count of consecutive failures
failure_pattern = Column(JSON, nullable=True) # JSON storing failure analysis
# Scheduling
next_check = Column(DateTime, nullable=True, index=True) # Next scheduled check time

View File

@@ -0,0 +1,262 @@
"""
Story Writer Models
Pydantic models for story generation API requests and responses.
"""
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any, Union
class StoryGenerationRequest(BaseModel):
"""Request model for story generation."""
persona: str = Field(..., description="The persona statement for the author")
story_setting: str = Field(..., description="The setting of the story")
character_input: str = Field(..., description="The characters in the story")
plot_elements: str = Field(..., description="The plot elements of the story")
writing_style: str = Field(..., description="The writing style (e.g., Formal, Casual, Poetic, Humorous)")
story_tone: str = Field(..., description="The tone of the story (e.g., Dark, Uplifting, Suspenseful, Whimsical)")
narrative_pov: str = Field(..., description="The narrative point of view (e.g., First Person, Third Person Limited, Third Person Omniscient)")
audience_age_group: str = Field(..., description="The target audience age group (e.g., Children, Young Adults, Adults)")
content_rating: str = Field(..., description="The content rating (e.g., G, PG, PG-13, R)")
ending_preference: str = Field(..., description="The preferred ending (e.g., Happy, Tragic, Cliffhanger, Twist)")
story_length: str = Field(default="Medium", description="Target story length (Short: >1000 words, Medium: >5000 words, Long: >10000 words)")
enable_explainer: bool = Field(default=True, description="Enable explainer features")
enable_illustration: bool = Field(default=True, description="Enable illustration features")
enable_video_narration: bool = Field(default=True, description="Enable story video and narration features")
# Image generation settings
image_provider: Optional[str] = Field(default=None, description="Image generation provider (gemini, huggingface, stability)")
image_width: int = Field(default=1024, description="Image width in pixels")
image_height: int = Field(default=1024, description="Image height in pixels")
image_model: Optional[str] = Field(default=None, description="Image generation model")
# Video generation settings
video_fps: int = Field(default=24, description="Frames per second for video")
video_transition_duration: float = Field(default=0.5, description="Duration of transitions between scenes in seconds")
# Audio generation settings
audio_provider: Optional[str] = Field(default="gtts", description="TTS provider (gtts, pyttsx3)")
audio_lang: str = Field(default="en", description="Language code for TTS")
audio_slow: bool = Field(default=False, description="Whether to speak slowly (gTTS only)")
audio_rate: int = Field(default=150, description="Speech rate (pyttsx3 only)")
class StorySetupGenerationRequest(BaseModel):
"""Request model for AI story setup generation."""
story_idea: str = Field(..., description="Basic story idea or information from the user")
class StorySetupOption(BaseModel):
"""A single story setup option."""
persona: str = Field(..., description="The persona statement for the author")
story_setting: str = Field(..., description="The setting of the story")
character_input: str = Field(..., description="The characters in the story")
plot_elements: str = Field(..., description="The plot elements of the story")
writing_style: str = Field(..., description="The writing style")
story_tone: str = Field(..., description="The tone of the story")
narrative_pov: str = Field(..., description="The narrative point of view")
audience_age_group: str = Field(..., description="The target audience age group")
content_rating: str = Field(..., description="The content rating")
ending_preference: str = Field(..., description="The preferred ending")
story_length: str = Field(default="Medium", description="Target story length (Short: >1000 words, Medium: >5000 words, Long: >10000 words)")
premise: str = Field(..., description="The story premise (1-2 sentences)")
reasoning: str = Field(..., description="Brief reasoning for this setup option")
# Image generation settings
image_provider: Optional[str] = Field(default=None, description="Image generation provider (gemini, huggingface, stability)")
image_width: int = Field(default=1024, description="Image width in pixels")
image_height: int = Field(default=1024, description="Image height in pixels")
image_model: Optional[str] = Field(default=None, description="Image generation model")
# Video generation settings
video_fps: int = Field(default=24, description="Frames per second for video")
video_transition_duration: float = Field(default=0.5, description="Duration of transitions between scenes in seconds")
# Audio generation settings
audio_provider: Optional[str] = Field(default="gtts", description="TTS provider (gtts, pyttsx3)")
audio_lang: str = Field(default="en", description="Language code for TTS")
audio_slow: bool = Field(default=False, description="Whether to speak slowly (gTTS only)")
audio_rate: int = Field(default=150, description="Speech rate (pyttsx3 only)")
class StorySetupGenerationResponse(BaseModel):
"""Response model for story setup generation."""
options: List[StorySetupOption] = Field(..., description="Three story setup options")
success: bool = Field(default=True, description="Whether the generation was successful")
class StoryScene(BaseModel):
"""Model for a story scene."""
scene_number: int = Field(..., description="Scene number")
title: str = Field(..., description="Scene title")
description: str = Field(..., description="Scene description")
image_prompt: str = Field(..., description="Image prompt for scene visualization")
audio_narration: str = Field(..., description="Audio narration text for the scene")
character_descriptions: List[str] = Field(default_factory=list, description="Character descriptions in the scene")
key_events: List[str] = Field(default_factory=list, description="Key events in the scene")
class StoryStartRequest(StoryGenerationRequest):
"""Request model for story start generation."""
premise: str = Field(..., description="The story premise")
outline: Union[str, List[StoryScene], List[Dict[str, Any]]] = Field(..., description="The story outline (text or structured scenes)")
class StoryPremiseResponse(BaseModel):
"""Response model for premise generation."""
premise: str = Field(..., description="Generated story premise")
success: bool = Field(default=True, description="Whether the generation was successful")
task_id: Optional[str] = Field(None, description="Task ID for async operations")
class StoryOutlineResponse(BaseModel):
"""Response model for outline generation."""
outline: Union[str, List[StoryScene]] = Field(..., description="Generated story outline (text or structured scenes)")
success: bool = Field(default=True, description="Whether the generation was successful")
task_id: Optional[str] = Field(None, description="Task ID for async operations")
is_structured: bool = Field(default=False, description="Whether the outline is structured (scenes) or plain text")
class StoryContentResponse(BaseModel):
"""Response model for story content generation."""
story: str = Field(..., description="Generated story content")
premise: Optional[str] = Field(None, description="Story premise")
outline: Optional[str] = Field(None, description="Story outline")
is_complete: bool = Field(default=False, description="Whether the story is complete")
iterations: int = Field(default=0, description="Number of continuation iterations")
success: bool = Field(default=True, description="Whether the generation was successful")
task_id: Optional[str] = Field(None, description="Task ID for async operations")
class StoryFullGenerationResponse(BaseModel):
"""Response model for full story generation."""
premise: str = Field(..., description="Generated story premise")
outline: str = Field(..., description="Generated story outline")
story: str = Field(..., description="Generated complete story")
is_complete: bool = Field(default=False, description="Whether the story is complete")
iterations: int = Field(default=0, description="Number of continuation iterations")
success: bool = Field(default=True, description="Whether the generation was successful")
task_id: Optional[str] = Field(None, description="Task ID for async operations")
class StoryContinueRequest(BaseModel):
"""Request model for continuing story generation."""
premise: str = Field(..., description="The story premise")
outline: Union[str, List[StoryScene], List[Dict[str, Any]]] = Field(..., description="The story outline (text or structured scenes)")
story_text: str = Field(..., description="Current story text to continue from")
persona: str = Field(..., description="The persona statement for the author")
story_setting: str = Field(..., description="The setting of the story")
character_input: str = Field(..., description="The characters in the story")
plot_elements: str = Field(..., description="The plot elements of the story")
writing_style: str = Field(..., description="The writing style")
story_tone: str = Field(..., description="The tone of the story")
narrative_pov: str = Field(..., description="The narrative point of view")
audience_age_group: str = Field(..., description="The target audience age group")
content_rating: str = Field(..., description="The content rating")
ending_preference: str = Field(..., description="The preferred ending")
story_length: str = Field(default="Medium", description="Target story length (Short: >1000 words, Medium: >5000 words, Long: >10000 words)")
class StoryContinueResponse(BaseModel):
"""Response model for story continuation."""
continuation: str = Field(..., description="Generated story continuation")
is_complete: bool = Field(default=False, description="Whether the story is complete (contains IAMDONE)")
success: bool = Field(default=True, description="Whether the generation was successful")
class TaskStatus(BaseModel):
"""Task status model."""
task_id: str = Field(..., description="Task ID")
status: str = Field(..., description="Task status (pending, processing, completed, failed)")
progress: Optional[float] = Field(None, description="Progress percentage (0-100)")
message: Optional[str] = Field(None, description="Progress message")
result: Optional[Dict[str, Any]] = Field(None, description="Task result when completed")
error: Optional[str] = Field(None, description="Error message if failed")
created_at: Optional[str] = Field(None, description="Task creation timestamp")
updated_at: Optional[str] = Field(None, description="Task last update timestamp")
class StoryImageGenerationRequest(BaseModel):
"""Request model for image generation."""
scenes: List[StoryScene] = Field(..., description="List of scenes to generate images for")
provider: Optional[str] = Field(None, description="Image generation provider (gemini, huggingface, stability)")
width: Optional[int] = Field(default=1024, description="Image width")
height: Optional[int] = Field(default=1024, description="Image height")
model: Optional[str] = Field(None, description="Image generation model")
class StoryImageResult(BaseModel):
"""Model for a generated image result."""
scene_number: int = Field(..., description="Scene number")
scene_title: str = Field(..., description="Scene title")
image_filename: str = Field(..., description="Image filename")
image_url: str = Field(..., description="Image URL")
width: int = Field(..., description="Image width")
height: int = Field(..., description="Image height")
provider: str = Field(..., description="Image generation provider")
model: Optional[str] = Field(None, description="Image generation model")
seed: Optional[int] = Field(None, description="Image generation seed")
error: Optional[str] = Field(None, description="Error message if generation failed")
class StoryImageGenerationResponse(BaseModel):
"""Response model for image generation."""
images: List[StoryImageResult] = Field(..., description="List of generated images")
success: bool = Field(default=True, description="Whether the generation was successful")
task_id: Optional[str] = Field(None, description="Task ID for async operations")
class StoryAudioGenerationRequest(BaseModel):
"""Request model for audio generation."""
scenes: List[StoryScene] = Field(..., description="List of scenes to generate audio for")
provider: Optional[str] = Field(default="gtts", description="TTS provider (gtts, pyttsx3)")
lang: Optional[str] = Field(default="en", description="Language code for TTS")
slow: Optional[bool] = Field(default=False, description="Whether to speak slowly (gTTS only)")
rate: Optional[int] = Field(default=150, description="Speech rate (pyttsx3 only)")
class StoryAudioResult(BaseModel):
"""Model for a generated audio result."""
scene_number: int = Field(..., description="Scene number")
scene_title: str = Field(..., description="Scene title")
audio_filename: str = Field(..., description="Audio filename")
audio_url: str = Field(..., description="Audio URL")
provider: str = Field(..., description="TTS provider")
file_size: int = Field(..., description="Audio file size in bytes")
error: Optional[str] = Field(None, description="Error message if generation failed")
class StoryAudioGenerationResponse(BaseModel):
"""Response model for audio generation."""
audio_files: List[StoryAudioResult] = Field(..., description="List of generated audio files")
success: bool = Field(default=True, description="Whether the generation was successful")
task_id: Optional[str] = Field(None, description="Task ID for async operations")
class StoryVideoGenerationRequest(BaseModel):
"""Request model for video generation."""
scenes: List[StoryScene] = Field(..., description="List of scenes to generate video for")
image_urls: List[str] = Field(..., description="List of image URLs for each scene")
audio_urls: List[str] = Field(..., description="List of audio URLs for each scene")
story_title: Optional[str] = Field(default="Story", description="Title of the story")
fps: Optional[int] = Field(default=24, description="Frames per second for video")
transition_duration: Optional[float] = Field(default=0.5, description="Duration of transitions between scenes")
class StoryVideoResult(BaseModel):
"""Model for a generated video result."""
video_filename: str = Field(..., description="Video filename")
video_url: str = Field(..., description="Video URL")
duration: float = Field(..., description="Video duration in seconds")
fps: int = Field(..., description="Frames per second")
file_size: int = Field(..., description="Video file size in bytes")
num_scenes: int = Field(..., description="Number of scenes in the video")
error: Optional[str] = Field(None, description="Error message if generation failed")
class StoryVideoGenerationResponse(BaseModel):
"""Response model for video generation."""
video: StoryVideoResult = Field(..., description="Generated video")
success: bool = Field(default=True, description="Whether the generation was successful")
task_id: Optional[str] = Field(None, description="Task ID for async operations")

View File

@@ -323,4 +323,54 @@ class BillingHistory(Base):
# Metadata
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
class SubscriptionRenewalHistory(Base):
"""Historical record of subscription renewals and expiration events."""
__tablename__ = "subscription_renewal_history"
id = Column(Integer, primary_key=True)
user_id = Column(String(100), nullable=False)
# Subscription Details
plan_id = Column(Integer, ForeignKey('subscription_plans.id'), nullable=False)
plan_name = Column(String(50), nullable=False)
plan_tier = Column(String(20), nullable=False) # e.g., "free", "basic", "pro", "enterprise"
# Period Information
previous_period_start = Column(DateTime, nullable=True) # Start of the previous period (if renewal)
previous_period_end = Column(DateTime, nullable=True) # End of the previous period (when it expired)
new_period_start = Column(DateTime, nullable=False) # Start of the new period (when renewed)
new_period_end = Column(DateTime, nullable=False) # End of the new period
# Billing Cycle
billing_cycle = Column(Enum(BillingCycle), nullable=False) # "monthly" or "yearly"
# Renewal Information
renewal_type = Column(String(20), nullable=False) # "new", "renewal", "upgrade", "downgrade"
renewal_count = Column(Integer, default=0) # Sequential renewal number (1st renewal, 2nd renewal, etc.)
# Previous Subscription Snapshot (before renewal)
previous_plan_name = Column(String(50), nullable=True)
previous_plan_tier = Column(String(20), nullable=True)
# Usage Summary Before Renewal (snapshot)
usage_before_renewal = Column(JSON, nullable=True) # Snapshot of usage before renewal
# Payment Information
payment_amount = Column(Float, default=0.0)
payment_status = Column(String(20), default="pending") # "pending", "paid", "failed"
payment_date = Column(DateTime, nullable=True)
stripe_invoice_id = Column(String(100), nullable=True)
# Metadata
created_at = Column(DateTime, default=datetime.utcnow)
# Relationships
plan = relationship("SubscriptionPlan")
# Indexes for performance
__table_args__ = (
{'mysql_engine': 'InnoDB'},
)

View File

@@ -28,7 +28,7 @@ class WebsiteAnalysisTask(Base):
competitor_id = Column(String(255), nullable=True) # For competitor tasks (domain or identifier)
# Task Status
status = Column(String(50), default='active') # 'active', 'failed', 'paused'
status = Column(String(50), default='active') # 'active', 'failed', 'paused', 'needs_intervention'
# Execution Tracking
last_check = Column(DateTime, nullable=True)
@@ -36,6 +36,10 @@ class WebsiteAnalysisTask(Base):
last_failure = Column(DateTime, nullable=True)
failure_reason = Column(Text, nullable=True)
# Failure Pattern Tracking
consecutive_failures = Column(Integer, default=0) # Count of consecutive failures
failure_pattern = Column(JSON, nullable=True) # JSON storing failure analysis
# Scheduling
next_check = Column(DateTime, nullable=True, index=True) # Next scheduled check time
frequency_days = Column(Integer, default=10) # Recurring frequency in days