ragV98 commited on
Commit
3bbcbf3
·
1 Parent(s): eb882d5

adding temp

Browse files
components/gateways/headlines_to_wa.py CHANGED
@@ -5,8 +5,7 @@ import requests
5
  from fastapi import FastAPI
6
  from fastapi.responses import JSONResponse
7
  import logging
8
- import time # Import time for a simple dynamic msgid if needed
9
- from typing import List, Dict, Any, Optional # Import Optional and List for type hints
10
 
11
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
12
 
@@ -27,7 +26,18 @@ except Exception as e:
27
  logging.error(f"❌ Failed to connect to Redis: {e}")
28
  raise
29
 
 
 
 
 
 
 
 
 
 
 
30
  # 🧾 Fetch and format headlines
 
31
  def fetch_cached_headlines() -> str:
32
  try:
33
  raw = redis_client.get("detailed_news_feed_cache")
@@ -39,32 +49,46 @@ def fetch_cached_headlines() -> str:
39
  logging.error(f"❌ Error reading from Redis: {e}")
40
  return f"❌ Error reading from Redis: {e}"
41
 
42
- message_parts = ["🗞️ *Your Daily Digest* 🟡\n"]
43
-
44
- sorted_topics = sorted(data.keys())
 
45
 
46
- for topic_key in sorted_topics:
47
- stories = data[topic_key]
48
- title = topic_key.replace("_", " ").title()
49
- message_parts.append(f"\n🏷️ *{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]
55
- summary = item.get("title", "")
56
- description = item.get("description", "")
 
 
 
 
 
 
 
 
 
57
 
58
- message_parts.append(f"{ref_id}. {summary}\n_Why this matters_: {description}")
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  return "\n".join(message_parts)
61
 
62
  # 📤 Send via Gupshup WhatsApp API
63
- def send_to_whatsapp(
64
- message_text: str,
65
- destination_number: str,
66
- quick_reply_options: Optional[List[str]] = None # <<< NEW PARAMETER
67
- ) -> dict:
68
  # Validate critical environment variables
69
  if not WHATSAPP_TOKEN or \
70
  not GUPSHUP_SOURCE_NUMBER or \
@@ -85,26 +109,10 @@ def send_to_whatsapp(
85
  "Cache-Control": "no-cache"
86
  }
87
 
88
- # <<< CONDITIONAL MESSAGE PAYLOAD BASED ON QUICK REPLY OPTIONS >>>
89
- if quick_reply_options:
90
- if not (1 <= len(quick_reply_options) <= 10): # WhatsApp quick reply limits
91
- logging.error("❌ Quick reply options must be between 1 and 10.")
92
- return {"status": "failed", "error": "Quick reply options count out of range", "code": 400}
93
-
94
- whatsapp_message_content = {
95
- "type": "quick_reply",
96
- "msgid": f"outgoing_msg_{int(time.time())}", # Dynamic msgid for quick reply
97
- "content": {
98
- "type": "text",
99
- "text": message_text # Main text of the quick reply message
100
- },
101
- "options": quick_reply_options # The quick reply buttons
102
- }
103
- else:
104
- whatsapp_message_content = {
105
- "type": "text",
106
- "text": message_text # Standard text message
107
- }
108
 
109
  payload = {
110
  "channel": "whatsapp",
@@ -115,7 +123,7 @@ def send_to_whatsapp(
115
  }
116
 
117
  try:
118
- logging.info(f"Attempting to send {'Quick Reply' if quick_reply_options else 'standard text'} WhatsApp message to {destination_number} via Gupshup. API URL: {WHATSAPP_API_URL}")
119
  response = requests.post(
120
  WHATSAPP_API_URL,
121
  headers=headers,
@@ -131,8 +139,8 @@ def send_to_whatsapp(
131
  logging.error(f"❌ An unexpected error occurred during WhatsApp send: {e}")
132
  return {"status": "failed", "error": str(e), "code": 500}
133
 
134
- # 🚀 FastAPI App (assuming this instance is part of app.py now)
135
- app = FastAPI() # This should really be in app.py only
136
 
137
  @app.get("/send-daily-whatsapp")
138
  def send_daily_whatsapp_digest():
@@ -144,20 +152,8 @@ def send_daily_whatsapp_digest():
144
  logging.warning(f"Returning error due to issue fetching headlines: {full_message_text}")
145
  return JSONResponse(status_code=404, content={"error": full_message_text})
146
 
147
- # Example of how to call send_to_whatsapp with quick replies from this endpoint
148
- # You would typically define these options based on your use case
149
- quick_reply_options_for_digest = [
150
- "Read more",
151
- "Unsubscribe",
152
- "Contact Support"
153
- ]
154
-
155
- # Call send_to_whatsapp with quick reply options
156
- result = send_to_whatsapp(
157
- message_text=full_message_text,
158
- destination_number=os.environ.get("WHATSAPP_TO_NUMBER"),
159
- quick_reply_options=quick_reply_options_for_digest # Pass the options here
160
- )
161
 
162
  if result.get("status") == "success":
163
  logging.info("✅ WhatsApp message sent successfully.")
@@ -169,39 +165,49 @@ def send_daily_whatsapp_digest():
169
  # 🧪 For local testing
170
  if __name__ == "__main__":
171
  # For local testing, ensure these environment variables are set in your shell or .env file.
 
172
  os.environ.setdefault("WHATSAPP_API_URL", "https://api.gupshup.io/wa/api/v1/msg")
173
  os.environ.setdefault("WHATSAPP_TOKEN", "YOUR_GUPSHUP_API_KEY")
174
- os.environ.setdefault("WHATSAPP_TO_NUMBER", "919999999999") # Use a valid test number
175
  os.environ.setdefault("GUPSHUP_SOURCE_NUMBER", "15557926439")
176
  os.environ.setdefault("GUPSHUP_APP_NAME", "NuseAI")
177
 
178
  # Simulate a cached detailed feed for testing
179
  dummy_cached_detailed_feed = {
180
  "india": {
181
- "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"]},
182
- "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"]}
 
183
  },
184
  "world": {
185
- "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"]},
186
- "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"]}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  }
188
  }
