Onboarding Manager and Router Manager refactored, analytics and background jobs added, database setup updated, environment setup updated, frontend updated, backend updated. Critical onboarding database migration implemented.
167 lines
6.3 KiB
Python
167 lines
6.3 KiB
Python
"""
|
|
Bing Webmaster Analytics API Routes
|
|
Provides endpoints for accessing Bing Webmaster Tools analytics data.
|
|
"""
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from typing import Optional, Dict, Any
|
|
from datetime import datetime, timedelta
|
|
from loguru import logger
|
|
|
|
from services.integrations.bing_oauth import BingOAuthService
|
|
from middleware.auth_middleware import get_current_user
|
|
|
|
router = APIRouter(prefix="/bing", tags=["Bing Analytics"])
|
|
|
|
# Initialize Bing OAuth service
|
|
bing_service = BingOAuthService()
|
|
|
|
@router.get("/query-stats")
|
|
async def get_query_stats(
|
|
site_url: str = Query(..., description="The site URL to get query stats for"),
|
|
start_date: Optional[str] = Query(None, description="Start date in YYYY-MM-DD format"),
|
|
end_date: Optional[str] = Query(None, description="End date in YYYY-MM-DD format"),
|
|
page: int = Query(0, description="Page number for pagination"),
|
|
current_user: Dict[str, Any] = Depends(get_current_user)
|
|
):
|
|
"""Get search query statistics for a Bing Webmaster site."""
|
|
try:
|
|
user_id = current_user.get("user_id")
|
|
if not user_id:
|
|
raise HTTPException(status_code=401, detail="User not authenticated")
|
|
|
|
logger.info(f"Getting Bing query stats for user {user_id}, site: {site_url}")
|
|
|
|
# Get query stats from Bing service
|
|
result = bing_service.get_query_stats(
|
|
user_id=user_id,
|
|
site_url=site_url,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
page=page
|
|
)
|
|
|
|
if "error" in result:
|
|
logger.error(f"Bing query stats error: {result['error']}")
|
|
raise HTTPException(status_code=400, detail=result["error"])
|
|
|
|
logger.info(f"Successfully retrieved Bing query stats for {site_url}")
|
|
return {
|
|
"success": True,
|
|
"data": result,
|
|
"site_url": site_url,
|
|
"start_date": start_date,
|
|
"end_date": end_date,
|
|
"page": page
|
|
}
|
|
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting Bing query stats: {e}")
|
|
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|
|
|
|
@router.get("/user-sites")
|
|
async def get_user_sites(
|
|
current_user: Dict[str, Any] = Depends(get_current_user)
|
|
):
|
|
"""Get list of user's verified sites from Bing Webmaster."""
|
|
try:
|
|
user_id = current_user.get("user_id")
|
|
if not user_id:
|
|
raise HTTPException(status_code=401, detail="User not authenticated")
|
|
|
|
logger.info(f"Getting Bing user sites for user {user_id}")
|
|
|
|
# Get user sites from Bing service
|
|
sites = bing_service.get_user_sites(user_id)
|
|
|
|
logger.info(f"Successfully retrieved {len(sites)} Bing sites for user {user_id}")
|
|
return {
|
|
"success": True,
|
|
"sites": sites,
|
|
"total_sites": len(sites)
|
|
}
|
|
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting Bing user sites: {e}")
|
|
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|
|
|
|
@router.get("/query-stats/summary")
|
|
async def get_query_stats_summary(
|
|
site_url: str = Query(..., description="The site URL to get query stats summary for"),
|
|
start_date: Optional[str] = Query(None, description="Start date in YYYY-MM-DD format"),
|
|
end_date: Optional[str] = Query(None, description="End date in YYYY-MM-DD format"),
|
|
current_user: Dict[str, Any] = Depends(get_current_user)
|
|
):
|
|
"""Get summarized query statistics for a Bing Webmaster site."""
|
|
try:
|
|
user_id = current_user.get("user_id")
|
|
if not user_id:
|
|
raise HTTPException(status_code=401, detail="User not authenticated")
|
|
|
|
logger.info(f"Getting Bing query stats summary for user {user_id}, site: {site_url}")
|
|
|
|
# Get query stats from Bing service
|
|
result = bing_service.get_query_stats(
|
|
user_id=user_id,
|
|
site_url=site_url,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
page=0 # Just get first page for summary
|
|
)
|
|
|
|
if "error" in result:
|
|
logger.error(f"Bing query stats error: {result['error']}")
|
|
raise HTTPException(status_code=400, detail=result["error"])
|
|
|
|
# Extract summary data
|
|
query_data = result.get('d', {})
|
|
queries = query_data.get('results', [])
|
|
|
|
# Calculate summary statistics
|
|
total_clicks = sum(query.get('Clicks', 0) for query in queries)
|
|
total_impressions = sum(query.get('Impressions', 0) for query in queries)
|
|
total_queries = len(queries)
|
|
avg_ctr = (total_clicks / total_impressions * 100) if total_impressions > 0 else 0
|
|
avg_position = sum(query.get('AvgClickPosition', 0) for query in queries) / total_queries if total_queries > 0 else 0
|
|
|
|
# Get top queries
|
|
top_queries = sorted(queries, key=lambda x: x.get('Clicks', 0), reverse=True)[:5]
|
|
|
|
summary = {
|
|
"total_queries": total_queries,
|
|
"total_clicks": total_clicks,
|
|
"total_impressions": total_impressions,
|
|
"average_ctr": round(avg_ctr, 2),
|
|
"average_position": round(avg_position, 2),
|
|
"top_queries": [
|
|
{
|
|
"query": q.get('Query', ''),
|
|
"clicks": q.get('Clicks', 0),
|
|
"impressions": q.get('Impressions', 0),
|
|
"ctr": round(q.get('Clicks', 0) / q.get('Impressions', 1) * 100, 2),
|
|
"position": q.get('AvgClickPosition', 0)
|
|
}
|
|
for q in top_queries
|
|
]
|
|
}
|
|
|
|
logger.info(f"Successfully created Bing query stats summary for {site_url}")
|
|
return {
|
|
"success": True,
|
|
"summary": summary,
|
|
"site_url": site_url,
|
|
"start_date": start_date,
|
|
"end_date": end_date,
|
|
"raw_data": result
|
|
}
|
|
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting Bing query stats summary: {e}")
|
|
raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
|