understanding commited on
Commit
7cca1d4
Β·
verified Β·
1 Parent(s): 55209e7

Update bot.py

Browse files
Files changed (1) hide show
  1. bot.py +86 -54
bot.py CHANGED
@@ -7,7 +7,7 @@ import re
7
  import uuid
8
  from typing import Dict
9
 
10
- from aiogram import Bot, Dispatcher, F
11
  from aiogram.filters import CommandStart
12
  from aiogram.types import Message, FSInputFile
13
  from aiogram.enums import ParseMode
@@ -63,24 +63,29 @@ async def link_processor_worker(worker_id: int):
63
  if not short_id:
64
  raise ValueError("Invalid Terabox link format.")
65
 
66
- download_url, raw_filename, error = await terabox.get_final_url_and_filename(original_link)
67
- if error:
68
- raise ValueError(error)
 
 
 
 
 
69
 
70
- local_filepath, _, download_error = await terabox.download_terabox_file(
71
- bot,
72
- batch_info["source_chat_id"],
73
- batch_info["status_message"].message_id,
74
- download_url,
75
- raw_filename
76
- )
77
- if download_error:
78
- raise ValueError(download_error)
79
 
80
- file_info = {
81
- 'path': local_filepath,
82
- 'name': raw_filename
83
- }
 
 
 
84
 
85
  except Exception as e:
86
  error_msg = str(e)
@@ -93,24 +98,48 @@ async def link_processor_worker(worker_id: int):
93
  batch_info["failed_links"].append({"link": original_link, "error": error_msg})
94
 
95
  processed, total = batch_info['processed_links'], batch_info['total_links']
 
96
  try:
97
- await bot.edit_message_text(
98
- chat_id=batch_info["source_chat_id"],
99
- message_id=batch_info["status_message"].message_id,
100
- text=f"βš™οΈ Batch `{batch_id[:6]}` in progress... Processed {processed}/{total} links."
101
  )
102
  except TelegramBadRequest:
103
  pass
104
 
 
 
105
  if processed == total:
106
  logger.info(f"Batch {batch_id[:6]} complete. Triggering final processing.")
107
  await handle_batch_completion(batch_id)
108
 
109
  TASK_QUEUE.task_done()
110
 
111
- async def send_file(chat_id: int, file_info: dict, caption: str) -> Message:
112
- file_path = FSInputFile(file_info['path'], filename=file_info['name'])
113
- sent_message = await bot.send_document(chat_id, file_path, caption=caption)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  return sent_message
115
 
116
  async def handle_batch_completion(batch_id: str):
@@ -126,45 +155,48 @@ async def handle_batch_completion(batch_id: str):
126
  failed_links_text = "\n".join(
127
  [f"- {x['link']} β†’ {x['error']}" for x in batch['failed_links']]
128
  )
129
- await bot.edit_message_text(
130
- chat_id=batch["source_chat_id"],
131
- message_id=status_msg.message_id,
132
- text=f"❌ Batch `{batch_id[:6]}` failed. No files could be processed.\nDetails:\n{failed_links_text}"
133
  )
134
  return
135
 
136
- await bot.edit_message_text(
137
- chat_id=batch["source_chat_id"],
138
- message_id=status_msg.message_id,
139
- text=f"βœ… Batch `{batch_id[:6]}` downloaded. Preparing to send {len(successful_downloads)} files..."
140
  )
141
 
 
 
 
 
 
 
 
 
 
 
 
142
  for item in successful_downloads:
143
- caption = f"`{item.get('name')}`"
144
- await send_file(batch["source_chat_id"], item, caption)
145
 
146
- summary = f"βœ… Batch `{batch_id[:6]}` complete: {len(successful_downloads)} files sent."
147
  if batch["failed_links"]:
148
  summary += f"\n❌ {len(batch['failed_links'])} links failed."
149
 
150
- await bot.edit_message_text(
151
- chat_id=batch["source_chat_id"],
152
- message_id=status_msg.message_id,
153
- text=summary
154
- )
155
 
156
  except Exception as e:
157
  logger.error(f"Error during batch completion for {batch_id}: {e}", exc_info=True)
158
- await bot.edit_message_text(
159
- chat_id=batch["source_chat_id"],
160
- message_id=status_msg.message_id,
161
- text=f"A critical error occurred while sending files for batch `{batch_id[:6]}`."
162
  )
