baha-99 commited on
Commit
dcf0e08
·
1 Parent(s): 78f8dbf

feat: no timeout limit and more accurate info for end users

Browse files
Files changed (1) hide show
  1. bot_telegram.py +109 -103
bot_telegram.py CHANGED
@@ -180,37 +180,27 @@ class TelegramBot:
180
  self.active_requests[message_id]['end_time'] = time.time()
181
 
182
  def _make_api_request(self, user_message):
183
- """Make the actual API request in a separate thread"""
184
- hf_authorization = "Bearer " + HF_TOKEN
185
- headers = {
186
- "Authorization": hf_authorization,
187
- "accept": "application/json"
188
- }
189
-
190
- json_payload = {"question": user_message}
191
- form_payload = {"question": user_message}
192
-
193
  try:
 
 
 
 
 
 
194
  response = requests.post(
195
- self.ai_url,
196
- headers={**headers, "Content-Type": "application/json"},
197
- json=json_payload
198
  )
199
 
200
- if response.status_code == 422:
201
- response = requests.post(
202
- self.ai_url,
203
- headers={**headers, "Content-Type": "application/x-www-form-urlencoded"},
204
- data=form_payload
205
- )
206
-
207
  if response.status_code == 200:
208
- return response.json().get("answer", "I didn't understand that.")
209
  else:
210
- return f"Error: {response.status_code}"
211
 
212
  except Exception as e:
213
- return f"Connection error: {e}"
214
 
215
  async def handle_excel(self, update: Update, context: CallbackContext):
216
  """Handle Excel files concurrently"""
@@ -220,69 +210,123 @@ class TelegramBot:
220
  asyncio.create_task(self._process_excel_file(update, context, message_id))
221
 
222
  async def _process_excel_file(self, update, context, message_id):
223
- """Process Excel file asynchronously"""
224
  try:
225
  document = update.message.document
226
 
227
  # Send initial processing message
228
  processing_msg = await update.message.reply_text(
229
- f"📊 Processing Excel file...\n"
230
  f"File: {document.file_name}\n"
231
- f"Request ID: #{message_id}"
 
232
  )
233
 
234
- # Track this Excel file
235
  self.active_excel_files[message_id] = {
236
  'filename': document.file_name,
237
- 'status': 'downloading',
238
  'start_time': time.time()
239
  }
240
 
241
- # Download file
242
- file = await context.bot.get_file(document.file_id)
243
- file_bytes = await file.download_as_bytearray()
 
244
 
245
- # Update status to processing
246
- self.active_excel_files[message_id]['status'] = 'processing'
247
- await processing_msg.edit_text(
248
- f"⚙️ Processing Excel file...\n"
249
- f"File: {document.file_name}\n"
250
- f"Request ID: #{message_id}"
251
- )
252
-
253
- # Process in thread pool
254
- result = await asyncio.get_event_loop().run_in_executor(
255
- self.excel_executor,
256
- self._process_excel_sync,
257
- file_bytes,
258
- document.file_name
259
- )
260
-
261
- if result is None:
262
- raise Exception("Failed to process Excel file")
263
 
264
- # Send processed file
265
- await context.bot.send_document(
266
- chat_id=update.effective_chat.id,
267
- document=io.BytesIO(result),
268
- filename=f'processed_{document.file_name}',
269
- caption=f"✅ Excel processing completed!\nRequest ID: #{message_id}"
270
- )
271
- await processing_msg.delete()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
 
273
- except Exception as e:
274
- logging.error(f"Error handling Excel file: {e}")
275
- await update.message.reply_text(
276
- f"❌ Error processing Excel file\n"
277
- f"File: {document.file_name}\n"
278
- f"Request ID: #{message_id}\n"
279
- f"Error: {str(e)}"
280
- )
281
  finally:
282
  if message_id in self.active_excel_files:
283
  self.active_excel_files[message_id]['status'] = 'completed'
284
  self.active_excel_files[message_id]['end_time'] = time.time()
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  async def status_command(self, update: Update, context: CallbackContext):
287
  """Show status of all active processes"""
288
  status_message = "Current Status:\n\n"
@@ -342,43 +386,5 @@ class TelegramBot:
342
  await self.app.stop()
343
  await self.app.shutdown()
344
 
345
- def _process_excel_sync(self, file_bytes, filename):
346
- """Synchronous function to process Excel file"""
347
- try:
348
- headers = {
349
- "Authorization": f"Bearer {HF_TOKEN}",
350
- "accept": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
351
- }
352
-
353
- # Create files payload
354
- files = {
355
- 'file': (
356
- filename,
357
- file_bytes,
358
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
359
- )
360
- }
361
-
362
- # Make the request
363
- response = requests.post(
364
- self.excel_url,
365
- headers=headers,
366
- files=files,
367
- timeout=60 # 60 second timeout for Excel processing
368
- )
369
-
370
- if response.status_code == 200:
371
- return response.content
372
- else:
373
- logging.error(f"Excel API Error: {response.status_code} - {response.text}")
374
- return None
375
-
376
- except requests.exceptions.Timeout:
377
- logging.error("Excel processing timeout")
378
- return None
379
- except Exception as e:
380
- logging.error(f"Excel processing error: {e}")
381
- return None
382
-
383
  def init_bot():
384
  return TelegramBot(bot_token=BOT_TOKEN,base_url=BASE_URL)
 
180
  self.active_requests[message_id]['end_time'] = time.time()
181
 
