Spaces:
Build error
Build error
File size: 4,177 Bytes
db6bff5 d5c46e9 9569b7d db6bff5 d5c46e9 db6bff5 d5c46e9 db6bff5 d5c46e9 db6bff5 e20916c db6bff5 e20916c db6bff5 e20916c db6bff5 e20916c db6bff5 e20916c db6bff5 9569b7d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
from fastapi import FastAPI, Request, status
from fastapi.responses import JSONResponse
from fastapi.responses import Response
from fastapi.exceptions import HTTPException
from typing import Dict
from app.services.message import generate_reply, send_reply, process_message_with_retry
import logging
from datetime import datetime
import time
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Initialize FastAPI app
app = FastAPI()
# In-memory cache with timestamp cleanup
class MessageCache:
def __init__(self, max_age_hours: int = 24):
self.messages: Dict[str, float] = {}
self.max_age_seconds = max_age_hours * 3600
def add(self, message_id: str) -> None:
self.cleanup()
self.messages[message_id] = time.time()
def exists(self, message_id: str) -> bool:
self.cleanup()
return message_id in self.messages
def cleanup(self) -> None:
current_time = time.time()
self.messages = {
msg_id: timestamp
for msg_id, timestamp in self.messages.items()
if current_time - timestamp < self.max_age_seconds
}
message_cache = MessageCache()
@app.post("/webhook")
async def webhook(request: Request):
request_id = f"req_{int(time.time()*1000)}"
logger.info(f"Processing webhook request {request_id}")
payload = await request.json()
processed_count = 0
error_count = 0
results = []
entries = payload.get("entry", [])
for entry in entries:
entry_id = entry.get("id")
logger.info(f"Processing entry_id: {entry_id}")
changes = entry.get("changes", [])
for change in changes:
messages = change.get("value", {}).get("messages", [])
for message in messages:
message_id = message.get("id")
timestamp = message.get("timestamp")
content = message.get("text", {}).get("body")
sender_id = message.get("from")
# Deduplicate messages based on message_id
if message_cache.exists(message_id):
logger.info(f"Duplicate message detected and skipped: {message_id}")
continue
try:
# Process message with retry logic
result = await process_message_with_retry(
sender_id,
content,
timestamp
)
# Add the message ID to the cache
message_cache.add(message_id)
processed_count += 1
results.append(result)
except Exception as e:
error_count += 1
logger.error(
f"Failed to process message {message_id}: {str(e)}",
exc_info=True
)
results.append({
"status": "error",
"message_id": message_id,
"error": str(e)
})
response_data = {
"request_id": request_id,
"processed": processed_count,
"errors": error_count,
"results": results
}
logger.info(
f"Webhook processing completed - "
f"Processed: {processed_count}, Errors: {error_count}"
)
return JSONResponse(
content=response_data,
status_code=status.HTTP_200_OK
)
@app.get("/webhook")
async def verify_webhook(request: Request):
mode = request.query_params.get('hub.mode')
token = request.query_params.get('hub.verify_token')
challenge = request.query_params.get('hub.challenge')
# Replace 'your_verification_token' with the token you set in Facebook Business Manager
if mode == 'subscribe' and token == 'test':
# Return the challenge as plain text
return Response(content=challenge, media_type="text/plain")
else:
raise HTTPException(status_code=403, detail="Verification failed") |