Chandima Prabhath commited on
Commit
1fbbc17
·
1 Parent(s): a9740d0

Refactor BotConfig validation to include BOT_JID; improve help text formatting and clarity in command descriptions.

Browse files
Files changed (1) hide show
  1. app.py +60 -46
app.py CHANGED
@@ -16,24 +16,28 @@ from polLLM import generate_llm
16
  # --- Configuration and Client Classes ---
17
 
18
  class BotConfig:
19
- GREEN_API_URL = os.getenv("GREEN_API_URL")
20
- GREEN_API_MEDIA_URL = os.getenv("GREEN_API_MEDIA_URL", "https://api.green-api.com")
21
- GREEN_API_TOKEN = os.getenv("GREEN_API_TOKEN")
22
- GREEN_API_ID_INSTANCE = os.getenv("GREEN_API_ID_INSTANCE")
23
- WEBHOOK_AUTH_TOKEN = os.getenv("WEBHOOK_AUTH_TOKEN")
24
- BOT_GROUP_CHAT = "[email protected]"
25
- IMAGE_DIR = "/tmp/images"
26
- AUDIO_DIR = "/tmp/audio"
27
- DEFAULT_IMAGE_COUNT = 4
 
28
 
29
  @classmethod
30
  def validate(cls):
31
- missing = [name for name in (
32
- "GREEN_API_URL",
33
- "GREEN_API_TOKEN",
34
- "GREEN_API_ID_INSTANCE",
35
- "WEBHOOK_AUTH_TOKEN",
36
- ) if not getattr(cls, name)]
 
 
 
37
  if missing:
38
  raise ValueError(f"Environment variables not set: {', '.join(missing)}")
39
 
@@ -147,14 +151,10 @@ def handle_image_generation(task):
147
  prompt = task["prompt"]
148
  count = task.get("num_images", BotConfig.DEFAULT_IMAGE_COUNT)
149
 
150
- # simple loop: one generate_image call per image
151
  for i in range(1, count + 1):
152
  try:
153
  img, path, ret_prompt, url = generate_image(
154
- prompt,
155
- message_id,
156
- message_id,
157
- BotConfig.IMAGE_DIR
158
  )
159
  if not img:
160
  raise RuntimeError("generate_image returned no image")
@@ -179,23 +179,22 @@ send_startup_message()
179
  # --- FastAPI App & Webhook ---
180
 
181
  app = FastAPI()
 
182
  help_text = (
183
  "🤖 *Hi there, I'm Eve!* Here are the commands you can use:\n\n"
184
- "• */help* – _Show this help message._\n"
185
- "• */summarize <text>* – _Get a quick summary._\n"
186
- "• */translate <language>|<text>* – _Translate text._\n"
187
- "• */joke* – _Get a joke._\n"
188
- "• */weather <location>* – _Short, creative weather report (°C)._ \n"
189
- "• */weatherpoem <location>* – _Poetic weather summary._\n"
190
- "• */inspire* – _Get an inspirational quote._\n"
191
- "• */trivia* – _Start trivia._\n"
192
- "• */answer* _Answer trivia._\n"
193
- "• */meme <text>* – _Generate a meme._\n"
194
- "• */poll Q|A|B…* _Create a poll._\n"
195
- " */results* _Show poll results._\n"
196
- " */endpoll* _End the poll._\n"
197
- "• */gen <prompt>|<count>* – _Generate images (default 4)._ \n\n"
198
- "Any other text → I'll send you a voice reply!"
199
  )
200
 
201
  @app.post("/whatsapp")
@@ -207,34 +206,49 @@ async def whatsapp_webhook(request: Request):
207
  if request.headers.get("Authorization") != f"Bearer {BotConfig.WEBHOOK_AUTH_TOKEN}":
208
  raise HTTPException(403, "Unauthorized")
209
 
210
- data = await request.json()
211
  chat_id = data.get("senderData", {}).get("chatId")
212
  if chat_id != BotConfig.BOT_GROUP_CHAT or data.get("typeWebhook") != "incomingMessageReceived":
213
  return {"success": True}
214
 
215
- md = data.get("messageData", {})
216
- mid = data["idMessage"]
217
-
218
- # Extract text + context
219
  text_data = md.get("textMessageData") or md.get("extendedTextMessageData")
220
  if not text_data:
221
  return {"success": True}
 
222
  body = text_data.get("textMessage", text_data.get("text", "")).strip()
223
  ctx = text_data.get("contextInfo", {})
224
 
225
- # Skip replies/quotes
226
- if ctx.get("quotedMessageId") or ctx.get("quotedMessage"):
227
- logging.debug("Skipping quoted/reply message")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  return {"success": True}
229
 
230
- # Skip @-mentions
231
  if ctx.get("mentionedJidList"):
232
- logging.debug("Skipping mention")
233
  return {"success": True}
234
 
235
  low = body.lower()
236
 
237
- # --- COMMANDS ---
238
  if low == "/help":
239
  client.send_message(mid, chat_id, help_text)
240
  return {"success": True}
 
16
  # --- Configuration and Client Classes ---
17
 