189
  # Store dummy data in Redis for testing fetch_cached_headlines
190
  redis_client.set("detailed_news_feed_cache", json.dumps(dummy_cached_detailed_feed))
191
 
192
 
193
- logging.info("\n--- WhatsApp Message Preview (Quick Reply) ---\n")
194
- msg_body_preview = fetch_cached_headlines()
195
- print(msg_body_preview)
196
 
197
- # Test sending a Quick Reply message
198
- test_options = ["Yes, I like it!", "No, not for me.", "Tell me more"]
199
- logging.info("\n--- Sending WhatsApp Quick Reply Message (Test) ---\n")
200
- # This will attempt to send a real Quick Reply message if your env vars are valid
201
- test_result = send_to_whatsapp(msg_body_preview, destination_number=os.environ.get("WHATSAPP_TO_NUMBER"), quick_reply_options=test_options)
202
- print(test_result)
203
-
204
- logging.info("\n--- Sending WhatsApp Standard Text Message (Test) ---\n")
205
- # This will attempt to send a real standard text message
206
- test_result_standard = send_to_whatsapp("This is a test of a standard text message.", destination_number=os.environ.get("WHATSAPP_TO_NUMBER"), quick_reply_options=None)
207
- print(test_result_standard)
 
5
  from fastapi import FastAPI
6
  from fastapi.responses import JSONResponse
7
  import logging
8
+ import datetime # Import datetime for dynamic date
 
9
 
10
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
11
 
 
26
  logging.error(f"❌ Failed to connect to Redis: {e}")
27
  raise
28
 
