BraveShopper / demo.py
rairo's picture
Create demo.py
1f42647 verified
raw
history blame
7.31 kB
import os
import logging
import socket
import requests
import dns.resolver
from heyoo import WhatsApp
from dotenv import load_dotenv
from flask import Flask, request, make_response
# Initialize Flask App
app = Flask(__name__)
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
# Load .env file
load_dotenv()
# Configure DNS resolver with environment variables from Spaces
nameserver1 = os.getenv('nameserver1', '8.8.8.8')
nameserver2 = os.getenv('nameserver2', '8.8.4.4')
# Configure global DNS resolution
def setup_dns():
"""Configure DNS resolution globally"""
resolver = dns.resolver.Resolver()
resolver.nameservers = [nameserver1, nameserver2]
# Create a custom getaddrinfo function
_orig_getaddrinfo = socket.getaddrinfo
def new_getaddrinfo(*args, **kwargs):
try:
# If the host is graph.facebook.com, use our custom resolver
if args and args[0] == 'graph.facebook.com':
answers = resolver.resolve('graph.facebook.com', 'A')
ip = str(answers[0])
return _orig_getaddrinfo(ip, *args[1:], **kwargs)
except Exception as e:
logger.error(f"DNS resolution failed: {e}")
return _orig_getaddrinfo(*args, **kwargs)
# Replace the global getaddrinfo function
socket.getaddrinfo = new_getaddrinfo
# Setup DNS resolution
setup_dns()
# Initialize WhatsApp
try:
messenger = WhatsApp(
os.getenv("whatsapp_token"),
phone_number_id=os.getenv("phone_number_id")
)
if not os.getenv("whatsapp_token") or not os.getenv("phone_number_id"):
raise ValueError("Missing required environment variables")
except Exception as e:
logger.error(f"Failed to initialize WhatsApp messenger: {str(e)}")
raise
VERIFY_TOKEN = "30cca545-3838-48b2-80a7-9e43b1ae8ce4"
@app.get("/health")
def health_check():
"""Health check endpoint to verify DNS resolution"""
try:
resolver = dns.resolver.Resolver()
resolver.nameservers = [nameserver1, nameserver2]
ip = resolver.resolve('graph.facebook.com', 'A')[0]
return {
"status": "healthy",
"dns_resolution": str(ip),
"nameserver1": nameserver1,
"nameserver2": nameserver2
}
except Exception as e:
return {
"status": "unhealthy",
"error": str(e)
}
@app.get("/")
def verify_token():
"""Webhook verification endpoint"""
try:
if request.args.get("hub.verify_token") == VERIFY_TOKEN:
logger.info("Verified webhook")
response = make_response(request.args.get("hub.challenge"), 200)
response.mimetype = "text/plain"
return response
logger.error("Webhook Verification failed")
return "Invalid verification token"
except Exception as e:
logger.error(f"Error in verify_token: {str(e)}")
return "Internal server error", 500
@app.post("/")
def hook():
"""Main webhook handler"""
try:
data = request.get_json()
logger.info("Received webhook data: %s", data)
changed_field = messenger.changed_field(data)
if changed_field != "messages":
return "OK", 200
if not messenger.is_message(data):
delivery = messenger.get_delivery(data)
if delivery:
logger.info(f"Message delivery status: {delivery}")
return "OK", 200
# Extract message details
mobile = messenger.get_mobile(data)
name = messenger.get_name(data)
message_type = messenger.get_message_type(data)
logger.info(f"New Message; sender:{mobile} name:{name} type:{message_type}")
# Handle different message types
try:
if message_type == "text":
message = messenger.get_message(data)
logger.info("Message: %s", message)
messenger.send_message(f"Hi {name}, nice to connect with you", mobile)
elif message_type == "interactive":
message_response = messenger.get_interactive_response(data)
interactive_type = message_response.get("type")
message_id = message_response[interactive_type]["id"]
message_text = message_response[interactive_type]["title"]
logger.info(f"Interactive Message; {message_id}: {message_text}")
elif message_type == "location":
message_location = messenger.get_location(data)
message_latitude = message_location["latitude"]
message_longitude = message_location["longitude"]
logger.info("Location: %s, %s", message_latitude, message_longitude)
elif message_type in ["image", "video", "audio", "document"]:
handle_media_message(messenger, data, message_type, mobile)
else:
logger.info(f"{mobile} sent unsupported message type: {message_type}")
logger.debug(f"Full message data: {data}")
except Exception as e:
logger.error(f"Error processing message type {message_type}: {str(e)}")
return "Internal server error", 500
return "OK", 200
except Exception as e:
logger.error(f"Error in webhook handler: {str(e)}")
return "Internal server error", 500
def handle_media_message(messenger, data, message_type, mobile):
"""Handle different types of media messages"""
try:
media_methods = {
"image": messenger.get_image,
"video": messenger.get_video,
"audio": messenger.get_audio,
"document": messenger.get_document
}
media = media_methods[message_type](data)
media_id, mime_type = media["id"], media["mime_type"]
try:
media_url = messenger.query_media_url(media_id)
media_filename = messenger.download_media(media_url, mime_type)
logger.info(f"{mobile} sent {message_type} {media_filename}")
except requests.exceptions.ConnectionError as ce:
logger.error(f"Connection error while downloading {message_type}: {str(ce)}")
except Exception as e:
logger.error(f"Error downloading {message_type}: {str(e)}")
except Exception as e:
logger.error(f"Error processing {message_type} message: {str(e)}")
raise
def test_connection():
"""Test DNS resolution and connection to Graph API"""
try:
resolver = dns.resolver.Resolver()
resolver.nameservers = [nameserver1, nameserver2]
ip = resolver.resolve('graph.facebook.com', 'A')[0]
logger.info(f"DNS Resolution successful: {ip}")
response = requests.get('https://graph.facebook.com')
logger.info(f"HTTPS Connection successful: {response.status_code}")
except Exception as e:
logger.error(f"Connection test failed: {e}")
if __name__ == "__main__":
# Test connection before starting
test_connection()
# Start Flask app
app.run(debug=True, host="0.0.0.0", port=7860)