|
import os |
|
import json |
|
import redis |
|
import requests |
|
import logging |
|
import datetime |
|
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') |
|
|
|
|
|
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") |
|
|
|
|
|
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 |
|
|
|
|
|
TOPIC_DISPLAY_MAP = { |
|
"india": {"name": "India", "emoji": "๐ฎ๐ณ"}, |
|
"world": {"name": "World", "emoji": "๐"}, |
|
"tech": {"name": "Technology", "emoji": "๐ง "}, |
|
"finance": {"name": "Business & Markets", "emoji": "๐ฐ"}, |
|
"sports": {"name": "Sports", "emoji": "๐"}, |
|
} |
|
|
|
|
|
|
|
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}" |
|
|
|
|
|
today = datetime.date.today() |
|
formatted_date = today.strftime("%B %d, %Y") |
|
|
|
message_parts = [] |
|
|
|
|
|
message_parts.append(f"Nuse Daily - {formatted_date}") |
|
message_parts.append("") |
|
|
|
|
|
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", "") |
|
|
|
|
|
|
|
message_parts.append(f"\u2007{ref_id}. \u2007{summary} - {description}") |
|
message_parts.append("") |
|
|
|
|
|
message_parts.append("") |
|
message_parts.append("Curated by Nuse.") |
|
|
|
return "\n".join(message_parts) |
|
|
|
|
|
def send_to_whatsapp(message_text: str, destination_number: str) -> dict: |
|
|
|
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} |