fmab777 commited on
Commit
4629ea6
·
verified ·
1 Parent(s): aea0e1a

Add more debug logging and remove nest_asyncio

Browse files
Files changed (1) hide show
  1. main.py +32 -47
main.py CHANGED
@@ -1,4 +1,4 @@
1
- # main.py (Revised for Hugging Face - Added Application.initialize())
2
  import os
3
  import re
4
  import logging
@@ -13,7 +13,8 @@ from telegram.ext import (
13
  MessageHandler,
14
  filters,
15
  ContextTypes,
16
- CallbackQueryHandler
 
17
  )
18
  from telegram.constants import ParseMode # Import ParseMode explicitly
19
 
@@ -26,18 +27,17 @@ _apify_token_exists = bool(os.environ.get('APIFY_API_TOKEN'))
26
  if _apify_token_exists:
27
  from apify_client import ApifyClient
28
  else:
29
- ApifyClient = None # Define it as None if not used, to avoid errors later
30
 
31
- # Apply nest_asyncio early, can help prevent event loop conflicts
32
- import nest_asyncio
33
- nest_asyncio.apply()
34
 
35
  # --- Logging Setup ---
36
  logging.basicConfig(
37
  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
38
- level=logging.DEBUG # Keep DEBUG level for now
39
  )
40
- # Reduce noise from libraries
41
  logging.getLogger("httpx").setLevel(logging.WARNING)
42
  if ApifyClient: logging.getLogger("apify_client").setLevel(logging.WARNING)
43
  logging.getLogger("telegram.ext").setLevel(logging.DEBUG)
@@ -47,17 +47,14 @@ logging.getLogger('gunicorn.error').setLevel(logging.INFO)
47
  logger = logging.getLogger(__name__)
48
  logger.info("Logging configured (DEBUG level).")
49
 
50
- # --- Environment Variable Loading & Debugging ---
51
  logger.info("Attempting to load secrets from environment variables...")
52
-
53
  def get_secret(secret_name):
54
- """Reads secret and logs the attempt and result."""
55
  logger.debug(f"Attempting to read secret: {secret_name}")
56
  value = os.environ.get(secret_name)
57
- if value:
58
- logger.info(f"Secret '{secret_name}': Found (Value length: {len(value)})")
59
- else:
60
- logger.warning(f"Secret '{secret_name}': Not Found")
61
  return value
62
 
63
  TELEGRAM_TOKEN = get_secret('TELEGRAM_TOKEN')
@@ -65,11 +62,11 @@ OPENROUTER_API_KEY = get_secret('OPENROUTER_API_KEY')
65
  URLTOTEXT_API_KEY = get_secret('URLTOTEXT_API_KEY')
66
  SUPADATA_API_KEY = get_secret('SUPADATA_API_KEY')
67
  APIFY_API_TOKEN = get_secret('APIFY_API_TOKEN')
68
-
69
  logger.info("Secret loading attempt finished.")
70
 
71
  # --- Bot Logic Functions ---
72
  # [PASTE ALL YOUR BOT LOGIC FUNCTIONS HERE - FROM is_youtube_url to generate_summary]
 
73
  # Helper Functions
74
  def is_youtube_url(url):
75
  """Checks if the URL is a valid YouTube video or shorts URL."""
