python / bot.js
TheFirstOython's picture
Update bot.js
ee3ec02 verified
raw
history blame
6.87 kB
const TelegramBot = require('node-telegram-bot-api');
const { spawn } = require('child_process');
const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
const os = require('os');
// Initialize Telegram bot with polling
const token = '7899900752:AAFUdjznKaXgSkpp7eqFJjXanpb9eQVqw6E';
if (!token) {
console.error('خطأ: يجب تعيين TELEGRAM_BOT_TOKEN في الكود');
process.exit(1);
}
const bot = new TelegramBot(token, { polling: true });
// Admin user ID (replace with your actual user ID)
const ADMIN_USER_ID = '7708913693'; // TODO: Replace with your Telegram user ID
// Store active streams: { id: { process: childProcess, chatId: number, rtmpsUrl: string } }
const activeStreams = new Map();
// Helper function to log with timestamp
function logToConsole(message) {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] ${message}`);
}
// Generate a random 4-digit ID
function generateStreamId() {
return Math.floor(1000 + Math.random() * 9000).toString();
}
// Check if user is admin
function isAdmin(userId) {
return userId.toString() === ADMIN_USER_ID;
}
// Handle /start command
bot.onText(/\/start/, (msg) => {
const userId = msg.from.id;
const chatId = msg.chat.id;
if (!isAdmin(userId)) {
bot.sendMessage(chatId, 'خطأ: لست مخولًا لاستخدام هذا البوت');
logToConsole(`Unauthorized user ${userId} sent /start`);
return;
}
const message = 'مرحبًا! أنا بوت بث الفيديو. استخدم الأوامر التالية:\n' +
'/stream <مفتاح_فيسبوك> <رابط_m3u8> - لبدء البث\n' +
'/check - لعرض معلومات النظام\n' +
'/stop <رقم_البث> - لإيقاف البث';
bot.sendMessage(chatId, message);
logToConsole(`User ${userId} sent /start`);
});
// Handle /stream <fbkey> <m3u8>
bot.onText(/\/stream (.+) (.+)/, (msg, match) => {
const userId = msg.from.id;
const chatId = msg.chat.id;
if (!isAdmin(userId)) {
bot.sendMessage(chatId, 'خطأ: لست مخولًا لاستخدام هذا البوت');
logToConsole(`Unauthorized user ${userId} attempted /stream`);
return;
}
const fbKey = match[1].trim();
const m3u8Url = match[2].trim();
const rtmpsUrl = `rtmps://live-api-s.facebook.com:443/rtmp/${fbKey}`;
// Validate inputs
if (!m3u8Url.startsWith('http') || !rtmpsUrl.startsWith('rtmps')) {
bot.sendMessage(chatId, 'خطأ: رابط M3U8 أو RTMPS غير صالح');
logToConsole(`Invalid URLs for user ${userId}: ${m3u8Url}, ${rtmpsUrl}`);
return;
}
// Generate unique stream ID
let streamId;
do {
streamId = generateStreamId();
} while (activeStreams.has(streamId));
// Single-line FFmpeg command with reconnect and 5-second delay
const ffmpegCommand = `ffmpeg -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5 -itsoffset 5 -re -i "${m3u8Url}" -c:v copy -c:a aac -f flv "${rtmpsUrl}"`;
logToConsole(`Executing FFmpeg for Stream ${streamId}: ${ffmpegCommand}`);
// Start FFmpeg process
const ffmpegProcess = spawn(ffmpegCommand, { shell: true });
ffmpegProcess.stdout.on('data', (data) => {
logToConsole(`FFmpeg stdout (Stream ${streamId}): ${data}`);
});
ffmpegProcess.stderr.on('data', (data) => {
logToConsole(`FFmpeg stderr (Stream ${streamId}): ${data}`);
});
ffmpegProcess.on('spawn', () => {
bot.sendMessage(chatId, `تم بدء البث برقم تعريف: ${streamId}`);
activeStreams.set(streamId, { process: ffmpegProcess, chatId, rtmpsUrl });
logToConsole(`Stream ${streamId} started for user ${userId}`);
});
ffmpegProcess.on('error', (err) => {
bot.sendMessage(chatId, `فشل البث ${streamId}: ${err.message}`);
logToConsole(`FFmpeg error (Stream ${streamId}): ${err.message}`);
activeStreams.delete(streamId);
});
ffmpegProcess.on('close', (code) => {
bot.sendMessage(chatId, `انتهى البث ${streamId} (رمز الخروج: ${code}).`);
logToConsole(`FFmpeg closed (Stream ${streamId}) with code ${code}`);
activeStreams.delete(streamId);
});
});
// Handle /check
bot.onText(/\/check/, (msg) => {
const userId = msg.from.id;
const chatId = msg.chat.id;
if (!isAdmin(userId)) {
bot.sendMessage(chatId, 'خطأ: لست مخولًا لاستخدام هذا البوت');
logToConsole(`Unauthorized user ${userId} attempted /check`);
return;
}
const systemInfo = `
معلومات النظام:
- استخدام المعالج: ${Math.round(os.loadavg()[0] * 100) / 100}% (متوسط دقيقة واحدة)
- الذاكرة الحرة: ${(os.freemem() / 1024 / 1024 / 1024).toFixed(2)} غيغابايت
- إجمالي الذاكرة: ${(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)} غيغابايت
- البثوث النشطة: ${activeStreams.size}
`;
bot.sendMessage(chatId, systemInfo);
logToConsole(`User ${userId} requested /check`);
});
// Handle /stop <number>
bot.onText(/\/stop (\d{4})/, (msg, match) => {
const userId = msg.from.id;
const chatId = msg.chat.id;
if (!isAdmin(userId)) {
bot.sendMessage(chatId, 'خطأ: لست مخولًا لاستخدام هذا البوت');
logToConsole(`Unauthorized user ${userId} attempted /stop ${match[1]}`);
return;
}
const streamId = match[1];
if (!activeStreams.has(streamId)) {
bot.sendMessage(chatId, `لا يوجد بث برقم تعريف: ${streamId}`);
logToConsole(`User ${userId} tried to stop non-existent stream ${streamId}`);
return;
}
const stream = activeStreams.get(streamId);
logToConsole(`Attempting to stop FFmpeg process for Stream ${streamId} (PID: ${stream.process.pid})`);
// Try SIGTERM first, then SIGKILL after 5 seconds if not terminated
stream.process.kill('SIGTERM');
const timeout = setTimeout(() => {
if (activeStreams.has(streamId)) {
stream.process.kill('SIGKILL');
logToConsole(`Force-killed FFmpeg process for Stream ${streamId} (PID: ${stream.process.pid})`);
}
}, 5000);
stream.process.on('close', (code) => {
clearTimeout(timeout); // Cancel SIGKILL if process closes
bot.sendMessage(chatId, `انتهى البث ${streamId} (رمز الخروج: ${code}).`);
logToConsole(`FFmpeg closed (Stream ${streamId}) with code ${code}`);
activeStreams.delete(streamId);
});
bot.sendMessage(chatId, `تم إيقاف البث ${streamId}.`);
logToConsole(`User ${userId} stopped stream ${streamId}`);
activeStreams.delete(streamId); // Ensure cleanup even if close event is delayed
});
// Log errors
bot.on('error', (err) => {
logToConsole(`Bot error: ${err.message}`);
});
// Handle polling errors
bot.on('polling_error', (err) => {
logToConsole(`Polling error: ${err.message}`);
});
logToConsole('Bot started');
console.log('البوت يعمل...');