163
  finally:
164
  for item in successful_downloads:
165
- if os.path.exists(item['path']):
166
  os.remove(item['path'])
167
-
168
  del BATCH_JOBS[batch_id]
169
 
170
  # --- Handlers ---
@@ -172,11 +204,14 @@ async def handle_batch_completion(batch_id: str):
172
  async def start_handler(message: Message):
173
  text = (
174
  "πŸ‘‹ <b>Welcome to the Terabox Downloader Bot!</b>\n\n"
175
- "πŸ“₯ Send me any valid Terabox link and I will fetch the file and send it to you.\n\n"
176
- f"πŸ“’ Please make sure you are a member of: @{config.FORCE_SUB_CHANNEL_USERNAME}\n\n"
177
- "βœ… <i>Just send your link below ⬇️</i>"
 
 
 
178
  )
179
- await message.reply(text)
180
 
181
  @dp.message(F.text | F.caption)
182
  async def message_handler(message: Message):
@@ -199,10 +234,7 @@ async def message_handler(message: Message):
199
  return
200
 
201
  batch_id = str(uuid.uuid4())
202
- status_msg = await bot.send_message(
203
- chat_id=message.chat.id,
204
- text=f"βœ… Found {len(terabox_links)} links. Queued as batch `{batch_id[:6]}`."
205
- )
206
 
