ragV98 commited on
Commit
eb882d5
Β·
1 Parent(s): f1e54f5

could work

Browse files
components/gateways/headlines_to_wa.py CHANGED
@@ -2,22 +2,23 @@ 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
 
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
  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", "353899495777") # Default can be changed
17
  GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER")
18
  GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME")
19
 
20
- # βœ… Redis connection (assuming it's connected successfully elsewhere in the full file)
21
  try:
22
  redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
23
  redis_client.ping()
@@ -26,9 +27,8 @@ except Exception as e:
26
  logging.error(f"❌ Failed to connect to Redis: {e}")
27
  raise
28
 
29
- # 🧾 Fetch and format headlines (assuming this function is defined as before)
30
  def fetch_cached_headlines() -> str:
31
- # ... (content of your fetch_cached_headlines function) ...
32
  try:
33
  raw = redis_client.get("detailed_news_feed_cache")
34
  if not raw:
@@ -56,21 +56,23 @@ 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
- # No extra empty line needed here if we add newline to topic title
60
 
61
  return "\n".join(message_parts)
62
 
63
  # πŸ“€ Send via Gupshup WhatsApp API
64
- def send_to_whatsapp(message_text: str, destination_number: str) -> dict: # destination_number is required
65
- # Validate critical environment variables for sending a message
 
 
 
 
66
  if not WHATSAPP_TOKEN or \
67
  not GUPSHUP_SOURCE_NUMBER or \
68
- not GUPSHUP_APP_NAME: # WHATSAPP_TO_NUMBER is no longer critically validated here, as it's passed as an argument
69
  error_msg = "❌ Missing one or more critical WhatsApp API environment variables (WHATSAPP_TOKEN, GUPSHUP_SOURCE_NUMBER, GUPSHUP_APP_NAME)."
70
  logging.error(error_msg)
71
  return {"status": "failed", "error": error_msg, "code": 500}
72
 
73
- # It's good practice to ensure the destination number itself isn't empty
74
  if not destination_number:
75
  error_msg = "❌ Destination number cannot be empty."
76
  logging.error(error_msg)
@@ -83,22 +85,37 @@ def send_to_whatsapp(message_text: str, destination_number: str) -> dict: # dest
83
  "Cache-Control": "no-cache"
84
  }
85
 
86
- whatsapp_message_content = {
87
- "type": "text",
88
- "text": message_text
89
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
  payload = {
92
  "channel": "whatsapp",
93
  "source": GUPSHUP_SOURCE_NUMBER,
94
- "destination": destination_number, # Use the passed destination_number
95
  "src.name": GUPSHUP_APP_NAME,
96
  "message": json.dumps(whatsapp_message_content)
97
  }
98
 
99
  try:
100
- # FIX: Log the actual destination_number being used
101
- logging.info(f"Attempting to send standard text WhatsApp message to {destination_number} via Gupshup. API URL: {WHATSAPP_API_URL}")
102
  response = requests.post(
103
  WHATSAPP_API_URL,
104
  headers=headers,
@@ -114,8 +131,8 @@ def send_to_whatsapp(message_text: str, destination_number: str) -> dict: # dest
114
  logging.error(f"❌ An unexpected error occurred during WhatsApp send: {e}")
115
  return {"status": "failed", "error": str(e), "code": 500}
116
 
117
- # πŸš€ FastAPI App
118
- app = FastAPI()
119
 
120
  @app.get("/send-daily-whatsapp")
121
  def send_daily_whatsapp_digest():
@@ -127,9 +144,20 @@ def send_daily_whatsapp_digest():
127
  logging.warning(f"Returning error due to issue fetching headlines: {full_message_text}")
128
  return JSONResponse(status_code=404, content={"error": full_message_text})
129
 
130
- # Call send_to_whatsapp with the default destination from environment variable
131
- # This now requires WHATSAPP_TO_NUMBER to be set and passed
132
- result = send_to_whatsapp(full_message_text, destination_number=WHATSAPP_TO_NUMBER)
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  if result.get("status") == "success":
135
  logging.info("βœ… WhatsApp message sent successfully.")
@@ -141,13 +169,11 @@ def send_daily_whatsapp_digest():
141
  # πŸ§ͺ For local testing
142
  if __name__ == "__main__":
143
  # For local testing, ensure these environment variables are set in your shell or .env file.
144
- # Example .env content:
145
- # UPSTASH_REDIS_URL="redis://your_redis_url"
146
- # WHATSAPP_API_URL="https://api.gupshup.io/wa/api/v1/msg"
147
- # WHATSAPP_TOKEN="YOUR_GUPSHUP_API_KEY"
148
- # WHATSAPP_TO_NUMBER="919999999999" # Ensure this is set for direct use by send_daily_whatsapp_digest
149
- # GUPSHUP_SOURCE_NUMBER="15557926439"
150
- # GUPSHUP_APP_NAME="NuseAI"
151
 
152
  # Simulate a cached detailed feed for testing
153
  dummy_cached_detailed_feed = {
@@ -164,14 +190,18 @@ if __name__ == "__main__":
164
  redis_client.set("detailed_news_feed_cache", json.dumps(dummy_cached_detailed_feed))
165
 
166
 
167
- logging.info("\n--- WhatsApp Message Preview ---\n")
168
- msg_preview = fetch_cached_headlines()
169
- print(msg_preview)
170
-
171
- logging.info("\n--- Sending WhatsApp Message (Test) ---\n")
172
- # When testing locally, you might pass a specific number here
173
- # test_result = send_to_whatsapp(msg_preview, destination_number="919999999999")
174
 
175
- # If running the app via uvicorn and hitting the /send-daily-whatsapp endpoint,
176
- # it will use WHATSAPP_TO_NUMBER from os.environ.get
177
- print("Run `uvicorn your_app_file:app --reload` and visit /send-daily-whatsapp in browser or curl.")
 
 
 
 
 
 
 
 
 
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 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
 
13
  # 🌐 Configuration from Environment Variables
 
14
  REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
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", "353899495777")
18
  GUPSHUP_SOURCE_NUMBER = os.environ.get("GUPSHUP_SOURCE_NUMBER")
19
  GUPSHUP_APP_NAME = os.environ.get("GUPSHUP_APP_NAME")
20
 
21
+ # βœ… Redis connection
22
  try:
23
  redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
24
  redis_client.ping()
 
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")
34
  if not raw:
 
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 \
71
+ not GUPSHUP_APP_NAME:
72
  error_msg = "❌ Missing one or more critical WhatsApp API environment variables (WHATSAPP_TOKEN, GUPSHUP_SOURCE_NUMBER, GUPSHUP_APP_NAME)."
73
  logging.error(error_msg)
74
  return {"status": "failed", "error": error_msg, "code": 500}
75
 
 
76
  if not destination_number:
77
  error_msg = "❌ Destination number cannot be empty."
78
  logging.error(error_msg)
 
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",
111
  "source": GUPSHUP_SOURCE_NUMBER,
112
+ "destination": destination_number,
113
  "src.name": GUPSHUP_APP_NAME,
114
  "message": json.dumps(whatsapp_message_content)
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
  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
  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
  # πŸ§ͺ 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 = {
 
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)