29
+ # --- New: Topic mapping for display names and emojis ---
30
+ TOPIC_DISPLAY_MAP = {
31
+ "india": {"name": "India", "emoji": "🇮🇳"},
32
+ "world": {"name": "World", "emoji": "🌍"},
33
+ "tech": {"name": "Technology", "emoji": "🧠"}, # Used brain emoji from your curl
34
+ "finance": {"name": "Business & Markets", "emoji": "💰"}, # Used money bag emoji from your curl
35
+ "sports": {"name": "Sports", "emoji": "🏆"}, # Used trophy emoji from your curl
36
+ }
37
+
38
+
39
  # 🧾 Fetch and format headlines
40
+ # UPDATED: To match the exact "NUSE DAILY" format
41
  def fetch_cached_headlines() -> str:
42
  try:
43
  raw = redis_client.get("detailed_news_feed_cache")
 
49
  logging.error(f"❌ Error reading from Redis: {e}")
50
  return f"❌ Error reading from Redis: {e}"
51
 
52
+ # Get current date for the header
53
+ today = datetime.date.today()
54
+ # Format: July 22, 2025
55
+ formatted_date = today.strftime("%B %d, %Y")
56
 
57
+ message_parts = []
 
 
 
 
 
58
 
59
+ # Header section
60
+ message_parts.append("🗞️ *NUSE DAILY* 🟡")
61
+ message_parts.append(f"{formatted_date} — Morning Edition")
62
+ message_parts.append("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") # Unicode Box Drawings Light Horizontal
63
+ message_parts.append("") # Empty line for spacing
64
+
65
+ # Iterate through topics in a defined order for consistent output
66
+ # Using the keys from TOPIC_DISPLAY_MAP to ensure order and access details
67
+ for topic_key, display_info in TOPIC_DISPLAY_MAP.items():
68
+ stories_for_topic = data.get(topic_key) # Get stories for this topic key
69
+
70
+ if stories_for_topic: # Only add topic section if there are stories
71
+ message_parts.append(f"{display_info['emoji']} *{display_info['name']}*")
72
 
73
+ sorted_story_ids = sorted(stories_for_topic.keys(), key=int)
74
+
75
+ for ref_id in sorted_story_ids:
76
+ item = stories_for_topic[ref_id]
77
+ summary = item.get("title", "")
78
+ description = item.get("description", "")
79
+
80
+ # Using U+2007 (Figure Space) for alignment as seen in your example
81
+ message_parts.append(f"\u2007{ref_id}. \u2007{summary}\n_Why this matters_: {description}")
82
+ message_parts.append("") # Empty line for spacing between topics
83
+
84
+ # Footer section
85
+ message_parts.append("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
86
+ message_parts.append("🟠 Curated by Nuse Editorial Desk")
87
 
88
  return "\n".join(message_parts)
89
 
90
  # 📤 Send via Gupshup WhatsApp API
91
+ def send_to_whatsapp(message_text: str, destination_number: str) -> dict:
 
 
 
 
92
  # Validate critical environment variables
93
  if not WHATSAPP_TOKEN or \
94
  not GUPSHUP_SOURCE_NUMBER or \
 
109
  "Cache-Control": "no-cache"
110
  }
111
 
