TheFirstOython commited on
Commit
ee3ec02
·
verified ·
1 Parent(s): 6245448

Update bot.js

Browse files
Files changed (1) hide show
  1. bot.js +162 -172
bot.js CHANGED
@@ -1,195 +1,185 @@
1
  const TelegramBot = require('node-telegram-bot-api');
2
- const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg');
3
- const ffmpeg = require('fluent-ffmpeg');
4
- const si = require('systeminformation');
5
-
6
- const TOKEN = '7899900752:AAE6xg24cB29m2O7_-Ox8P9e0Fhmyw6Y8bo';
7
- const ADMIN_ID = 7708913693;
8
-
9
- ffmpeg.setFfmpegPath(ffmpegInstaller.path);
10
-
11
- const bot = new TelegramBot(TOKEN, { polling: true });
12
-
13
- const userStreams = {}; // { chatId: { streamId: { proc, timeout } } }
14
- const streamCounter = {}; // { chatId: number }
15
-
16
- function getSystemSettings() {
17
- return si.cpu()
18
- .then(cpu => si.mem()
19
- .then(mem => {
20
- const cores = cpu.cores || 1;
21
- const ramGB = mem.total / 1024 / 1024 / 1024;
22
-
23
- let preset = 'ultrafast';
24
- if (cores >= 8) preset = 'faster';
25
- else if (cores >= 4) preset = 'veryfast';
26
-
27
- let bitrate = '800k';
28
- let resolution = '640x360';
29
- if (ramGB >= 8) {
30
- bitrate = '3000k';
31
- resolution = '1280x720';
32
- } else if (ramGB >= 4) {
33
- bitrate = '1500k';
34
- resolution = '854x480';
35
- }
36
- return { preset, bitrate, resolution };
37
- })
38
- );
39
  }
 
40
 
41
- function usageExample(chatId) {
42
- return bot.sendMessage(chatId,
43
- `❌ الأمر غير صحيح أو غير مكتمل.\n\n` +
44
- `استخدم أحد الأوامر التالية:\n\n` +
45
- `/stream streamkey m3u8_url [cc_text]\n` +
46
- `مثال:\n` +
47
- `/stream FB-123456789 https://example.com/stream.m3u8 مرحباً بالعالم\n\n` +
48
- `/stop stream_id\n` +
49
- `مثال:\n` +
50
- `/stop 1\n\n` +
51
- `/check\n` +
52
- `لعرض معلومات النظام`
53
- );
54
  }
55
 
56
- // /stream
57
- bot.onText(/^\/stream(?:\s+(.+))?$/, async (msg, match) => {
58
- const chatId = msg.chat.id;
59
- const argsText = match[1];
60
- if (!argsText) return usageExample(chatId);
61
-
62
- const args = argsText.trim().split(/\s+/);
63
- if (args.length < 2) return usageExample(chatId);
64
-
65
- const key = args[0];
66
- const m3u8 = args[1];
67
- const ccText = args.slice(2).join(' ');
68
-
69
- if (!streamCounter[chatId]) streamCounter[chatId] = 0;
70
- streamCounter[chatId]++;
71
- const streamId = streamCounter[chatId];
72
-
73
- try {
74
- const { preset, bitrate, resolution } = await getSystemSettings();
75
-
76
- let command = ffmpeg(m3u8)
77
- .videoCodec('libx264')
78
- .audioCodec('aac')
79
- .outputOptions([
80
- `-preset ${preset}`,
81
- `-b:v ${bitrate}`,
82
- '-f', 'flv'
83
- ])
84
- .size(resolution);
85
-
86
- if (ccText && ccText.trim() !== '') {
87
- const filter = `drawbox=x=(w-text_w)/2-10:y=h-text_h-40:w=text_w+20:h=text_h+30:[email protected]:t=max,` +
88
- `drawtext=text='${ccText}':fontcolor=white:fontsize=24:x=(w-text_w)/2:y=h-text_h-30`;
89
- command = command.videoFilters(filter);
90
- }
91
 
92
- const rtmpUrl = `rtmps://live-api-s.facebook.com:443/rtmp/${key}`;
93
- command = command.output(rtmpUrl);
94
-
95
- const proc = command.spawn();
96
-
97
- if (!userStreams[chatId]) userStreams[chatId] = {};
98
- userStreams[chatId][streamId] = { proc };
99
-
100
- const timeout = setTimeout(() => {
101
- if (proc && !proc.killed) {
102
- proc.kill('SIGTERM');
103
- bot.sendMessage(chatId, `⏹️ تم إيقاف البث معرف ${streamId} تلقائياً بعد 4 ساعات.`);
104
- delete userStreams[chatId][streamId];
105
- }
106
- }, 4 * 60 * 60 * 1000);
107
-
108
- userStreams[chatId][streamId].timeout = timeout;
109
-
110
- bot.sendMessage(chatId,
111
- `✅ تم بدء البث بنجاح!\n\n` +
112
- `▶️ معرف البث: ${streamId}\n` +
113
- `الدقة: ${resolution}\n` +
114
- `معدل البت: ${bitrate}\n` +
115
- `الإعدادات: ${preset}\n` +
116
- `⏳ سيتم إيقاف البث تلقائياً بعد 4 ساعات`
117
- );
118
-
119
- proc.on('error', err => {
120
- bot.sendMessage(chatId, `❌ حدث خطأ في البث معرف ${streamId}:\n${err.message}`);
121
- clearTimeout(timeout);
122
- delete userStreams[chatId][streamId];
123
- });
124
-
125
- proc.on('exit', (code, signal) => {
126
- if (signal === 'SIGTERM') {
127
- bot.sendMessage(chatId, `⏹️ تم إيقاف البث معرف ${streamId}.`);
128
- } else if (code !== 0) {
129
- bot.sendMessage(chatId, `⚠️ البث معرف ${streamId} انتهى برمز خروج ${code}.`);
130
- }
131
- clearTimeout(timeout);
132
- delete userStreams[chatId][streamId];
133
- });
134
-
135
- } catch (e) {
136
- return bot.sendMessage(chatId, `❌ فشل بدء البث:\n${e.message}`);
137
  }
 
 
 
 
 
 
138
  });
