understanding commited on
Commit
00c95d7
Β·
verified Β·
1 Parent(s): b0822c8

Update bot.py

Browse files
Files changed (1) hide show
  1. bot.py +55 -30
bot.py CHANGED
@@ -1,14 +1,13 @@
1
- # bot.py
2
-
3
  import asyncio
4
  import logging
5
  import os
6
  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
14
  from aiogram.exceptions import TelegramBadRequest
@@ -43,6 +42,7 @@ bot = Bot(
43
  dp = Dispatcher()
44
  TASK_QUEUE = asyncio.Queue()
45
  BATCH_JOBS: Dict[str, Dict] = {}
 
46
 
47
  # --- Worker Logic ---
48
  async def link_processor_worker(worker_id: int):
@@ -74,9 +74,6 @@ async def link_processor_worker(worker_id: int):
74
  raise ValueError(error)
75
 
76
  local_filepath, thumb_path, download_error = await terabox.download_terabox_file(
77
- bot,
78
- batch_info["source_chat_id"],
79
- batch_info["status_message"].message_id,
80
  download_url,
81
  raw_filename
82
  )
@@ -103,10 +100,12 @@ async def link_processor_worker(worker_id: int):
103
  batch_info["failed_links"].append({"link": original_link, "error": error_msg})
104
 
105
  processed, total = batch_info['processed_links'], batch_info['total_links']
 
 
106
  try:
107
  await batch_info["status_message"].edit_text(
108
- f"βš™οΈ Batch <code>{batch_id[:6]}</code> in progress...\n"
109
- f"Processed <b>{processed}</b>/<b>{total}</b> links."
110
  )
111
  except TelegramBadRequest:
112
  pass
@@ -117,7 +116,7 @@ async def link_processor_worker(worker_id: int):
117
 
118
  TASK_QUEUE.task_done()
119
 
120
- async def send_and_cache_file(chat_id: int, file_info: dict, caption: str) -> Message:
121
  file_path_or_id = file_info.get('file_id') or FSInputFile(file_info['path'], filename=file_info['name'])
122
  media_type = file_info.get('type')
123
  filename = file_info.get('name') or file_info.get('filename')
@@ -127,13 +126,13 @@ async def send_and_cache_file(chat_id: int, file_info: dict, caption: str) -> Me
127
 
128
  sent_message = None
129
  if media_type == 'video' or filename.lower().endswith(video_exts):
130
- sent_message = await bot.send_video(chat_id, file_path_or_id, caption=caption, supports_streaming=True)
131
  media_type = 'video'
132
  elif media_type == 'audio' or filename.lower().endswith(audio_exts):
133
- sent_message = await bot.send_audio(chat_id, file_path_or_id, caption=caption)
134
  media_type = 'audio'
135
  else:
136
- sent_message = await bot.send_document(chat_id, file_path_or_id, caption=caption)
137
  media_type = 'document'
138
 
139
  if not file_info.get('cached') and sent_message:
@@ -155,15 +154,15 @@ async def handle_batch_completion(batch_id: str):
155
  try:
156
  if not successful_downloads:
157
  failed_links_text = "\n".join(
158
- [f"- {x['link']} β†’ {x['error']}" for x in batch['failed_links']]
159
  )
160
  await status_msg.edit_text(
161
- f"❌ Batch <code>{batch_id[:6]}</code> failed.\nNo files could be processed.\n\n<b>Details:</b>\n{failed_links_text}"
162
  )
163
  return
164
 
165
  await status_msg.edit_text(
166
- f"βœ… Batch <code>{batch_id[:6]}</code> downloaded.\nPreparing to send <b>{len(successful_downloads)}</b> files..."
167
  )
168
 
169
  if config.FORWARD_CHANNEL_ID:
@@ -174,14 +173,14 @@ async def handle_batch_completion(batch_id: str):
174
  )
175
  for item in successful_downloads:
176
  caption = f"`{item.get('name') or item.get('filename')}`"
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"`{item.get('name') or item.get('filename')}`"
182
- await send_and_cache_file(batch["source_chat_id"], item, caption)
183
 
184
- summary = f"βœ… Batch <code>{batch_id[:6]}</code> complete: <b>{len(successful_downloads)}</b> files sent."
185
  if batch["failed_links"]:
186
  summary += f"\n❌ {len(batch['failed_links'])} links failed."
187
 
@@ -190,7 +189,7 @@ async def handle_batch_completion(batch_id: str):
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"❌ Critical error occurred while sending files for batch <code>{batch_id[:6]}</code>."
194
  )
195
  finally:
196
  for item in successful_downloads:
@@ -206,12 +205,35 @@ async def handle_batch_completion(batch_id: str):
206
  async def start_handler(message: Message):