112
+ whatsapp_message_content = {
113
+ "type": "text",
114
+ "text": message_text
115
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  payload = {
118
  "channel": "whatsapp",
 
123
  }
124
 
125
  try:
126
+ logging.info(f"Attempting to send standard text WhatsApp message to {destination_number} via Gupshup. API URL: {WHATSAPP_API_URL}")
127
  response = requests.post(
128
  WHATSAPP_API_URL,
129
  headers=headers,
 
139
  logging.error(f"❌ An unexpected error occurred during WhatsApp send: {e}")
140
  return {"status": "failed", "error": str(e), "code": 500}
141
 
142
+ # 🚀 FastAPI App (This part should ideally be in routes/api/wa_headlines.py, not here)
143
+ app = FastAPI()
144
 
145
  @app.get("/send-daily-whatsapp")
146
  def send_daily_whatsapp_digest():
 
152
  logging.warning(f"Returning error due to issue fetching headlines: {full_message_text}")
153
  return JSONResponse(status_code=404, content={"error": full_message_text})
154
 
155
+ # Call send_to_whatsapp with the default destination (from its os.environ.get)
156
+ result = send_to_whatsapp(full_message_text, destination_number=os.environ.get("WHATSAPP_TO_NUMBER"))
 
 
 
 
 
 
 
 
 
 
 
 
157
 
158
  if result.get("status") == "success":
159
  logging.info("✅ WhatsApp message sent successfully.")
 
165
  # 🧪 For local testing
166
  if __name__ == "__main__":
167
  # For local testing, ensure these environment variables are set in your shell or .env file.
168
+ os.environ.setdefault("UPSTASH_REDIS_URL", "redis://localhost:6379")
169
  os.environ.setdefault("WHATSAPP_API_URL", "https://api.gupshup.io/wa/api/v1/msg")
170
  os.environ.setdefault("WHATSAPP_TOKEN", "YOUR_GUPSHUP_API_KEY")
171
+ os.environ.setdefault("WHATSAPP_TO_NUMBER", "353899495777") # Use a valid test number
172
  os.environ.setdefault("GUPSHUP_SOURCE_NUMBER", "15557926439")
173
  os.environ.setdefault("GUPSHUP_APP_NAME", "NuseAI")
174
 
175
  # Simulate a cached detailed feed for testing
176
  dummy_cached_detailed_feed = {
177
  "india": {
178
+ "1": {"title": "RBI Holds Rates at 6.5% as Inflation Cools to 5.1%, Boosting Confidence Ahead of Festive Demand", "description": "The central bank's decision signals stability and aims to encourage consumer spending during the upcoming festive season, crucial for economic momentum. Lower inflation provides relief to households and supports growth prospects. The cautious approach balances economic recovery with price control.", "sources": ["Times of India"]},
179
+ "2": {"title": "Modi Inaugurates Global Summit Venue in Gandhinagar to Cement India’s Role as East–West Diplomatic Bridge", "description": "This new venue positions India as a key player in international diplomacy, fostering dialogue and collaboration between Asian and Western nations. It highlights the country's growing influence on global affairs and capacity for large-scale international events, boosting its soft power.", "sources": ["Indian Express"]},
180
+ "3": {"title": "Adani Pursues $50B Gulf Green Hydrogen Deal to Accelerate India’s Clean Energy Ambitions", "description": "This massive investment underscores India's commitment to renewable energy and its transition away from fossil fuels. Partnering with Gulf nations secures critical resources and technology, advancing India's position as a leader in green hydrogen production and reducing its carbon footprint.", "sources": ["The Economic Times"]}
181
  },
182
  "world": {
183
+ "4": {"title": "Biden Signs $95B Indo-Pacific Aid Bill, Reinforcing U.S. Strategy Against Chinese Expansion", "description": "The bill provides significant financial assistance to allies in the Indo-Pacific, strengthening regional security and economic ties. This move aims to counter China's growing influence and maintain stability in a strategically vital area, signaling continued U.S. commitment to its partners.", "sources": ["Reuters"]},
184
+ "5": {"title": "Hurricane Felix Strengthens Into Category 4, Florida Declares Statewide Emergency", "description": "The rapid intensification of Hurricane Felix poses a severe threat to coastal communities in Florida, prompting urgent evacuation orders and extensive preparedness measures. Residents are urged to secure their homes and follow safety guidelines as the storm approaches, emphasizing climate change impacts.", "sources": ["CNN World"]},
185
+ "6": {"title": "Iran’s Hardliner President Takes Office Amid Nuclear Tensions and Diplomatic Uncertainty", "description": "The new leadership in Iran signals a potential shift in foreign policy, raising concerns among international observers about the future of nuclear negotiations. Diplomatic tensions could escalate, impacting regional stability and global energy markets as nations reassess their strategies.", "sources": ["BBC News"]}
186
+ },
187
+ "finance": {
188
+ "7": {"title": "Nasdaq Surges as Nvidia and AI Stocks Power New Record Highs", "description": "The technology-heavy Nasdaq's rise reflects robust investor confidence in the artificial intelligence sector, with Nvidia leading the charge. This surge indicates strong market enthusiasm for innovation and potential future growth in tech, driving overall market performance.", "sources": ["CNBC"]},
189
+ "8": {"title": "Eurozone Inflation Falls Below 2.5%, Raising Hopes for ECB Rate Cuts in Q4", "description": "Declining inflation figures in the Eurozone signal easing price pressures, increasing the likelihood of interest rate reductions by the European Central Bank. Such cuts could stimulate economic activity and provide relief to consumers and businesses, supporting recovery efforts.", "sources": ["Financial Times"]},
190
+ "9": {"title": "Infosys Beats Earnings Expectations, Announces $1.5B Buyback", "description": "Infosys' strong financial performance demonstrates resilience in the IT services sector despite global economic uncertainties. The share buyback initiative signals confidence in the company's future prospects and aims to return value to shareholders, potentially boosting stock performance.", "sources": ["Economic Times"]}
191
+ },
192
+ "tech": {
193
+ "10": {"title": "Meta’s Llama 3.5 Rivals GPT-4 in Benchmarks, Marking Breakthrough for Open-Source AI", "description": "Meta's latest large language model, Llama 3.5, demonstrates impressive performance, challenging proprietary models like GPT-4. This development significantly advances open-source AI capabilities, promoting wider accessibility and innovation in artificial intelligence research and application development globally.", "sources": ["Wired"]},
194
+ "11": {"title": "Apple Unveils Foldable iPhone 17 with AI-Native OS, Signaling Shift Toward Software Innovation", "description": "Apple's new foldable smartphone, featuring a deeply integrated AI operating system, marks a significant technological leap. This move emphasizes a strategic shift towards software-driven experiences and design innovation, potentially reshaping the smartphone market and user interaction paradigms.", "sources": ["The Verge"]},
195
+ "12": {"title": "Google Partners With Indian Startups to Expand Regional AI Tools", "description": "Google's collaboration with Indian startups aims to foster localized AI solutions, addressing unique market needs and promoting technological advancement in the region. This initiative supports the growth of India's tech ecosystem and expands Google's reach into emerging markets, boosting digital transformation.", "sources": ["TechCrunch"]}
196
+ },
197
+ "sports": {
198
+ "13": {"title": "India Clinches T20 Series vs West Indies With Last-Over Thriller in Port of Spain", "description": "India's dramatic series victory showcases their resilience and strategic prowess in high-pressure cricket matches. This win boosts team morale and demonstrates strong form ahead of upcoming international tournaments, solidifying their position in global T20 rankings.", "sources": ["ESPN Cricinfo"]},
199
+ "14": {"title": "Messi Breaks MLS Scoring Record With Hat-Trick for Inter Miami", "description": "Lionel Messi continues to redefine Major League Soccer, setting a new scoring record with his exceptional performance for Inter Miami. His consistent brilliance elevates the league's global profile and inspires a new generation of football fans across North America.", "sources": ["MLS Soccer"]},
200
+ "15": {"title": "Olympic Torch Relay Kicks Off in Paris With 100 Days Until Opening", "description": "The ceremonial start of the Olympic Torch Relay in Paris ignites excitement and anticipation for the upcoming Summer Games. This milestone event symbolizes unity and athletic spirit, bringing the global community together in the countdown to the prestigious sporting spectacle.", "sources": ["Olympic.org"]}
201
  }
202
  }
203
  # Store dummy data in Redis for testing fetch_cached_headlines
204
  redis_client.set("detailed_news_feed_cache", json.dumps(dummy_cached_detailed_feed))
205
 
206
 
207
+ logging.info("\n--- WhatsApp Message Preview ---\n")
208
+ msg_preview = fetch_cached_headlines()
209
+ print(msg_preview)
210
 
211
+ logging.info("\n--- Sending WhatsApp Message (Test) ---\n")
212
+ test_result = send_to_whatsapp(msg_preview, destination_number=os.environ.get("WHATSAPP_TO_NUMBER"))
213
+ print(test_result)