139
 
140
- // /stop
141
- bot.onText(/^\/stop(?:\s+(\d+))?$/, (msg, match) => {
 
142
  const chatId = msg.chat.id;
143
- const streamId = match[1] ? Number(match[1]) : null;
144
- if (!streamId) return usageExample(chatId);
145
-
146
- if (!userStreams[chatId] || !userStreams[chatId][streamId]) {
147
- return bot.sendMessage(chatId, `⚠️ لا يوجد بث نشط بالمعرف ${streamId}.`);
148
  }
149
-
150
- const { proc, timeout } = userStreams[chatId][streamId];
151
- if (proc && !proc.killed) {
152
- proc.kill('SIGTERM');
153
- clearTimeout(timeout);
154
- bot.sendMessage(chatId, `⏹️ تم إيقاف البث معرف ${streamId} من قبلك.`);
155
- delete userStreams[chatId][streamId];
156
- } else {
157
- bot.sendMessage(chatId, `⚠️ البث معرف ${streamId} متوقف بالفعل.`);
158
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  });
160
 
161
- // /check
162
- bot.onText(/\/check/, async (msg) => {
 
163
  const chatId = msg.chat.id;
164
- try {
165
- const cpu = await si.cpu();
166
- const mem = await si.mem();
167
- const osInfo = await si.osInfo();
168
-
169
- const message = `
170
- <b>معلومات النظام:</b>
171
- نظام التشغيل: ${osInfo.distro} ${osInfo.release}
172
- المعالج: ${cpu.manufacturer} ${cpu.brand} (${cpu.cores} أنوية)
173
- الذاكرة: ${(mem.total / 1024 / 1024 / 1024).toFixed(2)} GB
174
- `;
175
- bot.sendMessage(chatId, message, { parse_mode: 'HTML' });
176
- } catch (err) {
177
- bot.sendMessage(chatId, `❌ خطأ في جلب معلومات النظام: ${err.message}`);
178
  }
 
 
 
 
 
 
 
 
 
179
  });
180
 
181
- // رد افتراضي
182
- bot.on('message', (msg) => {
 
183
  const chatId = msg.chat.id;
184
- const text = msg.text || "";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
 
186
- if (
187
- text.startsWith('/stream') ||
188
- text.startsWith('/stop') ||
189
- text.startsWith('/check')
190
- ) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
- usageExample(chatId);
 
 
193
  });
194
 
195
- console.log('🤖 البوت يعمل الآن...');
 
 
1
  const TelegramBot = require('node-telegram-bot-api');
2
+ const { spawn } = require('child_process');
3
+ const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
4
+ const os = require('os');
5
+
6
+ // Initialize Telegram bot with polling
7
+ const token = '7899900752:AAFUdjznKaXgSkpp7eqFJjXanpb9eQVqw6E';
8
+ if (!token) {
9
+ console.error('خطأ: يجب تعيين TELEGRAM_BOT_TOKEN في الكود');
10
+ process.exit(1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
12
+ const bot = new TelegramBot(token, { polling: true });
13
 
14
+ // Admin user ID (replace with your actual user ID)
15
+ const ADMIN_USER_ID = '7708913693'; // TODO: Replace with your Telegram user ID
16
+
17
+ // Store active streams: { id: { process: childProcess, chatId: number, rtmpsUrl: string } }
18
+ const activeStreams = new Map();
19
+
20
+ // Helper function to log with timestamp
21
+ function logToConsole(message) {
22
+ const timestamp = new Date().toISOString();
23
+ console.log(`[${timestamp}] ${message}`);
 
 
 
24
  }
25
 
26
+ // Generate a random 4-digit ID
27
+ function generateStreamId() {
28
+ return Math.floor(1000 + Math.random() * 9000).toString();
29
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
+ // Check if user is admin
32
+ function isAdmin(userId) {
33
+ return userId.toString() === ADMIN_USER_ID;
34
+ }
35
+
36
+ // Handle /start command
37
+ bot.onText(/\/start/, (msg) => {
38
+ const userId = msg.from.id;
39
+ const chatId = msg.chat.id;
40
+ if (!isAdmin(userId)) {
41
+ bot.sendMessage(chatId, 'خطأ: لست مخولًا لاستخدام هذا البوت');
42
+ logToConsole(`Unauthorized user ${userId} sent /start`);
43
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
+ const message = 'مرحبًا! أنا بوت بث الفيديو. استخدم الأوامر التالية:\n' +
46
+ '/stream <مفتاح_فيسبوك> <رابط_m3u8> - لبدء البث\n' +
47
+ '/check - لعرض معلومات النظام\n' +
48
+ '/stop <رقم_البث> - لإيقاف البث';
49
+ bot.sendMessage(chatId, message);
50
+ logToConsole(`User ${userId} sent /start`);
51
  });
52
 
53
+ // Handle /stream <fbkey> <m3u8>
54
+ bot.onText(/\/stream (.+) (.+)/, (msg, match) => {
55
+ const userId = msg.from.id;
56
  const chatId = msg.chat.id;
57
+ if (!isAdmin(userId)) {
58
+ bot.sendMessage(chatId, 'خطأ: لست مخولًا لاستخدام هذا البوت');
59
+ logToConsole(`Unauthorized user ${userId} attempted /stream`);
60
+ return;
 
61
  }
62
+ const fbKey = match[1].trim();
63
+ const m3u8Url = match[2].trim();
64
+ const rtmpsUrl = `rtmps://live-api-s.facebook.com:443/rtmp/${fbKey}`;
65
+
66
+ // Validate inputs
67
+ if (!m3u8Url.startsWith('http') || !rtmpsUrl.startsWith('rtmps')) {
68
+ bot.sendMessage(chatId, 'خطأ: رابط M3U8 أو RTMPS غير صالح');
69
+ logToConsole(`Invalid URLs for user ${userId}: ${m3u8Url}, ${rtmpsUrl}`);
70
+ return;
71
  }
72
+
73
+ // Generate unique stream ID
74
+ let streamId;
75
+ do {
76
+ streamId = generateStreamId();
77
+ } while (activeStreams.has(streamId));
78
+
79
+ // Single-line FFmpeg command with reconnect and 5-second delay
80
+ 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}"`;
81
+ logToConsole(`Executing FFmpeg for Stream ${streamId}: ${ffmpegCommand}`);
82
+
83
+ // Start FFmpeg process
84
+ const ffmpegProcess = spawn(ffmpegCommand, { shell: true });
85
+
86
+ ffmpegProcess.stdout.on('data', (data) => {
87
+ logToConsole(`FFmpeg stdout (Stream ${streamId}): ${data}`);
88
+ });
89
+
90
+ ffmpegProcess.stderr.on('data', (data) => {
91
+ logToConsole(`FFmpeg stderr (Stream ${streamId}): ${data}`);
92
+ });
93
+
94
+ ffmpegProcess.on('spawn', () => {
95
+ bot.sendMessage(chatId, `تم بدء البث برقم تعريف: ${streamId}`);
96
+ activeStreams.set(streamId, { process: ffmpegProcess, chatId, rtmpsUrl });
97
+ logToConsole(`Stream ${streamId} started for user ${userId}`);
98
+ });
99
+
100
+ ffmpegProcess.on('error', (err) => {
101
+ bot.sendMessage(chatId, `فشل البث ${streamId}: ${err.message}`);
102
+ logToConsole(`FFmpeg error (Stream ${streamId}): ${err.message}`);
103
+ activeStreams.delete(streamId);
104
+ });
105
+
106
+ ffmpegProcess.on('close', (code) => {
107
+ bot.sendMessage(chatId, `انتهى البث ${streamId} (رمز الخروج: ${code}).`);
108
+ logToConsole(`FFmpeg closed (Stream ${streamId}) with code ${code}`);
109
+ activeStreams.delete(streamId);
110
+ });
111
  });
112
 
113
+ // Handle /check
114
+ bot.onText(/\/check/, (msg) => {
115
+ const userId = msg.from.id;
116
  const chatId = msg.chat.id;
117
+ if (!isAdmin(userId)) {
118
+ bot.sendMessage(chatId, 'خطأ: لست مخولًا لاستخدام هذا البوت');
119
+ logToConsole(`Unauthorized user ${userId} attempted /check`);
120
+ return;
 
 
 
 
 
 
 
 
 
 
121
  }
122
+ const systemInfo = `
123
+ معلومات النظام:
124
+ - استخدام المعالج: ${Math.round(os.loadavg()[0] * 100) / 100}% (متوسط دقيقة واحدة)
125
+ - الذاكرة الحرة: ${(os.freemem() / 1024 / 1024 / 1024).toFixed(2)} غيغابايت
126
+ - إجمالي الذاكرة: ${(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)} غيغابايت
127
+ - البثوث النشطة: ${activeStreams.size}
128
+ `;
129
+ bot.sendMessage(chatId, systemInfo);
130
+ logToConsole(`User ${userId} requested /check`);
131
  });
132
 
133
+ // Handle /stop <number>
134
+ bot.onText(/\/stop (\d{4})/, (msg, match) => {
135
+ const userId = msg.from.id;
136
  const chatId = msg.chat.id;
137
+ if (!isAdmin(userId)) {
138
+ bot.sendMessage(chatId, 'خطأ: لست مخولًا لاستخدام هذا البوت');
139
+ logToConsole(`Unauthorized user ${userId} attempted /stop ${match[1]}`);
140
+ return;
141
+ }
142
+ const streamId = match[1];
143
+
144
+ if (!activeStreams.has(streamId)) {
145
+ bot.sendMessage(chatId, `لا يوجد بث برقم تعريف: ${streamId}`);
146
+ logToConsole(`User ${userId} tried to stop non-existent stream ${streamId}`);
147
+ return;
148
+ }
149
+
150
+ const stream = activeStreams.get(streamId);
151
+ logToConsole(`Attempting to stop FFmpeg process for Stream ${streamId} (PID: ${stream.process.pid})`);
152
 
153
+ // Try SIGTERM first, then SIGKILL after 5 seconds if not terminated
154
+ stream.process.kill('SIGTERM');
155
+ const timeout = setTimeout(() => {
156
+ if (activeStreams.has(streamId)) {
157
+ stream.process.kill('SIGKILL');
158
+ logToConsole(`Force-killed FFmpeg process for Stream ${streamId} (PID: ${stream.process.pid})`);
159
+ }
160
+ }, 5000);
161
+
162
+ stream.process.on('close', (code) => {
163
+ clearTimeout(timeout); // Cancel SIGKILL if process closes
164
+ bot.sendMessage(chatId, `انتهى البث ${streamId} (رمز الخروج: ${code}).`);
165
+ logToConsole(`FFmpeg closed (Stream ${streamId}) with code ${code}`);
166
+ activeStreams.delete(streamId);
167
+ });
168
+
169
+ bot.sendMessage(chatId, `تم إيقاف البث ${streamId}.`);
170
+ logToConsole(`User ${userId} stopped stream ${streamId}`);
171
+ activeStreams.delete(streamId); // Ensure cleanup even if close event is delayed
172
+ });
173
+
174
+ // Log errors
175
+ bot.on('error', (err) => {
176
+ logToConsole(`Bot error: ${err.message}`);
177
+ });
178
 
179
+ // Handle polling errors
180
+ bot.on('polling_error', (err) => {
181
+ logToConsole(`Polling error: ${err.message}`);
182
  });
183
 
184
+ logToConsole('Bot started');
185
+ console.log('البوت يعمل...');