182
  def _make_api_request(self, user_message):
183
+ """Make API request without timeout"""
 
 
 
 
 
 
 
 
 
184
  try:
185
+ headers = {
186
+ "Authorization": f"Bearer {HF_TOKEN}",
187
+ "accept": "application/json"
188
+ }
189
+
190
+ # No timeout specified
191
  response = requests.post(
192
+ self.ai_url,
193
+ headers=headers,
194
+ json={"question": user_message}
195
  )
196
 
 
 
 
 
 
 
 
197
  if response.status_code == 200:
198
+ return response.json().get("answer", "No answer received")
199
  else:
200
+ return f"API Error: {response.status_code}"
201
 
202
  except Exception as e:
203
+ return f"Error: {str(e)}"
204
 
205
  async def handle_excel(self, update: Update, context: CallbackContext):
206
  """Handle Excel files concurrently"""
 
210
  asyncio.create_task(self._process_excel_file(update, context, message_id))
211
 
212
  async def _process_excel_file(self, update, context, message_id):
213
+ """Process Excel file with progress updates but no timeout"""
214
  try:
215
  document = update.message.document
216
 
217
  # Send initial processing message
218
  processing_msg = await update.message.reply_text(
219
+ f"📊 Starting Excel processing...\n"
220
  f"File: {document.file_name}\n"
221
+ f"Request ID: #{message_id}\n"
222
+ f"Processing time may vary depending on file size and complexity. type /status to check the status of the request."
223
  )
224
 
 
225
  self.active_excel_files[message_id] = {
226
  'filename': document.file_name,
227
+ 'status': 'processing',
228
  'start_time': time.time()
229
  }
230
 
231
+ # Process in thread pool without timeout
232
+ try:
233
+ # Start a background task to update progress message
234
+ asyncio.create_task(self._update_progress(processing_msg, message_id, document.file_name))
235
 
236
+ result = await asyncio.get_event_loop().run_in_executor(
237
+ self.excel_executor,
238
+ self._process_excel_sync,
239
+ file_bytes,
240
+ document.file_name
241
+ )
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
+ if result is None:
244
+ await processing_msg.edit_text(
245
+ f"❌ Failed to process file\n"
246
+ f"File: {document.file_name}\n"
247
+ f"Please check the file format and try again."
248
+ )
249
+ return
250
+
251
+ # Send processed file
252
+ await context.bot.send_document(
253
+ chat_id=update.effective_chat.id,
254
+ document=io.BytesIO(result),
255
+ filename=f'processed_{document.file_name}',
256
+ caption=f"✅ Excel processing completed!\nRequest ID: #{message_id}"
257
+ )
258
+ await processing_msg.delete()
259
+
260
+ except Exception as e:
261
+ logging.error(f"Error processing file: {e}")
262
+ await processing_msg.edit_text(
263
+ f"❌ Error processing file\n"
264
+ f"File: {document.file_name}\n"
265
+ f"Error: {str(e)}"
266
+ )
267
 
 
 
 
 
 
 
 
 
268
  finally:
269
  if message_id in self.active_excel_files:
270
  self.active_excel_files[message_id]['status'] = 'completed'
271
  self.active_excel_files[message_id]['end_time'] = time.time()
272
 
273
+ async def _process_excel_sync(self, file_bytes, filename):
274
+ """Synchronous function to process Excel file without timeout"""
275
+ try:
276
+ headers = {
277
+ "Authorization": f"Bearer {HF_TOKEN}",
278
+ "accept": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
279
+ }
280
+
281
+ files = {
282
+ 'file': (
283
+ filename,
284
+ file_bytes,
285
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
286
+ )
287
+ }
288
+
289
+ # No timeout specified - will wait indefinitely
290
+ response = requests.post(
291
+ self.excel_url,
292
+ headers=headers,
293
+ files=files
294
+ )
295
+
296
+ if response.status_code == 200:
297
+ return response.content
298
+ else:
299
+ error_msg = f"API Error: {response.status_code}"
300
+ if response.text:
301
+ error_msg += f" - {response.text}"
302
+ logging.error(error_msg)
303
+ return None
304
+
305
+ except Exception as e:
306
+ logging.error(f"Excel processing error: {e}")
307
+ return None
308
+
309
+ async def _update_progress(self, message, message_id, filename):
310
+ """Update progress message periodically"""
311
+ try:
312
+ while message_id in self.active_excel_files:
313
+ elapsed_time = time.time() - self.active_excel_files[message_id]['start_time']
314
+ hours = int(elapsed_time // 3600)
315
+ minutes = int((elapsed_time % 3600) // 60)
316
+
317
+ await message.edit_text(
318
+ f"⚙️ Processing Excel file...\n"
319
+ f"File: {filename}\n"
320
+ f"Request ID: #{message_id}\n"
321
+ f"Time elapsed: {hours}h {minutes}m\n"
322
+ f"Status: {self.active_excel_files[message_id]['status']}"
323
+ )
324
+
325
+ # Update every 5 minutes
326
+ await asyncio.sleep(300)
327
+ except Exception as e:
328
+ logging.error(f"Error updating progress: {e}")
329
+
330
  async def status_command(self, update: Update, context: CallbackContext):
331
  """Show status of all active processes"""
332
  status_message = "Current Status:\n\n"
 
386
  await self.app.stop()
387
  await self.app.shutdown()
388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  def init_bot():
390
  return TelegramBot(bot_token=BOT_TOKEN,base_url=BASE_URL)