18
  class BotConfig:
19
+ GREEN_API_URL = os.getenv("GREEN_API_URL")
20
+ GREEN_API_MEDIA_URL = os.getenv("GREEN_API_MEDIA_URL", "https://api.green-api.com")
21
+ GREEN_API_TOKEN = os.getenv("GREEN_API_TOKEN")
22
+ GREEN_API_ID_INSTANCE = os.getenv("GREEN_API_ID_INSTANCE")
23
+ WEBHOOK_AUTH_TOKEN = os.getenv("WEBHOOK_AUTH_TOKEN")
24
+ BOT_GROUP_CHAT = "[email protected]"
25
+ BOT_JID = os.getenv("BOT_JID") # e.g. "[email protected]"
26
+ IMAGE_DIR = "/tmp/images"
27
+ AUDIO_DIR = "/tmp/audio"
28
+ DEFAULT_IMAGE_COUNT = 4
29
 
30
  @classmethod
31
  def validate(cls):
32
+ missing = [
33
+ name for name in (
34
+ "GREEN_API_URL",
35
+ "GREEN_API_TOKEN",
36
+ "GREEN_API_ID_INSTANCE",
37
+ "WEBHOOK_AUTH_TOKEN",
38
+ "BOT_JID",
39
+ ) if not getattr(cls, name)
40
+ ]
41
  if missing:
42
  raise ValueError(f"Environment variables not set: {', '.join(missing)}")
43
 
 
151
  prompt = task["prompt"]
152
  count = task.get("num_images", BotConfig.DEFAULT_IMAGE_COUNT)
153
 
 
154
  for i in range(1, count + 1):
155
  try:
156
  img, path, ret_prompt, url = generate_image(
157
+ prompt, message_id, message_id, BotConfig.IMAGE_DIR
 
 
 
158
  )
159
  if not img:
160
  raise RuntimeError("generate_image returned no image")
 
179
  # --- FastAPI App & Webhook ---
180
 
181
  app = FastAPI()
182
+
183
  help_text = (
184
  "🤖 *Hi there, I'm Eve!* Here are the commands you can use:\n\n"
185
+ "• */help* – list commands\n"
186
+ "• */gen <prompt>|<count>* – generate images (default 4)\n"
187
+ "• */summarize <text>*\n"
188
+ "• */translate <lang>|<text>*\n"
189
+ "• */joke*\n"
190
+ "• */weather <location>*\n"
191
+ "• */weatherpoem <location>*\n"
192
+ "• */inspire*\n"
193
+ "• */trivia* / *answer*\n"
194
+ "• */meme <text>*\n"
195
+ "• */poll <Q>|<opt1>|… / /results / /endpoll*\n\n"
196
+ "Reply to one of my messages → I'll LLM‑answer it.\n"
197
+ "Any other text voice reply."
 
 
198
  )
199
 
200
  @app.post("/whatsapp")
 
206
  if request.headers.get("Authorization") != f"Bearer {BotConfig.WEBHOOK_AUTH_TOKEN}":
207
  raise HTTPException(403, "Unauthorized")
208
 
209
+ data = await request.json()
210
  chat_id = data.get("senderData", {}).get("chatId")
211
  if chat_id != BotConfig.BOT_GROUP_CHAT or data.get("typeWebhook") != "incomingMessageReceived":
212
  return {"success": True}
213
 
214
+ md = data.get("messageData", {})
215
+ mid = data["idMessage"]
 
 
216
  text_data = md.get("textMessageData") or md.get("extendedTextMessageData")
217
  if not text_data:
218
  return {"success": True}
219
+
220
  body = text_data.get("textMessage", text_data.get("text", "")).strip()
221
  ctx = text_data.get("contextInfo", {})
222
 
223
+ # --- Quoted‑reply handling ---
224
+ if ctx.get("quotedMessageId"):
225
+ # only if the quoted message was sent by our bot
226
+ quoted_sender = ctx.get("participant") or ctx.get("quotedMessageSender")
227
+ if quoted_sender == BotConfig.BOT_JID:
228
+ # extract quoted text
229
+ qm = ctx.get("quotedMessage", {})
230
+ if "textMessageData" in qm:
231
+ quoted_text = qm["textMessageData"].get("textMessage", "")
232
+ else:
233
+ quoted_text = qm.get("extendedTextMessageData", {}).get("text", "")
234
+ # build and send LLM reply
235
+ prompt = (
236
+ f"You asked: {quoted_text}\n"
237
+ f"User replied: {body}\n"
238
+ "Provide a helpful, concise follow‑up."
239
+ )
240
+ reply = generate_llm(prompt)
241
+ client.send_message(mid, chat_id, reply)
242
+ # in either case, do not process further
243
  return {"success": True}
244
 
245
+ # --- Skip @‑mentions of others ---
246
  if ctx.get("mentionedJidList"):
 
247
  return {"success": True}
248
 
249
  low = body.lower()
250
 
251
+ # --- COMMANDS (unchanged) ---
252
  if low == "/help":
253
  client.send_message(mid, chat_id, help_text)
254
  return {"success": True}