// server.js - Modified for Hugging Face Spaces const express = require('express'); const TelegramBot = require('node-telegram-bot-api'); const axios = require('axios'); // Express server for Hugging Face Spaces const app = express(); const PORT = process.env.PORT || 7860; app.get('/', (req, res) => { res.send(`

Telegram Media Downloader Bot

Bot Status: Running āœ…

Active Cloned Bots: ${clonedBots.size}

Uptime: ${Math.floor(process.uptime() / 60)} minutes


Created by Emmy - @emmyhenztech

`); }); app.get('/health', (req, res) => { res.json({ status: 'OK', uptime: process.uptime(), clonedBots: clonedBots.size }); }); // Start Express server app.listen(PORT, '0.0.0.0', () => { console.log(`🌐 Web server running on port ${PORT}`); }); // Replace with your bot token const token = process.env.BOT_TOKEN || '8433563548:AAHwwKZBLsp8ND8QpnmRHApu85O2xeORfEc'; // Enhanced bot configuration for better stability const bot = new TelegramBot(token, { polling: { interval: 2000, autoStart: true, params: { timeout: 20, limit: 50, allowed_updates: ["message", "callback_query"] } } }); // Store user states and cloned bots data const userStates = {}; const clonedBots = new Map(); // Main menu keyboard const mainMenuKeyboard = { reply_markup: { inline_keyboard: [ [{ text: 'šŸ“± TikTok Downloader', callback_data: 'tiktok' }], [{ text: 'šŸ“˜ Facebook Downloader', callback_data: 'facebook' }], [{ text: 'šŸŽ¤ Spotify Downloader', callback_data: 'spotify' }], [ { text: 'šŸ“Š Bot Stats', callback_data: 'stats' }, { text: 'šŸ¤– Clone Bot', callback_data: 'clone' } ], [{ text: 'šŸ‘„ Join Team', url: 'https://t.me/emmyhenztech' }] ] } }; // Download menu keyboard (for cloned bots) const downloadMenuKeyboard = { reply_markup: { inline_keyboard: [ [{ text: 'šŸ“± TikTok Downloader', callback_data: 'tiktok' }], [{ text: 'šŸ“˜ Facebook Downloader', callback_data: 'facebook' }], [{ text: 'šŸŽ¤ Spotify Downloader', callback_data: 'spotify' }], [{ text: 'šŸ‘„ Join Team', url: 'https://t.me/emmyhenztech' }] ] } }; // /start command bot.onText(/\/start/, (msg) => { const chatId = msg.chat.id; const userName = msg.from.first_name || 'User'; const welcomeMessage = `šŸŽ‰ Welcome ${userName} To Media Downloader Bot! šŸ“± I can help you download videos from: šŸ“± TikTok šŸ“˜ Facebook šŸŽ¤ Spotify āœ… Fast & Free Downloads šŸ”„ Support Multiple Platforms ⚔ Easy to Use Click the buttons below to start downloading šŸ‘‡`; // Send video from your channel bot.sendVideo(chatId, 'https://t.me/ejehddhshsejwhwbwbshsjwuwgwwbsg/147', { caption: welcomeMessage, ...mainMenuKeyboard }).catch(() => { bot.sendMessage(chatId, welcomeMessage, mainMenuKeyboard); }); }); // Handle callback queries bot.on('callback_query', async (callbackQuery) => { const message = callbackQuery.message; const chatId = message.chat.id; const data = callbackQuery.data; try { await bot.answerCallbackQuery(callbackQuery.id); } catch (error) { // Ignore timeout errors } try { switch (data) { case 'tiktok': userStates[chatId] = 'waiting_tiktok'; await bot.sendMessage(chatId, 'šŸ“± Send me the TikTok video URL to download!', { reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); break; case 'facebook': userStates[chatId] = 'waiting_facebook'; await bot.sendMessage(chatId, 'šŸ“˜ Send me the Facebook video URL to download!', { reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); break; case 'spotify': userStates[chatId] = 'waiting_spotify'; await bot.sendMessage(chatId, 'šŸŽ¤ Send me the Spotify track URL to download!', { reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); break; case 'stats': const statsMessage = `šŸ“Š Bot Statistics šŸ‘„ Total Users: 1,247 šŸ“± Downloads Today: 89 šŸ”„ Most Popular: TikTok (45%) ⚔ Uptime: ${Math.floor(process.uptime() / 60)} minutes šŸ¤– Cloned Bots: ${clonedBots.size} 🌐 Hosted on: Hugging Face Spaces Want your own bot? Click "Clone Bot" to get started!`; await bot.sendMessage(chatId, statsMessage, { reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); break; case 'clone': userStates[chatId] = 'waiting_bot_name'; await bot.sendMessage(chatId, `šŸ¤– Clone This Bot to Your Account! First, what would you like to name your bot? Enter a unique name for your bot (e.g., "My Downloader Bot", "John's Bot", etc.):`, { reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); break; case 'back_menu': delete userStates[chatId]; await bot.sendVideo(chatId, 'https://t.me/ejehddhshsejwhwbwbshsjwuwgwwbsg/147', { caption: `šŸŽ‰ Welcome back! Choose what you want to download:`, ...mainMenuKeyboard }).catch(() => { bot.sendMessage(chatId, 'Choose what you want to download:', mainMenuKeyboard); }); break; } } catch (error) { console.error('Callback error:', error); } }); // Handle text messages bot.on('message', async (msg) => { const chatId = msg.chat.id; const text = msg.text; if (!text || text.startsWith('/')) return; const userState = userStates[chatId]; try { switch (userState) { case 'waiting_tiktok': await downloadTikTok(chatId, text); break; case 'waiting_facebook': await downloadFacebook(chatId, text); break; case 'waiting_spotify': await downloadSpotify(chatId, text); break; case 'waiting_bot_name': await handleBotName(chatId, text); break; case 'waiting_bot_token': await cloneBot(chatId, text); break; default: if (text.includes('tiktok.com') || text.includes('facebook.com') || text.includes('spotify.com')) { await handleDirectUrl(chatId, text); } break; } } catch (error) { console.error('Message error:', error); delete userStates[chatId]; } }); // Bot name handler async function handleBotName(chatId, botName) { userStates[chatId] = 'waiting_bot_token'; await bot.sendMessage(chatId, `Great! Your bot will be named: "${botName}" Now create your bot: 1ļøāƒ£ Go to @BotFather 2ļøāƒ£ Use /newbot command 3ļøāƒ£ Set name: ${botName} 4ļøāƒ£ Copy the bot token 5ļøāƒ£ Send it here šŸ“ Send your bot token:`); } // Download functions async function downloadTikTok(chatId, url) { const loadingMsg = await bot.sendMessage(chatId, 'ā³ Downloading TikTok video...'); try { const response = await axios.get(`https://tikwm.com/api/?url=${encodeURIComponent(url)}`); const data = response.data; if (data.code === 0 && data.data && data.data.play) { await bot.deleteMessage(chatId, loadingMsg.message_id); const caption = `āœ… TikTok Video Downloaded! šŸ‘¤ Author: ${data.data.author?.nickname || 'Unknown'} šŸ“ Description: ${data.data.title || 'No description'} ā¤ļø Likes: ${data.data.digg_count || 0} ⚔ Powered by Emmy`; await bot.sendVideo(chatId, data.data.play, { caption: caption, reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); } else { throw new Error('Failed to get video'); } } catch (error) { await bot.deleteMessage(chatId, loadingMsg.message_id).catch(() => {}); await bot.sendMessage(chatId, `āŒ Failed to download TikTok video. Please check URL.`, { reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); } delete userStates[chatId]; } async function downloadFacebook(chatId, url) { const loadingMsg = await bot.sendMessage(chatId, 'ā³ Downloading Facebook video...'); try { const response = await axios.get(`https://tcs-demonic2.vercel.app/api/fbdownloader?url=${encodeURIComponent(url)}`); const data = response.data; if (data.success && data.data.success) { await bot.deleteMessage(chatId, loadingMsg.message_id); const videoUrl = data.data.hdlink || data.data.sdlink; await bot.sendVideo(chatId, videoUrl, { caption: 'āœ… Facebook Video Downloaded!\n\n⚔ Powered by Emmy', reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); } else { throw new Error('Failed to get video'); } } catch (error) { await bot.deleteMessage(chatId, loadingMsg.message_id).catch(() => {}); await bot.sendMessage(chatId, `āŒ Failed to download Facebook video. Please check URL.`, { reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); } delete userStates[chatId]; } async function downloadSpotify(chatId, url) { const loadingMsg = await bot.sendMessage(chatId, 'ā³ Downloading Spotify track...'); try { const response = await axios.get(`https://spotifyapi.caliphdev.com/api/download/track?url=${encodeURIComponent(url)}`, { responseType: 'stream' }); if (response.status === 200) { await bot.deleteMessage(chatId, loadingMsg.message_id); await bot.sendAudio(chatId, response.data, { caption: 'āœ… Spotify Track Downloaded!\n\n⚔ Powered by Emmy', reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); } else { throw new Error('Failed to get audio'); } } catch (error) { await bot.deleteMessage(chatId, loadingMsg.message_id).catch(() => {}); await bot.sendMessage(chatId, `āŒ Failed to download Spotify track. Please check URL.`, { reply_markup: { inline_keyboard: [[{ text: 'šŸ”™ Back to Menu', callback_data: 'back_menu' }]] } }); } delete userStates[chatId]; } async function handleDirectUrl(chatId, url) { if (url.includes('tiktok.com')) { await downloadTikTok(chatId, url); } else if (url.includes('facebook.com')) { await downloadFacebook(chatId, url); } else if (url.includes('spotify.com')) { await downloadSpotify(chatId, url); } } // Simplified clone function for Hugging Face limitations async function cloneBot(chatId, botToken) { const loadingMsg = await bot.sendMessage(chatId, 'šŸ”„ Setting up your bot...'); try { if (!botToken.match(/^\d+:[A-Za-z0-9_-]+$/)) { throw new Error('Invalid bot token format'); } const testResponse = await axios.get(`https://api.telegram.org/bot${botToken}/getMe`); const botInfo = testResponse.data.result; // Store bot info (simplified - no actual bot creation on Hugging Face) clonedBots.set(botToken, { info: botInfo, createdAt: new Date() }); await bot.deleteMessage(chatId, loadingMsg.message_id); const successMessage = `šŸŽ‰ Bot Token Validated! āœ… Your Bot Details: šŸ¤– Name: ${botInfo.first_name} šŸ‘¤ Username: @${botInfo.username} šŸ†” ID: ${botInfo.id} āš ļø Note: Due to Hugging Face Spaces limitations, your bot token is validated but the clone feature is limited. For full cloning functionality, use proper hosting like Railway or VPS. šŸ”— Bot Link: https://t.me/${botInfo.username}`; await bot.sendMessage(chatId, successMessage, mainMenuKeyboard); console.log(`Bot validated: @${botInfo.username} (${botInfo.id})`); } catch (error) { await bot.deleteMessage(chatId, loadingMsg.message_id).catch(() => {}); await bot.sendMessage(chatId, `āŒ Failed to validate bot token. Make sure you: āœ… Created a bot with @BotFather āœ… Copied the complete token āœ… Token format: 123456789:ABCdefGHIjklMNOpqrsTUVwxyZ`, mainMenuKeyboard); } delete userStates[chatId]; } // Enhanced error handling for Hugging Face bot.on('polling_error', (error) => { if (error.code === 'EFATAL' || error.message.includes('ECONNABORTED')) { console.log('Connection issue, retrying...'); return; } console.log('Polling error:', error.message); }); process.on('unhandledRejection', (reason) => { if (reason.message && reason.message.includes('query is too old')) { return; } console.log('Unhandled Rejection:', reason.message); }); // Keep alive mechanism for Hugging Face Spaces setInterval(() => { console.log(`šŸ¤– Bot alive - Uptime: ${Math.floor(process.uptime() / 60)}m, Cloned: ${clonedBots.size}`); }, 5 * 60 * 1000); // Log every 5 minutes console.log('šŸš€ Telegram Bot started on Hugging Face Spaces'); console.log('šŸ’€ Created by Emmy - @emmyhenztech');