Recovered state: integrated TrendSurferAgent, restored frontend/backend files, and cleaned up recovery scripts

This commit is contained in:
ajaysi
2026-02-08 13:56:57 +05:30
parent 1db10ccd0f
commit e404a86502
333 changed files with 42223 additions and 10875 deletions

View File

@@ -19,35 +19,48 @@ from services.bing_analytics_storage_service import BingAnalyticsStorageService
import os
from services.database import get_user_db_path
class BingAnalyticsHandler(BaseAnalyticsHandler):
"""Handler for Bing Webmaster Tools analytics"""
def __init__(self):
super().__init__(PlatformType.BING)
self.bing_service = BingOAuthService()
# Initialize insights service
database_url = os.getenv('DATABASE_URL', 'sqlite:///./bing_analytics.db')
self.insights_service = BingInsightsService(database_url)
# Storage service used in onboarding step 5
self.storage_service = BingAnalyticsStorageService(os.getenv('DATABASE_URL', 'sqlite:///alwrity.db'))
def _get_storage_service(self, user_id: str) -> BingAnalyticsStorageService:
"""Get user-specific storage service."""
db_path = get_user_db_path(user_id)
db_url = f'sqlite:///{db_path}'
return BingAnalyticsStorageService(db_url)
def _get_insights_service(self, user_id: str) -> BingInsightsService:
"""Get user-specific insights service."""
# For now, insights might be in a separate DB or same.
# User requested isolation, so same user DB is best.
db_path = get_user_db_path(user_id)
db_url = f'sqlite:///{db_path}'
return BingInsightsService(db_url)
async def get_analytics(self, user_id: str) -> AnalyticsData:
"""
Get Bing Webmaster analytics data using Bing Webmaster API
Note: Bing Webmaster provides SEO insights and search performance data
"""
self.log_analytics_request(user_id, "get_analytics")
# Check cache first - this is an expensive operation
# Check cache first
cached_data = analytics_cache.get('bing_analytics', user_id)
if cached_data:
logger.info("Using cached Bing analytics for user {user_id}", user_id=user_id)
logger.info(f"Using cached Bing analytics for user {user_id}")
return AnalyticsData(**cached_data)
logger.info("Fetching fresh Bing analytics for user {user_id} (expensive operation)", user_id=user_id)
logger.info(f"Fetching fresh Bing analytics for user {user_id}")
try:
# Get user's Bing connection status with detailed token info
# Get services for this user
storage_service = self._get_storage_service(user_id)
insights_service = self._get_insights_service(user_id)
# Get user's Bing connection status
token_status = self.bing_service.get_user_token_status(user_id)
if not token_status.get('has_active_tokens'):
@@ -56,31 +69,24 @@ class BingAnalyticsHandler(BaseAnalyticsHandler):
else:
return self.create_error_response('Bing Webmaster not connected')
# Try once to fetch sites (may return empty if tokens are valid but no verified sites); do not block
sites = self.bing_service.get_user_sites(user_id)
# Get active tokens for access token
active_tokens = token_status.get('active_tokens', [])
if not active_tokens:
return self.create_error_response('No active Bing Webmaster tokens available')
# Get the first active token's access token
token_info = active_tokens[0]
access_token = token_info.get('access_token')
# Cache the sites for future use (even if empty)
analytics_cache.set('bing_sites', user_id, sites or [], ttl_override=2*60*60)
logger.info(f"Cached Bing sites for analytics for user {user_id} (TTL: 2 hours)")
if not access_token:
return self.create_error_response('Bing Webmaster access token not available')
# Do NOT call live Bing APIs here; use stored analytics like step 5
query_stats = {}
try:
# If sites available, use first; otherwise ask storage for any stored summary
site_url_for_storage = sites[0].get('Url', '') if (sites and isinstance(sites[0], dict)) else None
stored = self.storage_service.get_analytics_summary(user_id, site_url_for_storage, days=30)
stored = storage_service.get_analytics_summary(user_id, site_url_for_storage, days=30)
if stored and isinstance(stored, dict):
query_stats = {
'total_clicks': stored.get('summary', {}).get('total_clicks', 0),
@@ -92,10 +98,9 @@ class BingAnalyticsHandler(BaseAnalyticsHandler):
except Exception as e:
logger.warning(f"Bing analytics: Failed to read stored analytics summary: {e}")
# Get enhanced insights from database
insights = self._get_enhanced_insights(user_id, sites[0].get('Url', '') if sites else '')
# Get enhanced insights
insights = self._get_enhanced_insights_with_service(insights_service, user_id, sites[0].get('Url', '') if sites else '')
# Extract comprehensive site information with actual metrics
metrics = {
'connection_status': 'connected',
'connected_sites': len(sites),
@@ -111,25 +116,39 @@ class BingAnalyticsHandler(BaseAnalyticsHandler):
'note': 'Bing Webmaster API provides SEO insights, search performance, and index status data'
}
# If no stored data or no sites, return partial like step 5, else success
if (not sites) or (metrics.get('total_impressions', 0) == 0 and metrics.get('total_clicks', 0) == 0):
result = self.create_partial_response(metrics=metrics, error_message='Connected to Bing; waiting for stored analytics or site verification')
else:
result = self.create_success_response(metrics=metrics)
# Cache the result to avoid expensive API calls
analytics_cache.set('bing_analytics', user_id, result.__dict__)
logger.info("Cached Bing analytics data for user {user_id}", user_id=user_id)
return result
except Exception as e:
self.log_analytics_error(user_id, "get_analytics", e)
error_result = self.create_error_response(str(e))
# Cache error result for shorter time to retry sooner
analytics_cache.set('bing_analytics', user_id, error_result.__dict__, ttl_override=300) # 5 minutes
analytics_cache.set('bing_analytics', user_id, error_result.__dict__, ttl_override=300)
return error_result
def _get_enhanced_insights_with_service(self, insights_service: BingInsightsService, user_id: str, site_url: str) -> Dict[str, Any]:
"""Get enhanced insights using provided service."""
try:
if not site_url:
return {'status': 'no_site_url', 'message': 'No site URL available for insights'}
performance_insights = insights_service.get_performance_insights(user_id, site_url, days=30)
seo_insights = insights_service.get_seo_insights(user_id, site_url, days=30)
recommendations = insights_service.get_actionable_recommendations(user_id, site_url, days=30)
return {
'performance': performance_insights,
'seo': seo_insights,
'recommendations': recommendations,
'last_analyzed': datetime.now().isoformat()
}
except Exception as e:
logger.warning(f"Error getting enhanced insights: {e}")
return {'status': 'error', 'message': str(e)}
def get_connection_status(self, user_id: str) -> Dict[str, Any]:
"""Get Bing Webmaster connection status"""

View File

@@ -17,7 +17,7 @@ from ...analytics_cache_service import AnalyticsCacheService
class BingInsightsService:
"""Service for generating Bing Webmaster insights and recommendations"""
def __init__(self, database_url: str):
def __init__(self, database_url: Optional[str] = None):
self.storage_service = BingAnalyticsStorageService(database_url)
self.cache_service = AnalyticsCacheService()