Chandima Prabhath commited on
Commit
9b5a03d
·
1 Parent(s): e341e67

Implement WhatsApp status updater with image generation and sending functionality

Browse files
Files changed (1) hide show
  1. app.py +64 -60
app.py CHANGED
@@ -26,6 +26,10 @@ BOT_STATUS_CHAT = "[email protected]" # Chat ID for system messages
26
  image_dir = "/tmp/images"
27
  audio_dir = "/tmp/audio"
28
 
 
 
 
 
29
  if not all([GREEN_API_URL, GREEN_API_TOKEN, GREEN_API_ID_INSTANCE, WEBHOOK_AUTH_TOKEN]):
30
  raise ValueError("Environment variables are not set properly")
31
 
@@ -52,7 +56,7 @@ def inactivity_monitor():
52
 
53
  threading.Thread(target=inactivity_monitor, daemon=True).start()
54
 
55
- # --- Background Worker for normal tasks ---
56
  def worker():
57
  while True:
58
  task = task_queue.get()
@@ -71,60 +75,6 @@ def worker():
71
 
72
  threading.Thread(target=worker, daemon=True).start()
73
 
74
- # --- WhatsApp Status Updater ---
75
- def send_status_image(image_path, caption=""):
76
- """
77
- Send an image as WhatsApp status using the Green API.
78
- The endpoint used here is assumed to be `/sendFileStatus`.
79
- Adjust the URL if the docs specify a different endpoint.
80
- """
81
- url = f"{GREEN_API_MEDIA_URL}/waInstance{GREEN_API_ID_INSTANCE}/sendFileStatus/{GREEN_API_TOKEN}"
82
- payload = {"caption": caption}
83
- files = [("file", ("status.jpg", open(image_path, "rb"), "image/jpeg"))]
84
- retries = 3
85
- for i in range(retries):
86
- try:
87
- r = requests.post(url, data=payload, files=files)
88
- r.raise_for_status()
89
- logging.debug("Status image sent successfully.")
90
- return r.json()
91
- except requests.RequestException as e:
92
- logging.error("send_status_image attempt %d failed: %s", i+1, e)
93
- if i == retries - 1:
94
- return {"error": str(e)}
95
-
96
- def status_updater():
97
- """
98
- Background thread that every 2 minutes:
99
- 1. Generates a random image prompt using the LLM.
100
- 2. Generates an image from that prompt.
101
- 3. Updates the WhatsApp status with the generated image.
102
- """
103
- while True:
104
- try:
105
- # Generate a random creative prompt for a status image.
106
- prompt_llm = "Generate a unique and creative image prompt suitable for a WhatsApp status update."
107
- random_prompt = generate_llm(prompt_llm).strip()
108
- logging.debug("Random status prompt: %s", random_prompt)
109
-
110
- # Generate the image from the prompt.
111
- img, path, ret_prompt, url_img = generate_image(random_prompt, "status", "status", image_dir)
112
- if img:
113
- caption = f"Status updated! {ret_prompt}"
114
- send_status_image(path, caption=caption)
115
- logging.info("WhatsApp status updated with image: %s", url_img)
116
- # Clean up the image file if needed.
117
- if os.path.exists(path):
118
- os.remove(path)
119
- else:
120
- logging.error("Image generation for status failed for prompt: %s", random_prompt)
121
- except Exception as e:
122
- logging.error("Error in status_updater: %s", e)
123
- # Wait for 2 minutes before updating status again.
124
- time.sleep(120)
125
-
126
- threading.Thread(target=status_updater, daemon=True).start()
127
-
128
  # --- send helpers ---
129
  def send_message_to_chat(to_number, message, retries=3):
130
  chat_id = to_number if to_number.endswith("@g.us") else to_number
@@ -188,6 +138,30 @@ def send_audio(message_id, to_number, audio_path, retries=3):
188
  except Exception as e:
189
  return {"error": str(e)}
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  # --- core response functions ---
192
  def response_text(message_id, chat_id, prompt):
193
  try:
