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)}")
|