darkvibe314 commited on
Commit
bf627d0
·
verified ·
1 Parent(s): 3376815

Update bot.js

Browse files
Files changed (1) hide show
  1. bot.js +177 -194
bot.js CHANGED
@@ -1,197 +1,180 @@
1
- // ============================================================
2
- // 🪄 HUGGING FACE KEEP-ALIVE TRICK (Explicit 0.0.0.0 bind)
3
- // ============================================================
4
- const http = require('http');
5
- const server = http.createServer((req, res) => {
6
- res.writeHead(200, { 'Content-Type': 'text/plain' });
7
- res.end('Lecture Downloader Bot is alive and running on Hugging Face!');
8
- });
9
- // Explicitly binding to 0.0.0.0 is critical for Hugging Face network routing
10
- server.listen(7860, '0.0.0.0', () => console.log('🌐 Web server running on 0.0.0.0:7860'));
11
-
12
- // ============================================================
13
- // 🤖 BOT LIBRARIES
14
- // ============================================================
15
- const TelegramBot = require('node-telegram-bot-api');
16
- const axios = require('axios');
17
- const fs = require('fs');
18
- const path = require('path');
19
- const { exec } = require('child_process');
20
- const FormData = require('form-data');
21
-
22
- // ============================================================
23
- // ⚙️ CONFIGURATION
24
- // ============================================================
25
- const TOKEN = '8476068831:AAG9mEiMYhlIOEBYSy2P11V88NePwrJh06w';
26
- const OWNER_USERNAME = 'silent000666';
27
- const BANNER_URL = 'https://img.freepik.com/free-vector/laptop-with-program-code-isometric-icon-software-development-programming-applications-dark-neon_39422-971.jpg';
28
- const userState = {};
29
-
30
- // ============================================================
31
- // 📝 LOGGER
32
- // ============================================================
33
- const LOG_FILE = path.join(__dirname, 'debug_log.txt');
34
- fs.writeFileSync(LOG_FILE, `--- BOT STARTED ---\n`);
35
-
36
- function log(message) {
37
- const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
38
- console.log(`[${timestamp}] ${message}`);
39
- fs.appendFileSync(LOG_FILE, `[${timestamp}] ${message}\n`);
40
- }
41
-
42
- // ============================================================
43
- // 🚀 DELAYED BOOT SEQUENCE (The Network Fix)
44
- // ============================================================
45
- console.log("⏳ Waiting 5 seconds for Hugging Face DNS to stabilize...");
46
-
47
- setTimeout(() => {
48
- console.log("🚀 Network Ready! Booting Telegram Bot...");
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- const bot = new TelegramBot(TOKEN, { polling: true });
51
-
52
- // Stop errors from crashing the bot
53
- bot.on("polling_error", (err) => log(`[Polling Error] ${err.message}`));
54
-
55
- // ============================================================
56
- // 🎮 HANDLERS
57
- // ============================================================
58
- bot.onText(/\/start/, async (msg) => {
59
- userState[msg.chat.id] = null;
60
- await bot.sendPhoto(msg.chat.id, BANNER_URL, {
61
- caption: `👋 *Welcome, ${msg.from.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:_`,
62
- parse_mode: 'Markdown',
63
- reply_markup: {
64
- inline_keyboard: [
65
- [{ text: "🚀 Start Extraction", callback_data: "btn_extract" }]
66
- ]
67
- }
68
- });
69
- });
70
-
71
- bot.on('callback_query', async (q) => {
72
- const chatId = q.message.chat.id;
73
- bot.answerCallbackQuery(q.id);
74
-
75
- if (q.data === 'btn_extract') {
76
- userState[chatId] = 'WAITING_URL';
77
- await bot.sendMessage(chatId, "🔗 *Send the Lecture Link now.*", {
78
- reply_markup: { inline_keyboard: [[{ text: "❌ Cancel", callback_data: "btn_cancel" }]] }
79
- });
80
- }
81
- else if (q.data === 'btn_cancel') {
82
- userState[chatId] = null;
83
- bot.deleteMessage(chatId, q.message.message_id);
84
- }
85
- });
86
-
87
- bot.on('message', async (msg) => {
88
- const chatId = msg.chat.id;
89
- const text = msg.text;
90
-
91
- if (!text || text.startsWith('/') || userState[chatId] !== 'WAITING_URL') return;
92
-
93
- userState[chatId] = null;
94
- if (!text.startsWith('http')) return bot.sendMessage(chatId, "⚠️ Invalid Link.");
95
-
96
- fs.writeFileSync(LOG_FILE, `--- NEW PROCESS STARTED ---\n`);
97
- log(`User sent link: ${text}`);
98
-
99
- const processMsg = await bot.sendMessage(chatId, "🕵️‍♂️ *Starting Process...*\n_Analyzing..._", { parse_mode: 'Markdown' });
100
-
101
- try {
102
- log("STEP 1: Analyzing URL...");
103
- let streamUrl = text;
104
- let cookieString = "";
105
- let userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)';
106
-
107
- try {
108
- const res = await axios.get(text, { headers: { 'User-Agent': userAgent }, timeout: 15000 });
109
- if (res.headers['set-cookie']) {
110
- cookieString = res.headers['set-cookie'].map(c => c.split(';')[0]).join('; ');
111
- }
112
- const match = res.data.match(/src:\s*'(\/Stream\/Index\/[^']+)'/);
113
- if (match) {
114
- streamUrl = `https://vss-v2-app.techsol360.com${match[1]}`;
115
- log(`✅ Found HIDDEN Stream URL`);
116
- }
117
- } catch (e) {
118
- log(`⚠️ Scrape Error: ${e.message} (Using original link)`);
119
- }
120
-
121
- log("STEP 2: Starting FFmpeg Download...");
122
- await bot.editMessageText(`⬇️ *Downloading...*\n_Please wait..._`, { chat_id: chatId, message_id: processMsg.message_id, parse_mode: 'Markdown' });
123
-
124
- const timestamp = Date.now();
125
- const filePath = path.join(__dirname, `Lecture_${timestamp}.mp4`);
126
 
127
- const cmd = `ffmpeg -user_agent "${userAgent}" -headers "Cookie: ${cookieString}" -i "${streamUrl}" -c copy -bsf:a aac_adtstoasc "${filePath}" -y`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
- exec(cmd, { maxBuffer: 1024 * 1024 * 50 }, async (err, stdout, stderr) => {
130
- if (err) {
131
- log(`❌ FFmpeg Error: ${err.message}`);
132
- await sendErrorLog(chatId, processMsg.message_id, bot);
133
- return;
134
- }
135
- if (!fs.existsSync(filePath)) {
136
- log("❌ File missing after download.");
137
- await sendErrorLog(chatId, processMsg.message_id, bot);
138
- return;
139
- }
140
-
141
- const stats = fs.statSync(filePath);
142
- const sizeMB = stats.size / (1024 * 1024);
143
- log(`✅ Download Success. Size: ${sizeMB.toFixed(2)} MB`);
144
-
145
- if (sizeMB < 49) {
146
- log("STEP 3: Uploading to Telegram...");
147
- await bot.editMessageText(`📤 *Uploading to Telegram...*`, { chat_id: chatId, message_id: processMsg.message_id, parse_mode: 'Markdown' });
148
- try {
149
- await bot.sendDocument(chatId, filePath, { caption: `📦 ${sizeMB.toFixed(2)} MB` });
150
- log("Telegram Upload Success.");
151
- } catch (tgErr) { log(`Telegram Error: ${tgErr.message}`); }
152
- } else {
153
- log("STEP 3: Uploading to Gofile...");
154
- await bot.editMessageText(`🚀 *Uploading to Gofile Cloud...*`, { chat_id: chatId, message_id: processMsg.message_id, parse_mode: 'Markdown' });
155
- try {
156
- const link = await uploadToGofile(filePath);
157
- log(`✅ Gofile Success: ${link}`);
158
- await bot.sendMessage(chatId, `✅ *Done!*\n\n🔗 [Download Link](${link})\n📦 Size: ${sizeMB.toFixed(2)} MB`, { parse_mode: 'Markdown', disable_web_page_preview: true });
159
- } catch (cloudErr) {
160
- log(`❌ Gofile Failed: ${cloudErr.message}`);
161
- await sendErrorLog(chatId, processMsg.message_id, bot);
162
- }
163
- }
164
- if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
165
- });
166
- } catch (error) {
167
- log(`❌ CRITICAL: ${error.message}`);
168
- await sendErrorLog(chatId, processMsg.message_id, bot);
169
- }
170
- });
171
-
172
- }, 5000); // <-- This is the 5-second Magic Delay!
173
-
174
- // ============================================================
175
- // 📤 GOFILE UPLOAD
176
- // ============================================================
177
- async function uploadToGofile(filePath) {
178
- log("Initiating Gofile Upload...");
179
- const form = new FormData();
180
- form.append('file', fs.createReadStream(filePath));
181
- const res = await axios.post('https://upload.gofile.io/uploadfile', form, {
182
- headers: { ...form.getHeaders(), 'User-Agent': 'Mozilla/5.0' },
183
- maxContentLength: Infinity, maxBodyLength: Infinity
184
- });
185
- if (res.data.status === 'ok') return res.data.data.downloadPage;
186
- else throw new Error(`Gofile API Status: ${res.data.status}`);
187
- }
188
-
189
- // ============================================================
190
- // 🚨 ERROR REPORTER
191
- // ============================================================
192
- async function sendErrorLog(chatId, msgId, botInstance) {
193
- await botInstance.editMessageText("❌ *Process Failed.* Sending logs...", { chat_id: chatId, message_id: msgId, parse_mode: 'Markdown' });
194
- try {
195
- await botInstance.sendDocument(chatId, LOG_FILE, { caption: "📜 *Error Log*\nOpen this file to see details." });
196
- } catch (e) { console.error(e); }
197
- }
 