207
  BATCH_JOBS[batch_id] = {
208
  "total_links": len(terabox_links),
 
7
  import uuid
8
  from typing import Dict
9
 
10
+ from aiogram import Bot, Dispatcher, types, F
11
  from aiogram.filters import CommandStart
12
  from aiogram.types import Message, FSInputFile
13
  from aiogram.enums import ParseMode
 
63
  if not short_id:
64
  raise ValueError("Invalid Terabox link format.")
65
 
66
+ cached_file = await db_utils.get_cached_file(short_id)
67
+ if cached_file:
68
+ logger.info(f"Cache hit for {short_id}. Reusing file_id.")
69
+ file_info = {'cached': True, 'short_id': short_id, **cached_file}
70
+ else:
71
+ download_url, raw_filename, error = await terabox.get_final_url_and_filename(original_link)
72
+ if error:
73
+ raise ValueError(error)
74
 
75
+ local_filepath, download_error = await terabox.download_terabox_file(
76
+ download_url,
77
+ raw_filename
78
+ )
79
+ if download_error:
80
+ raise ValueError(download_error)
 
 
 
81
 
82
+ file_info = {
83
+ 'cached': False,
84
+ 'path': local_filepath,
85
+ 'name': raw_filename,
86
+ 'size': os.path.getsize(local_filepath),
87
+ 'short_id': short_id,
88
+ }
89
 
90
  except Exception as e:
91
  error_msg = str(e)
 
98
  batch_info["failed_links"].append({"link": original_link, "error": error_msg})
99
 
100
  processed, total = batch_info['processed_links'], batch_info['total_links']
101
+
102
  try:
103
+ await batch_info["status_message"].edit_text(
104
+ f"βš™οΈ Batch <code>{batch_id[:6]}</code> in progress...\nProcessed {processed}/{total} links.",
105
+ disable_web_page_preview=True
 
106
  )
107
  except TelegramBadRequest:
108
  pass
109
 
110
+ await asyncio.sleep(0.3) # prevent rate limit
111
+
112
  if processed == total:
113
  logger.info(f"Batch {batch_id[:6]} complete. Triggering final processing.")
114
  await handle_batch_completion(batch_id)
115
 
116
  TASK_QUEUE.task_done()
117
 
118
+ async def send_and_cache_file(chat_id: int, file_info: dict, caption: str) -> Message:
119
+ file_path_or_id = file_info.get('file_id') or FSInputFile(file_info['path'], filename=file_info['name'])
120
+ media_type = file_info.get('type')
121
+ filename = file_info.get('name') or file_info.get('filename')
122
+
123
+ video_exts = ('.mp4', '.mkv', '.mov', '.avi', '.webm')
124
+ audio_exts = ('.mp3', '.flac', '.ogg', '.wav')
125
+
126
+ sent_message = None
127
+ if media_type == 'video' or filename.lower().endswith(video_exts):
128
+ sent_message = await bot.send_video(chat_id, file_path_or_id, caption=caption, supports_streaming=True)
129
+ media_type = 'video'
130
+ elif media_type == 'audio' or filename.lower().endswith(audio_exts):
131
+ sent_message = await bot.send_audio(chat_id, file_path_or_id, caption=caption)
132
+ media_type = 'audio'
133
+ else:
134
+ sent_message = await bot.send_document(chat_id, file_path_or_id, caption=caption)
135
+ media_type = 'document'
136
+
137
+ if not file_info.get('cached') and sent_message:
138
+ file_id_to_cache = getattr(sent_message, media_type).file_id
139
+ await db_utils.add_to_cache(
140
+ file_info['short_id'], file_id_to_cache, filename, media_type, file_info['size']
141
+ )
142
+
143
  return sent_message
144
 
145
  async def handle_batch_completion(batch_id: str):
 
155
  failed_links_text = "\n".join(
156
  [f"- {x['link']} β†’ {x['error']}" for x in batch['failed_links']]
157
  )
158
+ await status_msg.edit_text(
159
+ f"❌ Batch <code>{batch_id[:6]}</code> failed. No files could be processed.\nDetails:\n{failed_links_text}",
160
+ disable_web_page_preview=True
 
161
  )
162
  return
163
 
164
+ await status_msg.edit_text(
165
+ f"βœ… Batch <code>{batch_id[:6]}</code> downloaded. Preparing to send {len(successful_downloads)} files...",
166
+ disable_web_page_preview=True
 
167
  )
168
 
169
+ if config.FORWARD_CHANNEL_ID:
170
+ await bot.forward_message(
171
+ config.FORWARD_CHANNEL_ID,
172
+ batch["source_chat_id"],
173
+ batch["source_message_id"]
174
+ )
175
+ for item in successful_downloads:
176
+ caption = f"🎬 <code>{item.get('name') or item.get('filename')}</code>"
177
+ await send_and_cache_file(config.FORWARD_CHANNEL_ID, item, caption)
178
+ await asyncio.sleep(1)
179
+
180
  for item in successful_downloads:
181
+ caption = f"🎬 <code>{item.get('name') or item.get('filename')}</code>"
182
+ await send_and_cache_file(batch["source_chat_id"], item, caption)
183
 
184
+ summary = f"βœ… Batch <code>{batch_id[:6]}</code> complete: {len(successful_downloads)} files sent."
185
  if batch["failed_links"]:
186
  summary += f"\n❌ {len(batch['failed_links'])} links failed."
187
 
188
+ await status_msg.edit_text(summary, disable_web_page_preview=True)
 
 
 
 
189
 
190
  except Exception as e:
191
  logger.error(f"Error during batch completion for {batch_id}: {e}", exc_info=True)
192
+ await status_msg.edit_text(
193
+ f"❌ A critical error occurred while sending files for batch <code>{batch_id[:6]}</code>.",
194
+ disable_web_page_preview=True
 
195
  )
196
  finally:
197
  for item in successful_downloads:
198
+ if not item.get('cached') and os.path.exists(item['path']):
199
  os.remove(item['path'])
 
200
  del BATCH_JOBS[batch_id]
201
 
202
  # --- Handlers ---
 
204
  async def start_handler(message: Message):
205
  text = (
206
  "πŸ‘‹ <b>Welcome to the Terabox Downloader Bot!</b>\n\n"
207
+ "πŸ“₯ Send me any valid <b>Terabox</b> link(s), and I will fetch and send the files to you.\n\n"
208
+ "βœ… Multi-link batch supported!\n"
209
+ "πŸ’Ύ Cache enabled β†’ faster for repeat links.\n"
210
+ "πŸ“’ Original message will be forwarded to: "
211
+ f"<b>@{config.FORCE_SUB_CHANNEL_USERNAME}</b> (if configured).\n\n"
212
+ "πŸš€ <i>Just send your link(s) below ⬇️</i>"
213
  )
214
+ await message.answer(text, disable_web_page_preview=True)
215
 
216
  @dp.message(F.text | F.caption)
217
  async def message_handler(message: Message):
 
234
  return
235
 
236
  batch_id = str(uuid.uuid4())
237
+ status_msg = await message.answer(f"βœ… Found {len(terabox_links)} link(s). Queued as batch <code>{batch_id[:6]}</code>.", disable_web_page_preview=True)
 
 
 
238
 
239
  BATCH_JOBS[batch_id] = {
240
  "total_links": len(terabox_links),