fastAPIv2 / components /gateways /headlines_to_wa.py
ragV98's picture
god knows
f5b0713
import os
import json
import redis
import requests
import logging
import datetime # Import datetime for dynamic date
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# ๐ŸŒ Configuration from Environment Variables
REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
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")
GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER")
GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME")
# โœ… Redis connection
try:
redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
redis_client.ping()
logging.info("Redis client connected successfully.")
except Exception as e:
logging.error(f"โŒ Failed to connect to Redis: {e}")
raise
# --- New: Topic mapping for display names and emojis ---
TOPIC_DISPLAY_MAP = {
"india": {"name": "India", "emoji": "๐Ÿ‡ฎ๐Ÿ‡ณ"},
"world": {"name": "World", "emoji": "๐ŸŒ"},
"tech": {"name": "Technology", "emoji": "๐Ÿง "},
"finance": {"name": "Business & Markets", "emoji": "๐Ÿ’ฐ"},
"sports": {"name": "Sports", "emoji": "๐Ÿ†"},
}
# ๐Ÿงพ Fetch and format headlines
# UPDATED: To match the exact "NUSE DAILY" format and new item format
def fetch_cached_headlines() -> str:
try:
raw = redis_client.get("daily_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}"
# Get current date for the header
today = datetime.date.today()
formatted_date = today.strftime("%B %d, %Y")
message_parts = []
# Header section
message_parts.append(f"Nuse Daily - {formatted_date}")
message_parts.append("")
# Iterate through topics in a defined order for consistent output
for topic_key, display_info in TOPIC_DISPLAY_MAP.items():
stories_for_topic = data.get(topic_key)
if stories_for_topic:
message_parts.append(f"{display_info['emoji']} *{display_info['name']}*")
sorted_story_ids = sorted(stories_for_topic.keys(), key=int)
for ref_id in sorted_story_ids:
item = stories_for_topic[ref_id]
summary = item.get("summary", "")
description = item.get("explanation", "")
# <<< UPDATED: Item format to "1. <summary> - <explanation>" >>>
# Using U+2007 (Figure Space) for alignment
message_parts.append(f"\u2007{ref_id}. \u2007{summary} - {description}")
message_parts.append("")
# Footer section
message_parts.append("")
message_parts.append("Curated by Nuse.")
return "\n".join(message_parts)
# ๐Ÿ“ค Send via Gupshup WhatsApp API
def send_to_whatsapp(message_text: str, destination_number: str) -> dict:
# Validate critical environment variables
if not WHATSAPP_TOKEN or \
not GUPSHUP_SOURCE_NUMBER or \
not GUPSHUP_APP_NAME:
error_msg = "โŒ Missing one or more critical WhatsApp API environment variables (WHATSAPP_TOKEN, GUPSHUP_SOURCE_NUMBER, GUPSHUP_APP_NAME)."
logging.error(error_msg)
return {"status": "failed", "error": error_msg, "code": 500}
if not destination_number:
error_msg = "โŒ Destination number cannot be empty."
logging.error(error_msg)
return {"status": "failed", "error": error_msg, "code": 400}
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"apikey": WHATSAPP_TOKEN,
"Cache-Control": "no-cache",
"accept": "application/json"
}
whatsapp_message_content = {
"type": "text",
"text": message_text
}
payload = {
"channel": "whatsapp",
"source": GUPSHUP_SOURCE_NUMBER,
"destination": destination_number,
"src.name": GUPSHUP_APP_NAME,
"message": message_text,
"disablePreview": False,
"encode": False
}
try:
logging.info(f"Attempting to send standard text WhatsApp message to {destination_number}, {GUPSHUP_SOURCE_NUMBER}, {GUPSHUP_APP_NAME}, {WHATSAPP_TOKEN} via Gupshup. API URL: {WHATSAPP_API_URL} and message text is {message_text}")
response = requests.post(
WHATSAPP_API_URL,
headers=headers,
data=payload,
)
response.raise_for_status()
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}