Compare commits

..

1 Commits

Author SHA1 Message Date
ي
af5a6e0ee3 Add podcast-only demo startup flag and CLI toggle 2026-03-30 06:56:57 +05:30
2 changed files with 178 additions and 145 deletions

View File

@@ -48,7 +48,8 @@ load_dotenv(backend_dir / '.env') # backend/.env
load_dotenv(project_root / '.env') # root .env (fallback) load_dotenv(project_root / '.env') # root .env (fallback)
load_dotenv() # CWD .env (fallback) load_dotenv() # CWD .env (fallback)
PODCAST_ONLY_DEMO_MODE = os.getenv("PODCAST_ONLY_DEMO_MODE", "false").lower() in {"1", "true", "yes", "on"} # Feature flags (read early so app wiring can rely on a single source of truth)
PODCAST_ONLY_DEMO_MODE = os.getenv("PODCAST_ONLY_DEMO_MODE", "false").lower() == "true"
# Set up clean logging for end users # Set up clean logging for end users
from logging_config import setup_clean_logging from logging_config import setup_clean_logging
@@ -112,8 +113,7 @@ from services.startup_health import (
# Import OAuth token monitoring routes # Import OAuth token monitoring routes
from api.oauth_token_monitoring_routes import router as oauth_token_monitoring_router from api.oauth_token_monitoring_routes import router as oauth_token_monitoring_router
if not PODCAST_ONLY_DEMO_MODE: # Import SEO Dashboard endpoints
# Import SEO Dashboard endpoints only when non-demo features are enabled
from api.seo_dashboard import ( from api.seo_dashboard import (
get_seo_dashboard_data, get_seo_dashboard_data,
get_seo_health_score, get_seo_health_score,
@@ -262,17 +262,12 @@ async def onboarding_status():
return onboarding_manager.get_onboarding_status() return onboarding_manager.get_onboarding_status()
# Include routers using modular utilities # Include routers using modular utilities
if not PODCAST_ONLY_DEMO_MODE:
router_manager.include_core_routers() router_manager.include_core_routers()
router_manager.include_optional_routers() router_manager.include_optional_routers()
else:
logger.info("PODCAST_ONLY_DEMO_MODE enabled: including only podcast and subscription feature routers.")
app.include_router(subscription_router)
# Include assets serving router (must be mounted to serve generated images) # Include assets serving router (must be mounted to serve generated images)
app.include_router(assets_serving_router) app.include_router(assets_serving_router)
if not PODCAST_ONLY_DEMO_MODE:
# SEO Dashboard endpoints # SEO Dashboard endpoints
@app.get("/api/seo-dashboard/data") @app.get("/api/seo-dashboard/data")
async def seo_dashboard_data(): async def seo_dashboard_data():
@@ -340,6 +335,8 @@ if not PODCAST_ONLY_DEMO_MODE:
"""Refresh analytics data by invalidating cache and fetching fresh data.""" """Refresh analytics data by invalidating cache and fetching fresh data."""
return await refresh_analytics_data(current_user, site_url) return await refresh_analytics_data(current_user, site_url)
@app.get("/api/seo-dashboard/onboarding-task-health") @app.get("/api/seo-dashboard/onboarding-task-health")
async def onboarding_task_health_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None): async def onboarding_task_health_endpoint(current_user: dict = Depends(get_current_user), site_url: str = None):
"""Get consolidated health for onboarding-scheduled SEO tasks.""" """Get consolidated health for onboarding-scheduled SEO tasks."""
@@ -353,17 +350,31 @@ if not PODCAST_ONLY_DEMO_MODE:
# Phase 2B: Semantic health monitoring endpoint (24-hour polling) # Phase 2B: Semantic health monitoring endpoint (24-hour polling)
@app.get("/api/seo-dashboard/semantic-health") @app.get("/api/seo-dashboard/semantic-health")
async def semantic_health_endpoint(current_user: dict = Depends(get_current_user)): async def semantic_health_endpoint(current_user: dict = Depends(get_current_user)):
"""Get real-time semantic health metrics for content and competitors.""" """
Get real-time semantic health metrics for content and competitors.
This endpoint provides Phase 2B semantic intelligence monitoring data.
Returns semantic health score, status, and recommendations.
Data is cached and updated every 24 hours via scheduler.
"""
return await get_semantic_health(current_user) return await get_semantic_health(current_user)
@app.get("/api/seo-dashboard/cache-stats") @app.get("/api/seo-dashboard/cache-stats")
async def semantic_cache_stats_endpoint(current_user: dict = Depends(get_current_user)): async def semantic_cache_stats_endpoint(current_user: dict = Depends(get_current_user)):
"""Get semantic cache performance statistics.""" """
Get semantic cache performance statistics.
Returns hit rate, memory usage, and eviction counts.
"""
return await get_semantic_cache_stats(current_user) return await get_semantic_cache_stats(current_user)
@app.get("/api/seo-dashboard/sif-health") @app.get("/api/seo-dashboard/sif-health")
async def sif_indexing_health_endpoint(current_user: dict = Depends(get_current_user)): async def sif_indexing_health_endpoint(current_user: dict = Depends(get_current_user)):
"""Get SIF indexing health summary for the current user.""" """
Get SIF indexing health summary for the current user.
Used by the Semantic Indexing Status widget on the dashboard.
"""
return await get_sif_indexing_health(current_user) return await get_sif_indexing_health(current_user)
# Comprehensive SEO Analysis endpoints # Comprehensive SEO Analysis endpoints
@@ -397,9 +408,25 @@ if not PODCAST_ONLY_DEMO_MODE:
"""Run AI-powered SEO analysis on selected URLs.""" """Run AI-powered SEO analysis on selected URLs."""
return await analyze_urls_ai(request, current_user) return await analyze_urls_ai(request, current_user)
# Centralized mode helpers for router wiring.
# Keep all mode decisions in this section to avoid scattered env checks.
def is_podcast_only_demo_mode() -> bool:
return PODCAST_ONLY_DEMO_MODE
def should_include_non_podcast_routers() -> bool:
return not is_podcast_only_demo_mode()
# Include Podcast Maker router (available in all modes)
from api.podcast.router import router as podcast_router
app.include_router(podcast_router)
if should_include_non_podcast_routers():
# Include platform analytics router # Include platform analytics router
from routers.platform_analytics import router as platform_analytics_router from routers.platform_analytics import router as platform_analytics_router
app.include_router(platform_analytics_router) app.include_router(platform_analytics_router)
# Include Bing Analytics Storage router to expose storage-backed endpoints # Include Bing Analytics Storage router to expose storage-backed endpoints
from routers.bing_analytics_storage import router as bing_analytics_storage_router from routers.bing_analytics_storage import router as bing_analytics_storage_router
app.include_router(bing_analytics_storage_router) app.include_router(bing_analytics_storage_router)
@@ -412,11 +439,6 @@ if not PODCAST_ONLY_DEMO_MODE:
from api.content_assets.router import router as content_assets_router from api.content_assets.router import router as content_assets_router
app.include_router(content_assets_router) app.include_router(content_assets_router)
# Include Podcast Maker router
from api.podcast.router import router as podcast_router
app.include_router(podcast_router)
if not PODCAST_ONLY_DEMO_MODE:
# Include YouTube Creator Studio router # Include YouTube Creator Studio router
from api.youtube.router import router as youtube_router from api.youtube.router import router as youtube_router
app.include_router(youtube_router, prefix="/api") app.include_router(youtube_router, prefix="/api")
@@ -440,6 +462,8 @@ if not PODCAST_ONLY_DEMO_MODE:
# Today workflow routes # Today workflow routes
from api.today_workflow import router as today_workflow_router from api.today_workflow import router as today_workflow_router
app.include_router(today_workflow_router) app.include_router(today_workflow_router)
else:
logger.info("PODCAST_ONLY_DEMO_MODE is enabled: non-podcast routers are not registered.")
# Setup frontend serving using modular utilities # Setup frontend serving using modular utilities
frontend_serving.setup_frontend_serving() frontend_serving.setup_frontend_serving()

View File

@@ -298,6 +298,11 @@ def main():
parser.add_argument("--dev", action="store_true", help="Enable development mode (auto-reload)") parser.add_argument("--dev", action="store_true", help="Enable development mode (auto-reload)")
parser.add_argument("--production", action="store_true", help="Enable production mode (optimized for deployment)") parser.add_argument("--production", action="store_true", help="Enable production mode (optimized for deployment)")
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging for debugging") parser.add_argument("--verbose", action="store_true", help="Enable verbose logging for debugging")
parser.add_argument(
"--podcast-only-demo",
action="store_true",
help="Enable podcast-only demo mode (sets PODCAST_ONLY_DEMO_MODE=true before app startup)",
)
args = parser.parse_args() args = parser.parse_args()
# Determine mode # Determine mode
@@ -307,6 +312,8 @@ def main():
# Set global verbose flag for utilities # Set global verbose flag for utilities
os.environ["ALWRITY_VERBOSE"] = "true" if verbose_mode else "false" os.environ["ALWRITY_VERBOSE"] = "true" if verbose_mode else "false"
if args.podcast_only_demo:
os.environ["PODCAST_ONLY_DEMO_MODE"] = "true"
print("[*] ALwrity Backend Server") print("[*] ALwrity Backend Server")
print("=" * 40) print("=" * 40)
@@ -314,6 +321,8 @@ def main():
print(f"Auto-reload: {'ENABLED' if enable_reload else 'DISABLED'}") print(f"Auto-reload: {'ENABLED' if enable_reload else 'DISABLED'}")
if verbose_mode: if verbose_mode:
print("Verbose logging: ENABLED") print("Verbose logging: ENABLED")
if args.podcast_only_demo:
print("Podcast-only demo mode: ENABLED")
print("=" * 40) print("=" * 40)
# Check if we're in the right directory # Check if we're in the right directory