fastAPIv2 / components /gateways /headlines_to_wa.py
ragV98's picture
ffs
a330e1e
raw
history blame
7.93 kB
import os
import json
import redis
import requests
from fastapi import FastAPI
from fastapi.responses import JSONResponse
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 🌐 Configuration from Environment Variables
# These variables MUST be set in your environment (e.g., .env file, shell exports, deployment configs)
REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
# Reverting API URL to generic WhatsApp message endpoint
WHATSAPP_API_URL = os.environ.get("WHATSAPP_API_URL", "https://api.gupshup.io/wa/api/v1/msg")
WHATSAPP_TOKEN = os.environ.get("WHATSAPP_TOKEN")
WHATSAPP_TO_NUMBER = os.environ.get("WHATSAPP_TO_NUMBER", "353899495777") # e.g., "91xxxxxxxxxx"
GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER") # e.g., your WABA number
GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME") # e.g., your Gupshup app name
# Removed: WHATSAPP_CATALOG_ID, WHATSAPP_PRODUCT_RETAILER_ID, WHATSAPP_FOOTER_TEXT, WHATSAPP_TEMPLATE_ID
# βœ… Redis connection
try:
redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
redis_client.ping() # Test connection
logging.info("Redis client connected successfully.")
except Exception as e:
logging.error(f"❌ Failed to connect to Redis: {e}")
raise
# 🧾 Fetch and format headlines
# Reverting this function to generate the full text message content
def fetch_cached_headlines() -> str:
try:
raw = redis_client.get("detailed_news_feed_cache")
if not raw:
logging.warning("⚠️ No detailed news headlines found in cache.")
return "⚠️ No daily headlines found in cache."
data = json.loads(raw)
except Exception as e:
logging.error(f"❌ Error reading from Redis: {e}")
return f"❌ Error reading from Redis: {e}"
message_parts = ["πŸ—žοΈ *Your Daily Digest* 🟑\n"]
sorted_topics = sorted(data.keys())
for topic_key in sorted_topics:
stories = data[topic_key]
title = topic_key.replace("_", " ").title()
message_parts.append(f"\n🏷️ *{title}*") # Added newline before topic title
sorted_story_ids = sorted(stories.keys(), key=int)
for ref_id in sorted_story_ids:
item = stories[ref_id]
summary = item.get("title", "")
description = item.get("description", "")
message_parts.append(f"{ref_id}. {summary}\n_Why this matters_: {description}")
# No extra empty line needed here if we add newline to topic title
return "\n".join(message_parts)
# πŸ“€ Send via Gupshup WhatsApp API
# Reverting to send a standard text message
def send_to_whatsapp(message_text: str) -> dict: # Function expects the full message text
# Validate critical environment variables for sending a message
if not WHATSAPP_TOKEN or \
not WHATSAPP_TO_NUMBER or \
not GUPSHUP_SOURCE_NUMBER or \
not GUPSHUP_APP_NAME:
error_msg = "❌ Missing one or more critical WhatsApp API environment variables (WHATSAPP_TOKEN, WHATSAPP_TO_NUMBER, GUPSHUP_SOURCE_NUMBER, GUPSHUP_APP_NAME)."
logging.error(error_msg)
return {"status": "failed", "error": error_msg, "code": 500}
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"apikey": WHATSAPP_TOKEN, # API key in 'apikey' header
"Cache-Control": "no-cache" # Add Cache-Control header
}
# <<< REVERTED MESSAGE PAYLOAD FOR STANDARD TEXT MESSAGE >>>
whatsapp_message_content = {
"type": "text",
"text": message_text # This is the full formatted text
}
payload = {
"channel": "whatsapp",
"source": GUPSHUP_SOURCE_NUMBER,
"destination": WHATSAPP_TO_NUMBER,
"src.name": GUPSHUP_APP_NAME,
"message": json.dumps(whatsapp_message_content) # 'message' parameter with JSON string for text type
}
try:
logging.info(f"Attempting to send standard text WhatsApp message to {WHATSAPP_TO_NUMBER} via Gupshup. API URL: {WHATSAPP_API_URL}")
response = requests.post(
WHATSAPP_API_URL,
headers=headers,
data=payload,
)
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
return {"status": "success", "details": response.json()}
except requests.exceptions.RequestException as e:
logging.error(f"❌ Failed to send WhatsApp message: {e}")
return {"status": "failed", "error": str(e), "code": e.response.status_code if e.response else 500}
except Exception as e:
logging.error(f"❌ An unexpected error occurred during WhatsApp send: {e}")
return {"status": "failed", "error": str(e), "code": 500}
# πŸš€ FastAPI App
app = FastAPI()
@app.get("/send-daily-whatsapp")
def send_daily_whatsapp_digest():
logging.info("API Call: /send-daily-whatsapp initiated.")
# fetch_cached_headlines now returns the full message text
full_message_text = fetch_cached_headlines()
if full_message_text.startswith("❌") or full_message_text.startswith("⚠️"):
logging.warning(f"Returning error due to issue fetching headlines: {full_message_text}")
return JSONResponse(status_code=404, content={"error": full_message_text})
# Call send_to_whatsapp with the full formatted text
result = send_to_whatsapp(full_message_text)
if result.get("status") == "success":
logging.info("βœ… WhatsApp message sent successfully.")
return JSONResponse(status_code=200, content=result)
else:
logging.error(f"❌ Failed to send WhatsApp message: {result.get('error')}")
return JSONResponse(status_code=result.get("code", 500), content=result)
# πŸ§ͺ For local testing
if __name__ == "__main__":
# For local testing, ensure these environment variables are set in your shell or .env file.
# Example .env content:
# UPSTASH_REDIS_URL="redis://your_redis_url"
# WHATSAPP_API_URL="https://api.gupshup.io/wa/api/v1/msg"
# WHATSAPP_TOKEN="YOUR_GUPSHUP_API_KEY"
# WHATSAPP_TO_NUMBER="919999999999"
# GUPSHUP_SOURCE_NUMBER="15557926439"
# GUPSHUP_APP_NAME="NuseAI"
# Simulate a cached detailed feed for testing
dummy_cached_detailed_feed = {
"india": {
"1": {"title": "India's Economy Surges", "description": "Rapid growth in manufacturing and services sectors signals a strong economic recovery, boosting investor confidence and job creation.", "sources": ["Times of India"]},
"2": {"title": "New Tech Policy Unveiled", "description": "Government introduces new regulations to foster innovation while addressing data privacy concerns, aiming to balance growth with user protection.", "sources": ["Indian Express"]}
},
"world": {
"3": {"title": "Global Climate Talks Advance", "description": "Nations agree on ambitious new targets for emissions reduction, marking a significant step towards combating climate change despite earlier disagreements.", "sources": ["BBC News"]},
"4": {"title": "Space Mission Explores Mars", "description": "A new rover successfully lands on Mars, sending back groundbreaking data that could revolutionize our understanding of planetary geology and potential for life.", "sources": ["CNN World"]}
}
}
# Store dummy data in Redis for testing fetch_cached_headlines
redis_client.set("detailed_news_feed_cache", json.dumps(dummy_cached_detailed_feed))
logging.info("\n--- WhatsApp Message Preview ---\n")
msg_preview = fetch_cached_headlines()
print(msg_preview)
logging.info("\n--- Sending WhatsApp Message (Test) ---\n")
# This will attempt to send a real message if your env vars are valid
test_result = send_to_whatsapp(msg_preview)
print(test_result)