207
  text = (
208
  "πŸ‘‹ <b>Welcome to the Terabox Downloader Bot!</b>\n\n"
209
- "πŸ“₯ Send me any valid Terabox link(s) and I will fetch the files and send them to you.\n\n"
210
- f"πŸ“’ Make sure you are a member of @{config.FORCE_SUB_CHANNEL_USERNAME}\n\n"
211
- "πŸš€ Supports multiple links per message (batch mode).\n"
212
- "πŸ’Ύ Auto-cache enabled.\n"
213
- "πŸ”„ Forwarding original message to channel enabled.\n\n"
214
- "βœ… <i>Just send your links below ⬇️</i>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  )
216
  await message.reply(text)
217
 
@@ -226,7 +248,7 @@ async def message_handler(message: Message):
226
  message.from_user.first_name
227
  )
228
 
229
- links = list(set(re.findall(r'https?://[^\s<>"\']+', message.text or message.caption or "")))
230
  terabox_links = [link for link in links if any(domain in link for domain in [
231
  "terabox.com", "teraboxapp.com", "terasharelink.com", "1024tera.com",
232
  "freeterabox.com", "4funbox.com", "box-links.com"
@@ -237,7 +259,8 @@ async def message_handler(message: Message):
237
 
238
  batch_id = str(uuid.uuid4())
239
  status_msg = await message.reply(
240
- f"βœ… <b>Found</b> {len(terabox_links)} links.\n<b>Queued</b> as batch <code>{batch_id[:6]}</code>."
 
241
  )
242
 
243
  BATCH_JOBS[batch_id] = {
@@ -249,7 +272,8 @@ async def message_handler(message: Message):
249
  "source_user_id": message.from_user.id,
250
  "source_message_id": message.message_id,
251
  "status_message": status_msg,
252
- "lock": asyncio.Lock()
 
253
  }
254
 
255
  for link in terabox_links:
@@ -266,4 +290,5 @@ def start_bot():
266
  dp.startup.register(on_startup)
267
  dp.message.register(message_handler)
268
  dp.message.register(start_handler, CommandStart())
269
- return dp, bot
 
 
 
 
1
  import asyncio
2
  import logging
3
  import os
4
  import re
5
  import uuid
6
+ import time
7
  from typing import Dict
8
 
9
+ from aiogram import Bot, Dispatcher, types, F
10
+ from aiogram.filters import CommandStart, Command
11
  from aiogram.types import Message, FSInputFile
12
  from aiogram.enums import ParseMode
13
  from aiogram.exceptions import TelegramBadRequest
 
42
  dp = Dispatcher()
43
  TASK_QUEUE = asyncio.Queue()
44
  BATCH_JOBS: Dict[str, Dict] = {}
45
+ BOT_START_TIME = time.time()
46
 
47
  # --- Worker Logic ---
48
  async def link_processor_worker(worker_id: int):
 
74
  raise ValueError(error)
75
 
76
  local_filepath, thumb_path, download_error = await terabox.download_terabox_file(
 
 
 
77
  download_url,
78
  raw_filename
79
  )
 
100
  batch_info["failed_links"].append({"link": original_link, "error": error_msg})
101
 
102
  processed, total = batch_info['processed_links'], batch_info['total_links']
103
+ eta_sec = ((time.time() - batch_info['start_time']) / processed) * (total - processed) if processed > 0 else 0
104
+
105
  try:
106
  await batch_info["status_message"].edit_text(
107
+ f"<b>πŸ”§ Batch `{batch_id[:6]}` in progress...</b>\n"
108
+ f"Processed: {processed}/{total} | ETA: {int(eta_sec)} sec"
109
  )
110
  except TelegramBadRequest:
111
  pass
 
116
 
117
  TASK_QUEUE.task_done()
118
 
119
+ async def send_and_cache_file(chat_id: int, file_info: dict, caption: str, reply_to: int) -> Message:
120
  file_path_or_id = file_info.get('file_id') or FSInputFile(file_info['path'], filename=file_info['name'])
121
  media_type = file_info.get('type')
122
  filename = file_info.get('name') or file_info.get('filename')
 
126
 
127
  sent_message = None
128
  if media_type == 'video' or filename.lower().endswith(video_exts):
129
+ sent_message = await bot.send_video(chat_id, file_path_or_id, caption=caption, supports_streaming=True, reply_to_message_id=reply_to)
130
  media_type = 'video'
131
  elif media_type == 'audio' or filename.lower().endswith(audio_exts):
132
+ sent_message = await bot.send_audio(chat_id, file_path_or_id, caption=caption, reply_to_message_id=reply_to)
133
  media_type = 'audio'
134
  else:
135
+ sent_message = await bot.send_document(chat_id, file_path_or_id, caption=caption, reply_to_message_id=reply_to)
136
  media_type = 'document'
137
 
138
  if not file_info.get('cached') and sent_message:
 
154
  try:
155
  if not successful_downloads:
156
  failed_links_text = "\n".join(
157
+ [f"- {x['link']} \u2192 {x['error']}" for x in batch['failed_links']]
158
  )
159
  await status_msg.edit_text(
160
+ f"<b>❌ Batch `{batch_id[:6]}` failed. No files could be processed.</b>\nDetails:\n{failed_links_text}"
161
  )
162
  return
163
 
164
  await status_msg.edit_text(
165
+ f"πŸ“₯ Batch `{batch_id[:6]}` downloaded. Preparing to send {len(successful_downloads)} files..."
166
  )
167
 
168
  if config.FORWARD_CHANNEL_ID:
 
173
  )
174
  for item in successful_downloads:
175
  caption = f"`{item.get('name') or item.get('filename')}`"
176
+ await send_and_cache_file(config.FORWARD_CHANNEL_ID, item, caption, reply_to=None)
177
  await asyncio.sleep(1)
178
 
179
  for item in successful_downloads:
180
  caption = f"`{item.get('name') or item.get('filename')}`"
181
+ await send_and_cache_file(batch["source_chat_id"], item, caption, reply_to=batch['source_message_id'])
182
 
183
+ summary = f"βœ… Batch `{batch_id[:6]}` complete: {len(successful_downloads)} files sent."
184
  if batch["failed_links"]:
185
  summary += f"\n❌ {len(batch['failed_links'])} links failed."
186
 
 
189
  except Exception as e:
190
  logger.error(f"Error during batch completion for {batch_id}: {e}", exc_info=True)
191
  await status_msg.edit_text(
192
+ f"A critical error occurred while sending files for batch `{batch_id[:6]}`."
193
  )
194
  finally:
195
  for item in successful_downloads:
 
205
  async def start_handler(message: Message):
206
  text = (
207
  "πŸ‘‹ <b>Welcome to the Terabox Downloader Bot!</b>\n\n"
208
+ "πŸ“₯ Send me any valid Terabox link (supports multi-link batch).\n\n"
209
+ f"πŸ“’ Make sure you are a member of: @{config.FORCE_SUB_CHANNEL_USERNAME}\n\n"
210
+ "πŸš€ Features:\n"
211
+ "- Multi batch link\n"
212
+ "- Auto cache\n"
213
+ "- Progress bar + ETA\n"
214
+ "- No ffmpeg re-encode\n"
215
+ "- Auto forward\n"
216
+ "\nβœ… <i>Send links below:</i>"
217
+ )
218
+ await message.reply(text)
219
+
220
+ @dp.message(Command("admin"))
221
+ async def admin_handler(message: Message):
222
+ if message.from_user.id != config.OWNER_ID:
223
+ return
224
+
225
+ users = await db_utils.get_all_active_user_ids_db()
226
+ uptime_sec = int(time.time() - BOT_START_TIME)
227
+
228
+ text = (
229
+ f"πŸ“… <b>Admin Panel</b>\n\n"
230
+ f"πŸ•° Uptime: {uptime_sec} sec\n"
231
+ f"πŸ“Š Total users: {len(users)}\n"
232
+ f"πŸ”’ Queue size: {TASK_QUEUE.qsize()}\n"
233
+ f"πŸ”§ Workers: {config.CONCURRENT_WORKERS}\n"
234
+ f"πŸ“ Forward Channel: {config.FORWARD_CHANNEL_ID}\n"
235
+ f"πŸ“’ Force Sub Channel: @{config.FORCE_SUB_CHANNEL_USERNAME}\n"
236
+ f"πŸ‘¨β€πŸ“‘ Worker URL: {config.TERABOX_WORKER_URL}"
237
  )
238
  await message.reply(text)
239
 
 
248
  message.from_user.first_name
249
  )
250
 
251
+ links = list(set(re.findall(r'https?://[^\s<>"]+', message.text or message.caption or "")))
252
  terabox_links = [link for link in links if any(domain in link for domain in [
253
  "terabox.com", "teraboxapp.com", "terasharelink.com", "1024tera.com",
254
  "freeterabox.com", "4funbox.com", "box-links.com"
 
259
 
260
  batch_id = str(uuid.uuid4())
261
  status_msg = await message.reply(
262
+ f"βœ… Found {len(terabox_links)} links. Queued as batch `{batch_id[:6]}`.",
263
+ reply_to_message_id=message.message_id
264
  )
265
 
266
  BATCH_JOBS[batch_id] = {
 
272
  "source_user_id": message.from_user.id,
273
  "source_message_id": message.message_id,
274
  "status_message": status_msg,
275
+ "lock": asyncio.Lock(),
276
+ "start_time": time.time()
277
  }
278
 
279
  for link in terabox_links:
 
290
  dp.startup.register(on_startup)
291
  dp.message.register(message_handler)
292
  dp.message.register(start_handler, CommandStart())
293
+ dp.message.register(admin_handler, Command("admin"))
294
+ return dp, bot