tgbot / server.js
EmmyHenz001's picture
Create server.js
f682fb6 verified
// 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(`
<h1>Telegram Media Downloader Bot</h1>
<p>Bot Status: <span style="color: green;">Running βœ…</span></p>
<p>Active Cloned Bots: ${clonedBots.size}</p>
<p>Uptime: ${Math.floor(process.uptime() / 60)} minutes</p>
<hr>
<p>Created by Emmy - @emmyhenztech</p>
`);
});
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');