ragV98 commited on
Commit
9f13b5b
ยท
1 Parent(s): 3bbcbf3

once again

Browse files
Files changed (1) hide show
  1. components/gateways/headlines_to_wa.py +26 -103
components/gateways/headlines_to_wa.py CHANGED
@@ -2,14 +2,11 @@ import os
2
  import json
3
  import redis
4
  import requests
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
 
12
- # ๐ŸŒ Configuration from Environment Variables
13
  REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
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")
@@ -17,7 +14,7 @@ WHATSAPP_TO_NUMBER = os.environ.get("WHATSAPP_TO_NUMBER", "353899495777")
17
  GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER")
18
  GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME")
19
 
20
- # โœ… Redis connection
21
  try:
22
  redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
23
  redis_client.ping()
@@ -26,19 +23,9 @@ except Exception as e:
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")
44
  if not raw:
@@ -57,17 +44,23 @@ def fetch_cached_headlines() -> str:
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)
@@ -77,9 +70,8 @@ def fetch_cached_headlines() -> str:
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("โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”")
@@ -87,6 +79,7 @@ def fetch_cached_headlines() -> str:
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
@@ -106,7 +99,8 @@ def send_to_whatsapp(message_text: str, destination_number: str) -> dict:
106
  headers = {
107
  "Content-Type": "application/x-www-form-urlencoded",
108
  "apikey": WHATSAPP_TOKEN,
109
- "Cache-Control": "no-cache"
 
110
  }
111
 
112
  whatsapp_message_content = {
@@ -119,7 +113,9 @@ def send_to_whatsapp(message_text: str, destination_number: str) -> dict:
119
  "source": GUPSHUP_SOURCE_NUMBER,
120
  "destination": destination_number,
121
  "src.name": GUPSHUP_APP_NAME,
122
- "message": json.dumps(whatsapp_message_content)
 
 
123
  }
124
 
125
  try:
@@ -137,77 +133,4 @@ def send_to_whatsapp(message_text: str, destination_number: str) -> dict:
137
  return {"status": "failed", "error": str(e), "code": e.response.status_code if e.response else 500}
138
  except Exception as e:
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():
147
- logging.info("API Call: /send-daily-whatsapp initiated.")
148
-
149
- full_message_text = fetch_cached_headlines()
150
-
151
- if full_message_text.startswith("โŒ") or full_message_text.startswith("โš ๏ธ"):
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.")
160
- return JSONResponse(status_code=200, content=result)
161
- else:
162
- logging.error(f"โŒ Failed to send WhatsApp message: {result.get('error')}")
163
- return JSONResponse(status_code=result.get("code", 500), content=result)
164
-
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)
 
2
  import json
3
  import redis
4
  import requests
 
 
5
  import logging
 
6
 
7
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
8
 
9
+ # ๐ŸŒ Configuration from Environment Variables (rest of the file's global section)
10
  REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
11
  WHATSAPP_API_URL = os.environ.get("WHATSAPP_API_URL", "https://api.gupshup.io/wa/api/v1/msg")
12
  WHATSAPP_TOKEN = os.environ.get("WHATSAPP_TOKEN")
 
14
  GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER")
15
  GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME")
16
 
17
+ # โœ… Redis connection (rest of the file's redis connection)
18
  try:
19
  redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
20
  redis_client.ping()
 
23
  logging.error(f"โŒ Failed to connect to Redis: {e}")
24
  raise
25
 
26
+ # ๐Ÿงพ Fetch and format headlines (rest of the file's fetch_cached_headlines)
 
 
 
 
 
 
 
 
 
 
 
27
  def fetch_cached_headlines() -> str:
28
+ # ... (rest of your fetch_cached_headlines function) ...
29
  try:
30
  raw = redis_client.get("detailed_news_feed_cache")
31
  if not raw:
 
44
  message_parts = []
45
 
46
  # Header section
47
+ message_parts.append(f"Nuse Daily - {formatted_date}")
48
+ message_parts.append("")
49
+
50
+ # --- New: Topic mapping for display names and emojis ---
51
+ TOPIC_DISPLAY_MAP = {
52
+ "india": {"name": "India", "emoji": "๐Ÿ‡ฎ๐Ÿ‡ณ"},
53
+ "world": {"name": "World", "emoji": "๐ŸŒ"},
54
+ "tech": {"name": "Technology", "emoji": "๐Ÿง "}, # Used brain emoji from your curl
55
+ "finance": {"name": "Business & Markets", "emoji": "๐Ÿ’ฐ"}, # Used money bag emoji from your curl
56
+ "sports": {"name": "Sports", "emoji": "๐Ÿ†"}, # Used trophy emoji from your curl
57
+ }
58
 
59
  # Iterate through topics in a defined order for consistent output
60
+ for topic_key, display_info in TOPIC_DISPLAY_MAP.items(): # TOPIC_DISPLAY_MAP needs to be defined
61
+ stories_for_topic = data.get(topic_key)
 
62
 
63
+ if stories_for_topic:
64
  message_parts.append(f"{display_info['emoji']} *{display_info['name']}*")
65
 
66
  sorted_story_ids = sorted(stories_for_topic.keys(), key=int)
 
70
  summary = item.get("title", "")
71
  description = item.get("description", "")
72
 
 
73
  message_parts.append(f"\u2007{ref_id}. \u2007{summary}\n_Why this matters_: {description}")
74
+ message_parts.append("")
75
 
76
  # Footer section
77
  message_parts.append("โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”")
 
79
 
80
  return "\n".join(message_parts)
81
 
82
+
83
  # ๐Ÿ“ค Send via Gupshup WhatsApp API
84
  def send_to_whatsapp(message_text: str, destination_number: str) -> dict:
85
  # Validate critical environment variables
 
99
  headers = {
100
  "Content-Type": "application/x-www-form-urlencoded",
101
  "apikey": WHATSAPP_TOKEN,
102
+ "Cache-Control": "no-cache",
103
+ "accept": "application/json" # <<< ADDED: Accept header
104
  }
105
 
106
  whatsapp_message_content = {
 
113
  "source": GUPSHUP_SOURCE_NUMBER,
114
  "destination": destination_number,
115
  "src.name": GUPSHUP_APP_NAME,
116
+ "message": json.dumps(whatsapp_message_content),
117
+ "disablePreview": False, # <<< ADDED: disablePreview parameter
118
+ "encode": False # <<< ADDED: encode parameter
119
  }
120
 
121
  try:
 
133
  return {"status": "failed", "error": str(e), "code": e.response.status_code if e.response else 500}
134
  except Exception as e:
135
  logging.error(f"โŒ An unexpected error occurred during WhatsApp send: {e}")
136
+ return {"status": "failed", "error": str(e), "code": 500}