fix 110
Browse files
components/gateways/headlines_to_wa.py
CHANGED
@@ -4,17 +4,18 @@ 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 |
# π Redis config
|
12 |
REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
|
|
18 |
|
19 |
# β
Redis connection
|
20 |
try:
|
@@ -23,14 +24,11 @@ try:
|
|
23 |
logging.info("Redis client connected successfully.")
|
24 |
except Exception as e:
|
25 |
logging.error(f"β Failed to connect to Redis: {e}")
|
26 |
-
# Depending on your application's needs, you might want to exit or fail gracefully here.
|
27 |
raise
|
28 |
|
29 |
# π§Ύ Fetch and format headlines
|
30 |
def fetch_cached_headlines() -> str:
|
31 |
try:
|
32 |
-
# Assuming 'detailed_news_feed_cache' is the key for the final detailed headlines
|
33 |
-
# This key should match what's used in components/generators/detailed_explainer.py
|
34 |
raw = redis_client.get("detailed_news_feed_cache")
|
35 |
if not raw:
|
36 |
logging.warning("β οΈ No detailed news headlines found in cache.")
|
@@ -42,28 +40,20 @@ def fetch_cached_headlines() -> str:
|
|
42 |
|
43 |
message_parts = ["ποΈ *Your Daily Digest* π‘\n"]
|
44 |
|
45 |
-
# Iterate through topics in the order defined by TOPIC_KEYS (if available, otherwise iterate data.items())
|
46 |
-
# Assuming TOPIC_KEYS is available globally or passed here if needed for consistent order
|
47 |
-
# For now, just iterate through the data items as they are in the cached JSON
|
48 |
-
|
49 |
-
# Sort topics alphabetically for consistent output if no external order is provided
|
50 |
sorted_topics = sorted(data.keys())
|
51 |
|
52 |
for topic_key in sorted_topics:
|
53 |
stories = data[topic_key]
|
54 |
-
# Format topic title nicely (e.g., "india" -> "India", "world" -> "World")
|
55 |
title = topic_key.replace("_", " ").title()
|
56 |
message_parts.append(f"π·οΈ *{title}*")
|
57 |
|
58 |
-
|
59 |
-
sorted_story_ids = sorted(stories.keys(), key=int) # Ensure keys are treated as integers for sorting
|
60 |
|
61 |
for ref_id in sorted_story_ids:
|
62 |
item = stories[ref_id]
|
63 |
-
summary = item.get("title", "")
|
64 |
-
description = item.get("description", "")
|
65 |
|
66 |
-
# Ensure ref_id is a string for the message
|
67 |
message_parts.append(f"{ref_id}. {summary}\n_Why this matters_: {description}")
|
68 |
message_parts.append("") # spacing between sections
|
69 |
|
@@ -77,16 +67,16 @@ def send_to_whatsapp(message_text: str) -> dict:
|
|
77 |
logging.error(error_msg)
|
78 |
return {"status": "failed", "error": error_msg, "code": 500}
|
79 |
|
80 |
-
# Gupshup requires the API key in the 'apikey' header
|
81 |
headers = {
|
82 |
"Content-Type": "application/x-www-form-urlencoded",
|
83 |
-
"apikey": WHATSAPP_TOKEN #
|
|
|
84 |
}
|
85 |
|
86 |
payload = {
|
87 |
"channel": "whatsapp",
|
88 |
"source": GUPSHUP_SOURCE_NUMBER,
|
89 |
-
"destination": WHATSAPP_TO_NUMBER,
|
90 |
"message": json.dumps({
|
91 |
"type": "text",
|
92 |
"text": message_text
|
@@ -95,12 +85,11 @@ def send_to_whatsapp(message_text: str) -> dict:
|
|
95 |
}
|
96 |
|
97 |
try:
|
98 |
-
logging.info(f"Attempting to send WhatsApp message to {WHATSAPP_TO_NUMBER} via Gupshup.")
|
99 |
response = requests.post(
|
100 |
-
WHATSAPP_API_URL,
|
101 |
headers=headers,
|
102 |
-
data=payload,
|
103 |
-
# auth=(WHATSAPP_TOKEN, '') # <<< REMOVED: This sends Basic Auth, which Gupshup doesn't support for API key
|
104 |
)
|
105 |
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
|
106 |
|
@@ -130,19 +119,12 @@ def send_daily_whatsapp_digest():
|
|
130 |
logging.info("β
WhatsApp message sent successfully.")
|
131 |
return JSONResponse(status_code=200, content=result)
|
132 |
else:
|
133 |
-
logging.error(f"β Failed to send WhatsApp message: {result.get(
|
134 |
return JSONResponse(status_code=result.get("code", 500), content=result)
|
135 |
|
136 |
# π§ͺ For local testing
|
137 |
if __name__ == "__main__":
|
138 |
-
|
139 |
-
os.environ.setdefault("WHATSAPP_API_URL", "https://api.gupshup.io/sm/api/v1/msg")
|
140 |
-
os.environ.setdefault("WHATSAPP_TOKEN", "sk_e73f674b797549ed80c85105ded5a0d1") # Replace with a real dummy or your actual key
|
141 |
-
os.environ.setdefault("WHATSAPP_TO_NUMBER", "35389945777") # Replace with a test number
|
142 |
-
os.environ.setdefault("GUPSHUP_SOURCE_NUMBER", "15557926439") # Replace with your WABA number
|
143 |
-
os.environ.setdefault("GUPSHUP_APP_NAME", "NuseAI") # Replace with your app name
|
144 |
-
|
145 |
-
# Simulate a cached detailed feed for testing
|
146 |
dummy_cached_detailed_feed = {
|
147 |
"india": {
|
148 |
"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"]},
|
@@ -162,6 +144,5 @@ if __name__ == "__main__":
|
|
162 |
print(msg_preview)
|
163 |
|
164 |
logging.info("\n--- Sending WhatsApp Message (Test) ---\n")
|
165 |
-
# This will attempt to send a real message if your env vars are valid
|
166 |
test_result = send_to_whatsapp(msg_preview)
|
167 |
print(test_result)
|
|
|
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 |
# π Redis config
|
12 |
REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
|
13 |
+
# <<< CHANGE 1: Update the API URL to match the curl template >>>
|
14 |
+
WHATSAPP_API_URL = os.environ.get("WHATSAPP_API_URL", "https://api.gupshup.io/wa/api/v1/msg")
|
15 |
+
WHATSAPP_TOKEN = os.environ.get("WHATSAPP_TOKEN")
|
16 |
+
WHATSAPP_TO_NUMBER = os.environ.get("WHATSAPP_TO_NUMBER") # e.g., "91xxxxxxxxxx"
|
17 |
+
GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER") # e.g., your WABA number
|
18 |
+
GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME") # e.g., your Gupshup app name
|
19 |
|
20 |
# β
Redis connection
|
21 |
try:
|
|
|
24 |
logging.info("Redis client connected successfully.")
|
25 |
except Exception as e:
|
26 |
logging.error(f"β Failed to connect to Redis: {e}")
|
|
|
27 |
raise
|
28 |
|
29 |
# π§Ύ Fetch and format headlines
|
30 |
def fetch_cached_headlines() -> str:
|
31 |
try:
|
|
|
|
|
32 |
raw = redis_client.get("detailed_news_feed_cache")
|
33 |
if not raw:
|
34 |
logging.warning("β οΈ No detailed news headlines found in cache.")
|
|
|
40 |
|
41 |
message_parts = ["ποΈ *Your Daily Digest* π‘\n"]
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
sorted_topics = sorted(data.keys())
|
44 |
|
45 |
for topic_key in sorted_topics:
|
46 |
stories = data[topic_key]
|
|
|
47 |
title = topic_key.replace("_", " ").title()
|
48 |
message_parts.append(f"π·οΈ *{title}*")
|
49 |
|
50 |
+
sorted_story_ids = sorted(stories.keys(), key=int)
|
|
|
51 |
|
52 |
for ref_id in sorted_story_ids:
|
53 |
item = stories[ref_id]
|
54 |
+
summary = item.get("title", "")
|
55 |
+
description = item.get("description", "")
|
56 |
|
|
|
57 |
message_parts.append(f"{ref_id}. {summary}\n_Why this matters_: {description}")
|
58 |
message_parts.append("") # spacing between sections
|
59 |
|
|
|
67 |
logging.error(error_msg)
|
68 |
return {"status": "failed", "error": error_msg, "code": 500}
|
69 |
|
|
|
70 |
headers = {
|
71 |
"Content-Type": "application/x-www-form-urlencoded",
|
72 |
+
"apikey": WHATSAPP_TOKEN, # API key in 'apikey' header
|
73 |
+
"Cache-Control": "no-cache" # <<< CHANGE 2: Add Cache-Control header
|
74 |
}
|
75 |
|
76 |
payload = {
|
77 |
"channel": "whatsapp",
|
78 |
"source": GUPSHUP_SOURCE_NUMBER,
|
79 |
+
"destination": WHATSAPP_TO_NUMBER, # Ensure this holds the full number, not just '91'
|
80 |
"message": json.dumps({
|
81 |
"type": "text",
|
82 |
"text": message_text
|
|
|
85 |
}
|
86 |
|
87 |
try:
|
88 |
+
logging.info(f"Attempting to send WhatsApp message to {WHATSAPP_TO_NUMBER} via Gupshup. API URL: {WHATSAPP_API_URL}")
|
89 |
response = requests.post(
|
90 |
+
WHATSAPP_API_URL, # Uses the updated URL
|
91 |
headers=headers,
|
92 |
+
data=payload, # requests will correctly url-encode this dict
|
|
|
93 |
)
|
94 |
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
|
95 |
|
|
|
119 |
logging.info("β
WhatsApp message sent successfully.")
|
120 |
return JSONResponse(status_code=200, content=result)
|
121 |
else:
|
122 |
+
logging.error(f"β Failed to send WhatsApp message: {result.get("error")}")
|
123 |
return JSONResponse(status_code=result.get("code", 500), content=result)
|
124 |
|
125 |
# π§ͺ For local testing
|
126 |
if __name__ == "__main__":
|
127 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
dummy_cached_detailed_feed = {
|
129 |
"india": {
|
130 |
"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"]},
|
|
|
144 |
print(msg_preview)
|
145 |
|
146 |
logging.info("\n--- Sending WhatsApp Message (Test) ---\n")
|
|
|
147 |
test_result = send_to_whatsapp(msg_preview)
|
148 |
print(test_result)
|