@@ -214,7 +188,8 @@ def response_audio(message_id, chat_id, prompt):
214
  def handle_image_generation(message_id, chat_id, prompt):
215
  for i in range(4):
216
  try:
217
- img, path, ret_prompt, url_img = generate_image(prompt, message_id, message_id, image_dir)
 
218
  if img:
219
  formatted_ret_prompt = "\n\n".join(
220
  f"_{paragraph.strip()}_" for paragraph in ret_prompt.split("\n\n") if paragraph.strip()
@@ -223,14 +198,43 @@ def handle_image_generation(message_id, chat_id, prompt):
223
  message_id,
224
  chat_id,
225
  path,
226
- caption=f"✨ Image ready: {url_img}\n>{chr(8203)} {formatted_ret_prompt}"
227
  )
228
  else:
229
  send_message(message_id, chat_id, "Image generation failed.")
 
230
  except Exception as e:
231
  logging.error("Error in handle_image_generation: %s", e)
232
  send_message(message_id, chat_id, "Error generating image.")
233
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  # --- Startup Message ---
235
  def send_startup_message():
236
  if BOT_STATUS_CHAT:
@@ -272,7 +276,7 @@ async def whatsapp_webhook(request: Request):
272
  data = await request.json()
273
  chat_id = data["senderData"]["chatId"]
274
  print(f"New message from chat ID: {chat_id}")
275
- except Exception:
276
  return JSONResponse({"error": "Invalid JSON"}, status_code=400)
277
  if data.get("typeWebhook") != "incomingMessageReceived":
278
  return {"success": True}
@@ -329,7 +333,7 @@ async def whatsapp_webhook(request: Request):
329
  try:
330
  joke = requests.get("https://official-joke-api.appspot.com/random_joke", timeout=5).json()
331
  send_message(mid, chat, f"{joke['setup']}\n\n{joke['punchline']}")
332
- except Exception:
333
  send_message(mid, chat, generate_llm("Tell me a short, funny joke."))
334
  return {"success": True}
335
 
@@ -338,7 +342,7 @@ async def whatsapp_webhook(request: Request):
338
  try:
339
  w = requests.get(f"http://sl.wttr.in/{loc}?format=4", timeout=5).text
340
  send_message(mid, chat, w)
341
- except Exception:
342
  send_message(mid, chat, "Could not fetch weather.")
343
  return {"success": True}
344
 
 
26
  image_dir = "/tmp/images"
27
  audio_dir = "/tmp/audio"
28
 
29
+ # Ensure necessary directories exist
30
+ os.makedirs(image_dir, exist_ok=True)
31
+ os.makedirs(audio_dir, exist_ok=True)
32
+
33
  if not all([GREEN_API_URL, GREEN_API_TOKEN, GREEN_API_ID_INSTANCE, WEBHOOK_AUTH_TOKEN]):
34
  raise ValueError("Environment variables are not set properly")
35
 
 
56
 
57
  threading.Thread(target=inactivity_monitor, daemon=True).start()
58
 
59
+ # --- Background Worker ---
60
  def worker():
61
  while True:
62
  task = task_queue.get()
 
75
 
76
  threading.Thread(target=worker, daemon=True).start()
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  # --- send helpers ---
79
  def send_message_to_chat(to_number, message, retries=3):
80
  chat_id = to_number if to_number.endswith("@g.us") else to_number
 
138
  except Exception as e:
139
  return {"error": str(e)}
140
 
141
+ # --- New helper: send WhatsApp status image ---
142
+ def send_status_image(image_path, caption="Status Update", retries=3):
143
+ """
144
+ Sends an image as your WhatsApp status update using Green API's sendMediaStatus endpoint.
145
+ """
146
+ url = f"{GREEN_API_MEDIA_URL}/waInstance{GREEN_API_ID_INSTANCE}/sendMediaStatus/{GREEN_API_TOKEN}"
147
+ payload = {"caption": caption}
148
+ try:
149
+ with open(image_path, "rb") as f:
150
+ files = [("file", ("status.jpg", f, "image/jpeg"))]
151
+ for i in range(retries):
152
+ try:
153
+ r = requests.post(url, data=payload, files=files)
154
+ r.raise_for_status()
155
+ logging.info("Status image sent successfully.")
156
+ return r.json()
157
+ except requests.RequestException as e:
158
+ if i == retries - 1:
159
+ logging.error("send_status_image failed: %s", str(e))
160
+ return {"error": str(e)}
161
+ except Exception as e:
162
+ logging.error("Error opening status image: %s", e)
163
+ return {"error": str(e)}
164
+
165
  # --- core response functions ---
