darkvibe314's picture
Rename bot.js to main.py
c5fb545 verified
Raw
History Blame Contribute Delete
6.8 kB
import os
import time
import re
import asyncio
import requests
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from pyrogram import Client, filters, idle
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
# ==========================================
# ๐Ÿช„ HUGGING FACE KEEP-ALIVE TRICK
# ==========================================
class DummyHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b"Lecture Bot is alive and running on Hugging Face!")
def keep_alive():
server = HTTPServer(('0.0.0.0', 7860), DummyHandler)
server.serve_forever()
threading.Thread(target=keep_alive, daemon=True).start()
# ==========================================
# โš™๏ธ CONFIGURATION
# ==========================================
TOKEN = "8476068831:AAG9mEiMYhlIOEBYSy2P11V88NePwrJh06w"
API_ID = 2040
API_HASH = "b18441a1ff607e10a989891a5462e627"
BANNER_URL = "https://img.freepik.com/free-vector/laptop-with-program-code-isometric-icon-software-development-programming-applications-dark-neon_39422-971.jpg"
app = Client("LectureBot", api_id=API_ID, api_hash=API_HASH, bot_token=TOKEN)
user_states = {}
print("๐Ÿš€ LECTURE BOT STARTED...")
# ==========================================
# ๐Ÿ“ค GOFILE UPLOAD HELPER
# ==========================================
def upload_to_gofile(filepath):
print("Initiating Gofile Upload...")
with open(filepath, 'rb') as f:
files = {'file': f}
# Gofile creates a guest account automatically when no token is provided
res = requests.post('https://upload.gofile.io/uploadfile', files=files)
data = res.json()
if data.get('status') == 'ok':
return data['data']['downloadPage']
else:
raise Exception(f"Gofile API Error: {data.get('status')}")
# ==========================================
# ๐ŸŽฎ BOT HANDLERS
# ==========================================
@app.on_message(filters.command("start"))
async def start_cmd(client, message):
user_states[message.chat.id] = None
keyboard = InlineKeyboardMarkup([
[InlineKeyboardButton("๐Ÿš€ Start Extraction", callback_data="btn_extract")]
])
await message.reply_photo(
photo=BANNER_URL,
caption=f"๐Ÿ‘‹ **Welcome, {message.from_user.first_name}**\n\nI am your **Lecture Downloader**.\n\n๐Ÿ”น **Modes:**\nโ€ข < 50MB: Direct Telegram File\nโ€ข > 50MB: High-Speed Gofile Link\n\n_Click below to start:_".replace(".", "\\."),
reply_markup=keyboard
)
@app.on_callback_query()
async def callback_handler(client, query: CallbackQuery):
chat_id = query.message.chat.id
if query.data == "btn_extract":
user_states[chat_id] = "WAITING_URL"
keyboard = InlineKeyboardMarkup([[InlineKeyboardButton("โŒ Cancel", callback_data="btn_cancel")]])
await query.message.reply_text("๐Ÿ”— **Send the Lecture Link now.**", reply_markup=keyboard)
await query.answer()
elif query.data == "btn_cancel":
user_states[chat_id] = None
await query.message.delete()
await query.answer("Cancelled.")
@app.on_message(filters.text & ~filters.command("start"))
async def message_handler(client, message):
chat_id = message.chat.id
text = message.text
if user_states.get(chat_id) != "WAITING_URL":
return
user_states[chat_id] = None # Reset state
if not text.startswith("http"):
return await message.reply_text("โš ๏ธ Invalid Link.")
process_msg = await message.reply_text("๐Ÿ•ต๏ธโ€โ™‚๏ธ **Starting Process...**\n_Analyzing..._")
try:
# --- STEP 1: ANALYZE URL ---
print(f"STEP 1: Analyzing URL: {text}")
stream_url = text
cookie_string = ""
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
try:
res = requests.get(text, headers={'User-Agent': user_agent}, timeout=15)
# Extract cookies if present
if 'set-cookie' in res.headers:
raw_cookies = res.headers['set-cookie'].split(',')
cookie_string = "; ".join([c.split(';')[0] for c in raw_cookies])
# Regex check for hidden stream URL
match = re.search(r"src:\s*'(/Stream/Index/[^']+)'", res.text)
if match:
stream_url = f"https://vss-v2-app.techsol360.com{match.group(1)}"
print("โœ… Found HIDDEN Stream URL")
except Exception as e:
print(f"โš ๏ธ Scrape Error: {str(e)} (Using original link)")
# --- STEP 2: DOWNLOAD ---
print("STEP 2: Starting FFmpeg Download...")
await process_msg.edit_text("โฌ‡๏ธ **Downloading...**\n_Please wait..._")
timestamp = int(time.time())
filepath = f"Lecture_{timestamp}.mp4"
cmd = f'ffmpeg -user_agent "{user_agent}" -headers "Cookie: {cookie_string}" -i "{stream_url}" -c copy -bsf:a aac_adtstoasc "{filepath}" -y'
# Run FFmpeg asynchronously so it doesn't block the bot
process = await asyncio.create_subprocess_shell(
cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
await process.communicate()
if not os.path.exists(filepath):
raise Exception("File missing after FFmpeg download.")
# Check size
size_bytes = os.path.getsize(filepath)
size_mb = size_bytes / (1024 * 1024)
print(f"โœ… Download Success. Size: {size_mb:.2f} MB")
# --- STEP 3: UPLOAD ---
if size_mb < 49.0:
print("STEP 3: Uploading to Telegram...")
await process_msg.edit_text("๐Ÿ“ค **Uploading to Telegram...**")
await message.reply_document(
document=filepath,
caption=f"๐Ÿ“ฆ {size_mb:.2f} MB"
)
else:
print("STEP 3: Uploading to Gofile...")
await process_msg.edit_text("๐Ÿš€ **Uploading to Gofile Cloud...**")
link = await asyncio.to_thread(upload_to_gofile, filepath)
print(f"โœ… Gofile Success: {link}")
await message.reply_text(
f"โœ… **Done!**\n\n๐Ÿ”— [Download Link]({link})\n๐Ÿ“ฆ Size: {size_mb:.2f} MB",
disable_web_page_preview=True
)
# Cleanup
if os.path.exists(filepath):
os.remove(filepath)
except Exception as e:
print(f"โŒ CRITICAL ERROR: {str(e)}")
await process_msg.edit_text(f"โŒ **Process Failed.**\n`{str(e)}`")
if 'filepath' in locals() and os.path.exists(filepath):
os.remove(filepath)
if __name__ == "__main__":
app.run()