@@ -526,6 +523,7 @@ Here is the text to summarise:"""
526
  return "Sorry, an unexpected error occurred while generating the summary."
527
 
528
 
 
529
  # --- Telegram Bot Handlers (Command, Message, CallbackQuery) ---
530
 
531
  async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
@@ -591,7 +589,13 @@ async def handle_summary_type_callback(update: Update, context: ContextTypes.DEF
591
  """Handles button presses for summary type selection."""
592
  query = update.callback_query
593
  if not query: return
594
- await query.answer() # Acknowledge button press immediately
 
 
 
 
 
 
595
 
596
  summary_type = query.data
597
  user = update.effective_user or query.from_user # Get user info
@@ -640,9 +644,10 @@ async def handle_summary_type_callback(update: Update, context: ContextTypes.DEF
640
  try:
641
  # Edit the message to show processing status
642
  await query.edit_message_text(processing_message)
 
643
  except Exception as e:
644
  # If editing fails (e.g., message too old), send a new status message
645
- logger.warning(f"Could not edit original message: {e}, sending new status message.")
646
  try:
647
  message_to_delete_later = await context.bot.send_message(chat_id=user.id, text=processing_message)
648
  except Exception as send_err:
@@ -657,6 +662,7 @@ async def handle_summary_type_callback(update: Update, context: ContextTypes.DEF
657
 
658
  try:
659
  # Show "typing..." status in Telegram chat
 
660
  await context.bot.send_chat_action(chat_id=user.id, action='typing')
661
 
662
  # --- Content Fetching Logic ---
@@ -664,6 +670,7 @@ async def handle_summary_type_callback(update: Update, context: ContextTypes.DEF
664
  video_id = extract_youtube_id(url)
665
  if video_id:
666
  # Fetch YT transcript using the function with fallbacks
 
667
  content = await get_youtube_transcript(
668
  video_id,
669
  url, # Pass full URL for Apify
@@ -672,6 +679,7 @@ async def handle_summary_type_callback(update: Update, context: ContextTypes.DEF
672
  )
673
  # Set feedback message only if content fetching failed
674
  user_feedback_message = None if content else "Sorry, I couldn't get the transcript for that YouTube video using any available method (unavailable/private/no captions?)."
 
675
  else:
676
  user_feedback_message = "Sorry, I couldn't understand that YouTube URL format."
677
  else: # Website Logic (Requests/BS4 -> URLToText API)
@@ -712,6 +720,7 @@ async def handle_summary_type_callback(update: Update, context: ContextTypes.DEF
712
  logger.warning(f"Summary generation failed or returned error: {summary}")
713
  else:
714
  # Send the successful summary
 
715
  await context.bot.send_message(
716
  chat_id=user.id,
717
  text=summary,
@@ -727,6 +736,7 @@ async def handle_summary_type_callback(update: Update, context: ContextTypes.DEF
727
 
728
  # --- Send Feedback if any step failed ---
729
  if user_feedback_message and not success:
 
730
  await context.bot.send_message(chat_id=user.id, text=user_feedback_message)
731
 
732
  except Exception as e:
@@ -741,12 +751,14 @@ async def handle_summary_type_callback(update: Update, context: ContextTypes.DEF
741
  finally:
742
  # --- Cleanup ---
743
  # Delete the "Processing..." status message or the original message with buttons
 
744
  try:
745
  if message_to_delete_later: # If we sent a separate status message
746
  await context.bot.delete_message(chat_id=user.id, message_id=message_to_delete_later.message_id)
 
747
  elif query: # Otherwise, delete the original message with the buttons
748
- # We might have already edited it, but deleting ensures cleanup
749
  await query.delete_message()
 
750
  except Exception as del_e:
751
  # Log if deletion fails, but don't let it stop anything
752
  logger.warning(f"Could not delete status/button message: {del_e}")
@@ -756,33 +768,8 @@ async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> N
756
  """Log Errors caused by Updates."""
757
  # Log the error and traceback
758
  logger.error(f"Exception while handling an update: {context.error}", exc_info=context.error)
 
759
 
760
- # Optionally send a notification to developer chat ID (replace with your actual ID)
761
- # developer_chat_id = 12345678
762
- # try:
763
- # # Extract user/chat info if available
764
- # chat_info = "N/A"
765
- # user_info = "N/A"
766
- # update_details = "N/A"
767
- # if isinstance(update, Update) and update.effective_chat:
768
- # chat_info = f"Chat: {update.effective_chat.id} ({update.effective_chat.type})"
769
- # if isinstance(update, Update) and update.effective_user:
770
- # user_info = f"User: {update.effective_user.id} (@{update.effective_user.username})"
771
- # if update:
772
- # update_details = f"Update Type: {update.__class__.__name__}"
773
-
774
- # tb_list = traceback.format_exception(None, context.error, context.error.__traceback__)
775
- # tb_string = "".join(tb_list)
776
- # # Keep message reasonably short
777
- # error_message = (
778
- # f"🚨 Bot Error 🚨\n"
779
- # f"{chat_info}\n{user_info}\n{update_details}\n"
780
- # f"Error: {context.error}\n\n"
781
- # f"Traceback (last part):\n```\n{tb_string[-1000:]}\n```" # Limit traceback length
782
- # )
783
- # await context.bot.send_message(chat_id=developer_chat_id, text=error_message[:4096]) # Limit msg len
784
- # except Exception as e:
785
- # logger.error(f"Failed to send error notification to developer: {e}")
786
 
787
  # --- Bot Application Setup Function ---
788
  async def setup_bot():
@@ -812,8 +799,6 @@ async def setup_bot():
812
 
813
  # --- Run Setup and Store Application Instance ---
814
  logger.info("Running bot setup...")
815
- # Run the async setup function and store the application instance globally
816
- # This runs once when the script/module is first loaded by Gunicorn worker
817
  ptb_app = asyncio.run(setup_bot())
818
  logger.info(f"Bot setup finished. Application instance: {'OK' if ptb_app else 'Failed'}")
819
 
 
1
+ # main.py (Revised for Hugging Face - Fix Event Loop Issue)
2
  import os
3
  import re
4
  import logging
 
13
  MessageHandler,
14
  filters,
15
  ContextTypes,
16
+ CallbackQueryHandler,
17
+ ApplicationBuilder # Import ApplicationBuilder
18
  )
19
  from telegram.constants import ParseMode # Import ParseMode explicitly
20
 
 
27
  if _apify_token_exists:
28
  from apify_client import ApifyClient
29
  else:
30
+ ApifyClient = None
31
 
32
+ # NO nest_asyncio needed here usually when using native async framework integration
33
+ # import nest_asyncio
34
+ # nest_asyncio.apply()
35
 
36
  # --- Logging Setup ---
37
  logging.basicConfig(
38
  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
39
+ level=logging.DEBUG # Keep DEBUG
40
  )
 
41
  logging.getLogger("httpx").setLevel(logging.WARNING)
42
  if ApifyClient: logging.getLogger("apify_client").setLevel(logging.WARNING)
43
  logging.getLogger("telegram.ext").setLevel(logging.DEBUG)
 
47
  logger = logging.getLogger(__name__)
48
  logger.info("Logging configured (DEBUG level).")
49
 
50
+ # --- Environment Variable Loading ---
51
  logger.info("Attempting to load secrets from environment variables...")
52
+ # (Keep the get_secret function and secret loading as before)
53
  def get_secret(secret_name):
 
54
  logger.debug(f"Attempting to read secret: {secret_name}")
55
  value = os.environ.get(secret_name)
56
+ if value: logger.info(f"Secret '{secret_name}': Found (Value length: {len(value)})")
57
+ else: logger.warning(f"Secret '{secret_name}': Not Found")
 
 
58
  return value
59
 
60
  TELEGRAM_TOKEN = get_secret('TELEGRAM_TOKEN')
 
62
  URLTOTEXT_API_KEY = get_secret('URLTOTEXT_API_KEY')
63
  SUPADATA_API_KEY = get_secret('SUPADATA_API_KEY')
64
  APIFY_API_TOKEN = get_secret('APIFY_API_TOKEN')
 
65
  logger.info("Secret loading attempt finished.")
66
 
67
  # --- Bot Logic Functions ---
68
  # [PASTE ALL YOUR BOT LOGIC FUNCTIONS HERE - FROM is_youtube_url to generate_summary]
69
+ # --- [ Ensure all functions from previous main.py are here ] ---
70
  # Helper Functions
71
  def is_youtube_url(url):
72
  """Checks if the URL is a valid YouTube video or shorts URL."""
 
523
  return "Sorry, an unexpected error occurred while generating the summary."
524
 
525
 
526
+
527
  # --- Telegram Bot Handlers (Command, Message, CallbackQuery) ---
528
 
529
  async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 
589
  """Handles button presses for summary type selection."""
590
  query = update.callback_query
591
  if not query: return
592
+ # --- Acknowledge callback query ---
593
+ try:
594
+ await query.answer() # Acknowledge button press immediately
595
+ logger.debug(f"Callback query {query.id} answered.")
596
+ except Exception as e:
597
+ logger.error(f"Failed to answer callback query {query.id}: {e}", exc_info=True)
598
+ # Proceed anyway, but logging the error is important
599
 
600
  summary_type = query.data
601
  user = update.effective_user or query.from_user # Get user info
 
644
  try:
645
  # Edit the message to show processing status
646
  await query.edit_message_text(processing_message)
647
+ logger.debug(f"Edited message for query {query.id} to show processing status.")
648
  except Exception as e:
649
  # If editing fails (e.g., message too old), send a new status message
650
+ logger.warning(f"Could not edit original message for query {query.id}: {e}. Sending new status message.")
651
  try:
652
  message_to_delete_later = await context.bot.send_message(chat_id=user.id, text=processing_message)
653
  except Exception as send_err:
 
662
 
663
  try:
664
  # Show "typing..." status in Telegram chat
665
+ logger.debug(f"Sending 'typing' action for chat {user.id}")
666
  await context.bot.send_chat_action(chat_id=user.id, action='typing')
667
 
668
  # --- Content Fetching Logic ---
 
670
  video_id = extract_youtube_id(url)
671
  if video_id:
672
  # Fetch YT transcript using the function with fallbacks
673
+ logger.info(f"Fetching YouTube transcript for video_id: {video_id}")
674
  content = await get_youtube_transcript(
675
  video_id,
676
  url, # Pass full URL for Apify
 
679
  )
680
  # Set feedback message only if content fetching failed
681
  user_feedback_message = None if content else "Sorry, I couldn't get the transcript for that YouTube video using any available method (unavailable/private/no captions?)."
682
+ logger.info(f"YouTube transcript fetch completed. Content found: {bool(content)}")
683
  else:
684
  user_feedback_message = "Sorry, I couldn't understand that YouTube URL format."
685
  else: # Website Logic (Requests/BS4 -> URLToText API)
 
720
  logger.warning(f"Summary generation failed or returned error: {summary}")
721
  else:
722
  # Send the successful summary
723
+ logger.info("Summary generated successfully. Sending response.")
724
  await context.bot.send_message(
725
  chat_id=user.id,
726
  text=summary,
 
736
 
737
  # --- Send Feedback if any step failed ---
738
  if user_feedback_message and not success:
739
+ logger.warning(f"Sending failure feedback to user: {user_feedback_message}")
740
  await context.bot.send_message(chat_id=user.id, text=user_feedback_message)
741
 
742
  except Exception as e:
 
751
  finally:
752
  # --- Cleanup ---
753
  # Delete the "Processing..." status message or the original message with buttons
754
+ logger.debug("Cleaning up status message...")
755
  try:
756
  if message_to_delete_later: # If we sent a separate status message
757
  await context.bot.delete_message(chat_id=user.id, message_id=message_to_delete_later.message_id)
758
+ logger.debug("Deleted separate status message.")
759
  elif query: # Otherwise, delete the original message with the buttons
 
760
  await query.delete_message()
761
+ logger.debug(f"Deleted original message for query {query.id}.")
762
  except Exception as del_e:
763
  # Log if deletion fails, but don't let it stop anything
764
  logger.warning(f"Could not delete status/button message: {del_e}")
 
768
  """Log Errors caused by Updates."""
769
  # Log the error and traceback
770
  logger.error(f"Exception while handling an update: {context.error}", exc_info=context.error)
771
+ # (Keep optional developer notification code as before if desired)
772
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
773
 
774
  # --- Bot Application Setup Function ---
775
  async def setup_bot():
 
799
 
800
  # --- Run Setup and Store Application Instance ---
801
  logger.info("Running bot setup...")
 
 
802
  ptb_app = asyncio.run(setup_bot())
803
  logger.info(f"Bot setup finished. Application instance: {'OK' if ptb_app else 'Failed'}")
804