Spaces:
Running
Running
File size: 6,869 Bytes
6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d 6af76e3 2d70f5d |
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 181 182 183 184 185 |
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('البوت يعمل...'); |