File size: 6,798 Bytes
bf627d0 854a069 bf627d0 854a069 bf627d0 854a069 bf627d0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | 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() |