166
  def response_text(message_id, chat_id, prompt):
167
  try:
 
188
  def handle_image_generation(message_id, chat_id, prompt):
189
  for i in range(4):
190
  try:
191
+ # Here we pass "message_id" for both the message and chat identifiers.
192
+ img, path, ret_prompt, url = generate_image(prompt, message_id, message_id, image_dir)
193
  if img:
194
  formatted_ret_prompt = "\n\n".join(
195
  f"_{paragraph.strip()}_" for paragraph in ret_prompt.split("\n\n") if paragraph.strip()
 
198
  message_id,
199
  chat_id,
200
  path,
201
+ caption=f"✨ Image ready: {url}\n>{chr(8203)} {formatted_ret_prompt}"
202
  )
203
  else:
204
  send_message(message_id, chat_id, "Image generation failed.")
205
+ break # exit on success
206
  except Exception as e:
207
  logging.error("Error in handle_image_generation: %s", e)
208
  send_message(message_id, chat_id, "Error generating image.")
209
 
210
+ # --- New background thread: WhatsApp Status Updater ---
211
+ def whatsapp_status_updater():
212
+ """
213
+ Every 2 minutes, this function uses the LLM to generate a random creative image prompt,
214
+ generates an image from it, and sends it as a WhatsApp status update.
215
+ """
216
+ while True:
217
+ try:
218
+ # Generate a random image prompt via LLM
219
+ random_prompt = generate_llm("Generate a creative and random image prompt for a WhatsApp status update.")
220
+ logging.info("Random status prompt: %s", random_prompt)
221
+ # Generate image from the prompt; using "status" as a dummy message/chat id.
222
+ img, path, ret_prompt, url = generate_image(random_prompt, "status", "status", image_dir)
223
+ if img and os.path.exists(path):
224
+ caption = f"Status: {random_prompt}"
225
+ send_status_image(path, caption)
226
+ # Optionally remove the image file after sending
227
+ os.remove(path)
228
+ else:
229
+ logging.error("Image generation for status failed.")
230
+ except Exception as e:
231
+ logging.error("Error in whatsapp_status_updater: %s", e)
232
+ # Sleep for 2 minutes
233
+ time.sleep(120)
234
+
235
+ # Start the WhatsApp status updater thread
236
+ threading.Thread(target=whatsapp_status_updater, daemon=True).start()
237
+
238
  # --- Startup Message ---
239
  def send_startup_message():
240
  if BOT_STATUS_CHAT:
 
276
  data = await request.json()
277
  chat_id = data["senderData"]["chatId"]
278
  print(f"New message from chat ID: {chat_id}")
279
+ except:
280
  return JSONResponse({"error": "Invalid JSON"}, status_code=400)
281
  if data.get("typeWebhook") != "incomingMessageReceived":
282
  return {"success": True}
 
333
  try:
334
  joke = requests.get("https://official-joke-api.appspot.com/random_joke", timeout=5).json()
335
  send_message(mid, chat, f"{joke['setup']}\n\n{joke['punchline']}")
336
+ except:
337
  send_message(mid, chat, generate_llm("Tell me a short, funny joke."))
338
  return {"success": True}
339
 
 
342
  try:
343
  w = requests.get(f"http://sl.wttr.in/{loc}?format=4", timeout=5).text
344
  send_message(mid, chat, w)
345
+ except:
346
  send_message(mid, chat, "Could not fetch weather.")
347
  return {"success": True}
348