let's see
Browse files
components/gateways/headlines_to_wa.py
CHANGED
@@ -4,18 +4,22 @@ import redis
|
|
4 |
import requests
|
5 |
from fastapi import FastAPI
|
6 |
from fastapi.responses import JSONResponse
|
7 |
-
import logging
|
8 |
|
9 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
10 |
|
11 |
-
# π
|
|
|
12 |
REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
|
|
|
13 |
WHATSAPP_API_URL = os.environ.get("WHATSAPP_API_URL", "https://api.gupshup.io/wa/api/v1/msg")
|
14 |
WHATSAPP_TOKEN = os.environ.get("WHATSAPP_TOKEN")
|
15 |
-
WHATSAPP_TO_NUMBER = os.environ.get("WHATSAPP_TO_NUMBER"
|
16 |
GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER") # e.g., your WABA number
|
17 |
GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME") # e.g., your Gupshup app name
|
18 |
|
|
|
|
|
19 |
# β
Redis connection
|
20 |
try:
|
21 |
redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
|
@@ -26,10 +30,9 @@ except Exception as e:
|
|
26 |
raise
|
27 |
|
28 |
# π§Ύ Fetch and format headlines
|
|
|
29 |
def fetch_cached_headlines() -> str:
|
30 |
try:
|
31 |
-
# Assuming 'detailed_news_feed_cache' is the key for the final detailed headlines
|
32 |
-
# This key should match what's used in components/generators/detailed_explainer.py
|
33 |
raw = redis_client.get("detailed_news_feed_cache")
|
34 |
if not raw:
|
35 |
logging.warning("β οΈ No detailed news headlines found in cache.")
|
@@ -46,9 +49,9 @@ def fetch_cached_headlines() -> str:
|
|
46 |
for topic_key in sorted_topics:
|
47 |
stories = data[topic_key]
|
48 |
title = topic_key.replace("_", " ").title()
|
49 |
-
message_parts.append(f"π·οΈ *{title}*")
|
50 |
|
51 |
-
sorted_story_ids = sorted(stories.keys(), key=int)
|
52 |
|
53 |
for ref_id in sorted_story_ids:
|
54 |
item = stories[ref_id]
|
@@ -56,42 +59,48 @@ def fetch_cached_headlines() -> str:
|
|
56 |
description = item.get("description", "")
|
57 |
|
58 |
message_parts.append(f"{ref_id}. {summary}\n_Why this matters_: {description}")
|
59 |
-
|
60 |
|
61 |
return "\n".join(message_parts)
|
62 |
|
63 |
# π€ Send via Gupshup WhatsApp API
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
|
|
|
|
|
|
|
|
68 |
logging.error(error_msg)
|
69 |
return {"status": "failed", "error": error_msg, "code": 500}
|
70 |
|
71 |
-
# Gupshup requires the API key in the 'apikey' header
|
72 |
headers = {
|
73 |
"Content-Type": "application/x-www-form-urlencoded",
|
74 |
"apikey": WHATSAPP_TOKEN, # API key in 'apikey' header
|
75 |
"Cache-Control": "no-cache" # Add Cache-Control header
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
payload = {
|
79 |
"channel": "whatsapp",
|
80 |
"source": GUPSHUP_SOURCE_NUMBER,
|
81 |
-
"destination": WHATSAPP_TO_NUMBER,
|
82 |
-
"message": json.dumps({
|
83 |
-
"type": "text",
|
84 |
-
"text": message_text
|
85 |
-
}),
|
86 |
"src.name": GUPSHUP_APP_NAME,
|
|
|
87 |
}
|
88 |
|
89 |
try:
|
90 |
-
logging.info(f"Attempting to send WhatsApp message to {WHATSAPP_TO_NUMBER} via Gupshup. API URL: {WHATSAPP_API_URL}")
|
91 |
response = requests.post(
|
92 |
WHATSAPP_API_URL,
|
93 |
headers=headers,
|
94 |
-
data=payload,
|
95 |
)
|
96 |
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
|
97 |
|
@@ -109,13 +118,16 @@ app = FastAPI()
|
|
109 |
@app.get("/send-daily-whatsapp")
|
110 |
def send_daily_whatsapp_digest():
|
111 |
logging.info("API Call: /send-daily-whatsapp initiated.")
|
112 |
-
|
|
|
|
|
113 |
|
114 |
-
if
|
115 |
-
logging.warning(f"Returning error due to issue fetching headlines: {
|
116 |
-
return JSONResponse(status_code=404, content={"error":
|
117 |
|
118 |
-
|
|
|
119 |
|
120 |
if result.get("status") == "success":
|
121 |
logging.info("β
WhatsApp message sent successfully.")
|
@@ -126,15 +138,14 @@ def send_daily_whatsapp_digest():
|
|
126 |
|
127 |
# π§ͺ For local testing
|
128 |
if __name__ == "__main__":
|
129 |
-
#
|
130 |
-
#
|
131 |
-
#
|
132 |
-
#
|
133 |
-
#
|
134 |
-
#
|
135 |
-
#
|
136 |
-
#
|
137 |
-
# -----------------------------------------------------------------------------
|
138 |
|
139 |
# Simulate a cached detailed feed for testing
|
140 |
dummy_cached_detailed_feed = {
|
|
|
4 |
import requests
|
5 |
from fastapi import FastAPI
|
6 |
from fastapi.responses import JSONResponse
|
7 |
+
import logging
|
8 |
|
9 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
10 |
|
11 |
+
# π Configuration from Environment Variables
|
12 |
+
# These variables MUST be set in your environment (e.g., .env file, shell exports, deployment configs)
|
13 |
REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
|
14 |
+
# Reverting API URL to generic WhatsApp message endpoint
|
15 |
WHATSAPP_API_URL = os.environ.get("WHATSAPP_API_URL", "https://api.gupshup.io/wa/api/v1/msg")
|
16 |
WHATSAPP_TOKEN = os.environ.get("WHATSAPP_TOKEN")
|
17 |
+
WHATSAPP_TO_NUMBER = os.environ.get("WHATSAPP_TO_NUMBER") # e.g., "91xxxxxxxxxx"
|
18 |
GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER") # e.g., your WABA number
|
19 |
GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME") # e.g., your Gupshup app name
|
20 |
|
21 |
+
# Removed: WHATSAPP_CATALOG_ID, WHATSAPP_PRODUCT_RETAILER_ID, WHATSAPP_FOOTER_TEXT, WHATSAPP_TEMPLATE_ID
|
22 |
+
|
23 |
# β
Redis connection
|
24 |
try:
|
25 |
redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
|
|
|
30 |
raise
|
31 |
|
32 |
# π§Ύ Fetch and format headlines
|
33 |
+
# Reverting this function to generate the full text message content
|
34 |
def fetch_cached_headlines() -> str:
|
35 |
try:
|
|
|
|
|
36 |
raw = redis_client.get("detailed_news_feed_cache")
|
37 |
if not raw:
|
38 |
logging.warning("β οΈ No detailed news headlines found in cache.")
|
|
|
49 |
for topic_key in sorted_topics:
|
50 |
stories = data[topic_key]
|
51 |
title = topic_key.replace("_", " ").title()
|
52 |
+
message_parts.append(f"\nπ·οΈ *{title}*") # Added newline before topic title
|
53 |
|
54 |
+
sorted_story_ids = sorted(stories.keys(), key=int)
|
55 |
|
56 |
for ref_id in sorted_story_ids:
|
57 |
item = stories[ref_id]
|
|
|
59 |
description = item.get("description", "")
|
60 |
|
61 |
message_parts.append(f"{ref_id}. {summary}\n_Why this matters_: {description}")
|
62 |
+
# No extra empty line needed here if we add newline to topic title
|
63 |
|
64 |
return "\n".join(message_parts)
|
65 |
|
66 |
# π€ Send via Gupshup WhatsApp API
|
67 |
+
# Reverting to send a standard text message
|
68 |
+
def send_to_whatsapp(message_text: str) -> dict: # Function expects the full message text
|
69 |
+
# Validate critical environment variables for sending a message
|
70 |
+
if not WHATSAPP_TOKEN or \
|
71 |
+
not WHATSAPP_TO_NUMBER or \
|
72 |
+
not GUPSHUP_SOURCE_NUMBER or \
|
73 |
+
not GUPSHUP_APP_NAME:
|
74 |
+
error_msg = "β Missing one or more critical WhatsApp API environment variables (WHATSAPP_TOKEN, WHATSAPP_TO_NUMBER, GUPSHUP_SOURCE_NUMBER, GUPSHUP_APP_NAME)."
|
75 |
logging.error(error_msg)
|
76 |
return {"status": "failed", "error": error_msg, "code": 500}
|
77 |
|
|
|
78 |
headers = {
|
79 |
"Content-Type": "application/x-www-form-urlencoded",
|
80 |
"apikey": WHATSAPP_TOKEN, # API key in 'apikey' header
|
81 |
"Cache-Control": "no-cache" # Add Cache-Control header
|
82 |
}
|
83 |
|
84 |
+
# <<< REVERTED MESSAGE PAYLOAD FOR STANDARD TEXT MESSAGE >>>
|
85 |
+
whatsapp_message_content = {
|
86 |
+
"type": "text",
|
87 |
+
"text": message_text # This is the full formatted text
|
88 |
+
}
|
89 |
+
|
90 |
payload = {
|
91 |
"channel": "whatsapp",
|
92 |
"source": GUPSHUP_SOURCE_NUMBER,
|
93 |
+
"destination": WHATSAPP_TO_NUMBER,
|
|
|
|
|
|
|
|
|
94 |
"src.name": GUPSHUP_APP_NAME,
|
95 |
+
"message": json.dumps(whatsapp_message_content) # 'message' parameter with JSON string for text type
|
96 |
}
|
97 |
|
98 |
try:
|
99 |
+
logging.info(f"Attempting to send standard text WhatsApp message to {WHATSAPP_TO_NUMBER} via Gupshup. API URL: {WHATSAPP_API_URL}")
|
100 |
response = requests.post(
|
101 |
WHATSAPP_API_URL,
|
102 |
headers=headers,
|
103 |
+
data=payload,
|
104 |
)
|
105 |
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
|
106 |
|
|
|
118 |
@app.get("/send-daily-whatsapp")
|
119 |
def send_daily_whatsapp_digest():
|
120 |
logging.info("API Call: /send-daily-whatsapp initiated.")
|
121 |
+
|
122 |
+
# fetch_cached_headlines now returns the full message text
|
123 |
+
full_message_text = fetch_cached_headlines()
|
124 |
|
125 |
+
if full_message_text.startswith("β") or full_message_text.startswith("β οΈ"):
|
126 |
+
logging.warning(f"Returning error due to issue fetching headlines: {full_message_text}")
|
127 |
+
return JSONResponse(status_code=404, content={"error": full_message_text})
|
128 |
|
129 |
+
# Call send_to_whatsapp with the full formatted text
|
130 |
+
result = send_to_whatsapp(full_message_text)
|
131 |
|
132 |
if result.get("status") == "success":
|
133 |
logging.info("β
WhatsApp message sent successfully.")
|
|
|
138 |
|
139 |
# π§ͺ For local testing
|
140 |
if __name__ == "__main__":
|
141 |
+
# For local testing, ensure these environment variables are set in your shell or .env file.
|
142 |
+
# Example .env content:
|
143 |
+
# UPSTASH_REDIS_URL="redis://your_redis_url"
|
144 |
+
# WHATSAPP_API_URL="https://api.gupshup.io/wa/api/v1/msg"
|
145 |
+
# WHATSAPP_TOKEN="YOUR_GUPSHUP_API_KEY"
|
146 |
+
# WHATSAPP_TO_NUMBER="919999999999"
|
147 |
+
# GUPSHUP_SOURCE_NUMBER="15557926439"
|
148 |
+
# GUPSHUP_APP_NAME="NuseAI"
|
|
|
149 |
|
150 |
# Simulate a cached detailed feed for testing
|
151 |
dummy_cached_detailed_feed = {
|