Spaces:
Running
Running
const TelegramBot = require('node-telegram-bot-api'); | |
const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg'); | |
const ffmpeg = require('fluent-ffmpeg'); | |
const si = require('systeminformation'); | |
const TOKEN = '7899900752:AAE6xg24cB29m2O7_-Ox8P9e0Fhmyw6Y8bo'; | |
const ADMIN_ID = 7708913693; | |
ffmpeg.setFfmpegPath(ffmpegInstaller.path); | |
const bot = new TelegramBot(TOKEN, { polling: true }); | |
const userStreams = {}; // { chatId: { streamId: { proc, timeout } } } | |
const streamCounter = {}; // { chatId: number } | |
function getSystemSettings() { | |
return si.cpu() | |
.then(cpu => si.mem() | |
.then(mem => { | |
const cores = cpu.cores || 1; | |
const ramGB = mem.total / 1024 / 1024 / 1024; | |
let preset = 'ultrafast'; | |
if (cores >= 8) preset = 'faster'; | |
else if (cores >= 4) preset = 'veryfast'; | |
let bitrate = '800k'; | |
let resolution = '640x360'; | |
if (ramGB >= 8) { | |
bitrate = '3000k'; | |
resolution = '1280x720'; | |
} else if (ramGB >= 4) { | |
bitrate = '1500k'; | |
resolution = '854x480'; | |
} | |
return { preset, bitrate, resolution }; | |
}) | |
); | |
} | |
function usageExample(chatId) { | |
return bot.sendMessage(chatId, | |
`❌ الأمر غير صحيح أو غير مكتمل.\n\n` + | |
`استخدم أحد الأوامر التالية:\n\n` + | |
`/stream streamkey m3u8_url [cc_text]\n` + | |
`مثال:\n` + | |
`/stream FB-123456789 https://example.com/stream.m3u8 مرحباً بالعالم\n\n` + | |
`/stop stream_id\n` + | |
`مثال:\n` + | |
`/stop 1\n\n` + | |
`/check\n` + | |
`لعرض معلومات النظام` | |
); | |
} | |
// /stream | |
bot.onText(/^\/stream(?:\s+(.+))?$/, async (msg, match) => { | |
const chatId = msg.chat.id; | |
const argsText = match[1]; | |
if (!argsText) return usageExample(chatId); | |
const args = argsText.trim().split(/\s+/); | |
if (args.length < 2) return usageExample(chatId); | |
const key = args[0]; | |
const m3u8 = args[1]; | |
const ccText = args.slice(2).join(' '); | |
if (!streamCounter[chatId]) streamCounter[chatId] = 0; | |
streamCounter[chatId]++; | |
const streamId = streamCounter[chatId]; | |
try { | |
const { preset, bitrate, resolution } = await getSystemSettings(); | |
let command = ffmpeg(m3u8) | |
.videoCodec('libx264') | |
.audioCodec('aac') | |
.outputOptions([ | |
`-preset ${preset}`, | |
`-b:v ${bitrate}`, | |
'-f', 'flv' | |
]) | |
.size(resolution); | |
if (ccText && ccText.trim() !== '') { | |
const filter = `drawbox=x=(w-text_w)/2-10:y=h-text_h-40:w=text_w+20:h=text_h+30:color=black@0.5:t=max,` + | |
`drawtext=text='${ccText}':fontcolor=white:fontsize=24:x=(w-text_w)/2:y=h-text_h-30`; | |
command = command.videoFilters(filter); | |
} | |
const rtmpUrl = `rtmps://live-api-s.facebook.com:443/rtmp/${key}`; | |
command = command.output(rtmpUrl); | |
const proc = command.spawn(); | |
if (!userStreams[chatId]) userStreams[chatId] = {}; | |
userStreams[chatId][streamId] = { proc }; | |
const timeout = setTimeout(() => { | |
if (proc && !proc.killed) { | |
proc.kill('SIGTERM'); | |
bot.sendMessage(chatId, `⏹️ تم إيقاف البث معرف ${streamId} تلقائياً بعد 4 ساعات.`); | |
delete userStreams[chatId][streamId]; | |
} | |
}, 4 * 60 * 60 * 1000); | |
userStreams[chatId][streamId].timeout = timeout; | |
bot.sendMessage(chatId, | |
`✅ تم بدء البث بنجاح!\n\n` + | |
`▶️ معرف البث: ${streamId}\n` + | |
`الدقة: ${resolution}\n` + | |
`معدل البت: ${bitrate}\n` + | |
`الإعدادات: ${preset}\n` + | |
`⏳ سيتم إيقاف البث تلقائياً بعد 4 ساعات` | |
); | |
proc.on('error', err => { | |
bot.sendMessage(chatId, `❌ حدث خطأ في البث معرف ${streamId}:\n${err.message}`); | |
clearTimeout(timeout); | |
delete userStreams[chatId][streamId]; | |
}); | |
proc.on('exit', (code, signal) => { | |
if (signal === 'SIGTERM') { | |
bot.sendMessage(chatId, `⏹️ تم إيقاف البث معرف ${streamId}.`); | |
} else if (code !== 0) { | |
bot.sendMessage(chatId, `⚠️ البث معرف ${streamId} انتهى برمز خروج ${code}.`); | |
} | |
clearTimeout(timeout); | |
delete userStreams[chatId][streamId]; | |
}); | |
} catch (e) { | |
return bot.sendMessage(chatId, `❌ فشل بدء البث:\n${e.message}`); | |
} | |
}); | |
// /stop | |
bot.onText(/^\/stop(?:\s+(\d+))?$/, (msg, match) => { | |
const chatId = msg.chat.id; | |
const streamId = match[1] ? Number(match[1]) : null; | |
if (!streamId) return usageExample(chatId); | |
if (!userStreams[chatId] || !userStreams[chatId][streamId]) { | |
return bot.sendMessage(chatId, `⚠️ لا يوجد بث نشط بالمعرف ${streamId}.`); | |
} | |
const { proc, timeout } = userStreams[chatId][streamId]; | |
if (proc && !proc.killed) { | |
proc.kill('SIGTERM'); | |
clearTimeout(timeout); | |
bot.sendMessage(chatId, `⏹️ تم إيقاف البث معرف ${streamId} من قبلك.`); | |
delete userStreams[chatId][streamId]; | |
} else { | |
bot.sendMessage(chatId, `⚠️ البث معرف ${streamId} متوقف بالفعل.`); | |
} | |
}); | |
// /check | |
bot.onText(/\/check/, async (msg) => { | |
const chatId = msg.chat.id; | |
try { | |
const cpu = await si.cpu(); | |
const mem = await si.mem(); | |
const osInfo = await si.osInfo(); | |
const message = ` | |
<b>معلومات النظام:</b> | |
نظام التشغيل: ${osInfo.distro} ${osInfo.release} | |
المعالج: ${cpu.manufacturer} ${cpu.brand} (${cpu.cores} أنوية) | |
الذاكرة: ${(mem.total / 1024 / 1024 / 1024).toFixed(2)} GB | |
`; | |
bot.sendMessage(chatId, message, { parse_mode: 'HTML' }); | |
} catch (err) { | |
bot.sendMessage(chatId, `❌ خطأ في جلب معلومات النظام: ${err.message}`); | |
} | |
}); | |
// رد افتراضي | |
bot.on('message', (msg) => { | |
const chatId = msg.chat.id; | |
const text = msg.text || ""; | |
if ( | |
text.startsWith('/stream') || | |
text.startsWith('/stop') || | |
text.startsWith('/check') | |
) return; | |
usageExample(chatId); | |
}); | |
console.log('🤖 البوت يعمل الآن...'); |