1
+ import os
2
+ import time
3
+ import re
4
+ import asyncio
5
+ import requests
6
+ import threading
7
+ from http.server import HTTPServer, BaseHTTPRequestHandler
8
+ from pyrogram import Client, filters, idle
9
+ from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
10
+
11
+ # ==========================================
12
+ # 🪄 HUGGING FACE KEEP-ALIVE TRICK
13
+ # ==========================================
14
+ class DummyHandler(BaseHTTPRequestHandler):
15
+ def do_GET(self):
16
+ self.send_response(200)
17
+ self.end_headers()
18
+ self.wfile.write(b"Lecture Bot is alive and running on Hugging Face!")
19
+
20
+ def keep_alive():
21
+ server = HTTPServer(('0.0.0.0', 7860), DummyHandler)
22
+ server.serve_forever()
23
+
24
+ threading.Thread(target=keep_alive, daemon=True).start()
25
+
26
+ # ==========================================
27
+ # ⚙️ CONFIGURATION
28
+ # ==========================================
29
+ TOKEN = "8476068831:AAG9mEiMYhlIOEBYSy2P11V88NePwrJh06w"
30
+ API_ID = 2040
31
+ API_HASH = "b18441a1ff607e10a989891a5462e627"
32
+
33
+ BANNER_URL = "https://img.freepik.com/free-vector/laptop-with-program-code-isometric-icon-software-development-programming-applications-dark-neon_39422-971.jpg"
34
+
35
+ app = Client("LectureBot", api_id=API_ID, api_hash=API_HASH, bot_token=TOKEN)
36
+ user_states = {}
37
+
38
+ print("🚀 LECTURE BOT STARTED...")
39
+
40
+ # ==========================================
41
+ # 📤 GOFILE UPLOAD HELPER
42
+ # ==========================================
43
+ def upload_to_gofile(filepath):
44
+ print("Initiating Gofile Upload...")
45
+ with open(filepath, 'rb') as f:
46
+ files = {'file': f}
47
+ # Gofile creates a guest account automatically when no token is provided
48
+ res = requests.post('https://upload.gofile.io/uploadfile', files=files)
49
+ data = res.json()
50
+ if data.get('status') == 'ok':
51
+ return data['data']['downloadPage']
52
+ else:
53
+ raise Exception(f"Gofile API Error: {data.get('status')}")
54
+
55
+ # ==========================================
56
+ # 🎮 BOT HANDLERS
57
+ # ==========================================
58
+ @app.on_message(filters.command("start"))
59
+ async def start_cmd(client, message):
60
+ user_states[message.chat.id] = None
61
 
62
+ keyboard = InlineKeyboardMarkup([
63
+ [InlineKeyboardButton("🚀 Start Extraction", callback_data="btn_extract")]
64
+ ])
65
+
66
+ await message.reply_photo(
67
+ photo=BANNER_URL,
68
+ 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(".", "\\."),
69
+ reply_markup=keyboard
70
+ )
71
+
72
+ @app.on_callback_query()
73
+ async def callback_handler(client, query: CallbackQuery):
74
+ chat_id = query.message.chat.id
75
+
76
+ if query.data == "btn_extract":
77
+ user_states[chat_id] = "WAITING_URL"
78
+ keyboard = InlineKeyboardMarkup([[InlineKeyboardButton("❌ Cancel", callback_data="btn_cancel")]])
79
+ await query.message.reply_text("🔗 **Send the Lecture Link now.**", reply_markup=keyboard)
80
+ await query.answer()
81
+
82
+ elif query.data == "btn_cancel":
83
+ user_states[chat_id] = None
84
+ await query.message.delete()
85
+ await query.answer("Cancelled.")
86
+
87
+ @app.on_message(filters.text & ~filters.command("start"))
88
+ async def message_handler(client, message):
89
+ chat_id = message.chat.id
90
+ text = message.text
91
+
92
+ if user_states.get(chat_id) != "WAITING_URL":
93
+ return
94
+
95
+ user_states[chat_id] = None # Reset state
96
+
97
+ if not text.startswith("http"):
98
+ return await message.reply_text("⚠️ Invalid Link.")
99
+
100
+ process_msg = await message.reply_text("🕵️‍♂️ **Starting Process...**\n_Analyzing..._")
101
+
102
+ try:
103
+ # --- STEP 1: ANALYZE URL ---
104
+ print(f"STEP 1: Analyzing URL: {text}")
105
+ stream_url = text
106
+ cookie_string = ""
107
+ user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
108
+
109
+ try:
110
+ res = requests.get(text, headers={'User-Agent': user_agent}, timeout=15)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
+ # Extract cookies if present
113
+ if 'set-cookie' in res.headers:
114
+ raw_cookies = res.headers['set-cookie'].split(',')
115
+ cookie_string = "; ".join([c.split(';')[0] for c in raw_cookies])
116
+
117
+ # Regex check for hidden stream URL
118
+ match = re.search(r"src:\s*'(/Stream/Index/[^']+)'", res.text)
119
+ if match:
120
+ stream_url = f"https://vss-v2-app.techsol360.com{match.group(1)}"
121
+ print("✅ Found HIDDEN Stream URL")
122
+ except Exception as e:
123
+ print(f"⚠️ Scrape Error: {str(e)} (Using original link)")
124
+
125
+ # --- STEP 2: DOWNLOAD ---
126
+ print("STEP 2: Starting FFmpeg Download...")
127
+ await process_msg.edit_text("⬇️ **Downloading...**\n_Please wait..._")
128
+
129
+ timestamp = int(time.time())
130
+ filepath = f"Lecture_{timestamp}.mp4"
131
+
132
+ cmd = f'ffmpeg -user_agent "{user_agent}" -headers "Cookie: {cookie_string}" -i "{stream_url}" -c copy -bsf:a aac_adtstoasc "{filepath}" -y'
133
+
134
+ # Run FFmpeg asynchronously so it doesn't block the bot
135
+ process = await asyncio.create_subprocess_shell(
136
+ cmd,
137
+ stdout=asyncio.subprocess.PIPE,
138
+ stderr=asyncio.subprocess.PIPE
139
+ )
140
+ await process.communicate()
141
+
142
+ if not os.path.exists(filepath):
143
+ raise Exception("File missing after FFmpeg download.")
144
+
145
+ # Check size
146
+ size_bytes = os.path.getsize(filepath)
147
+ size_mb = size_bytes / (1024 * 1024)
148
+ print(f"✅ Download Success. Size: {size_mb:.2f} MB")
149
+
150
+ # --- STEP 3: UPLOAD ---
151
+ if size_mb < 49.0:
152
+ print("STEP 3: Uploading to Telegram...")
153
+ await process_msg.edit_text("📤 **Uploading to Telegram...**")
154
+ await message.reply_document(
155
+ document=filepath,
156
+ caption=f"📦 {size_mb:.2f} MB"
157
+ )
158
+ else:
159
+ print("STEP 3: Uploading to Gofile...")
160
+ await process_msg.edit_text("🚀 **Uploading to Gofile Cloud...**")
161
+ link = await asyncio.to_thread(upload_to_gofile, filepath)
162
+ print(f"✅ Gofile Success: {link}")
163
 
164
+ await message.reply_text(
165
+ f"✅ **Done!**\n\n🔗 [Download Link]({link})\n📦 Size: {size_mb:.2f} MB",
166
+ disable_web_page_preview=True
167
+ )
168
+
169
+ # Cleanup
170
+ if os.path.exists(filepath):
171
+ os.remove(filepath)
172
+
173
+ except Exception as e:
174
+ print(f"❌ CRITICAL ERROR: {str(e)}")
175
+ await process_msg.edit_text(f"❌ **Process Failed.**\n`{str(e)}`")
176
+ if 'filepath' in locals() and os.path.exists(filepath):
177
+ os.remove(filepath)
178
+
179
+ if __name__ == "__main__":
180
+ app.run()