update
Browse files- .env +26 -0
- Dockerfile +2 -2
- index.js +149 -41
- package.json +6 -6
.env
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Bot Configuration
|
| 2 |
+
BOT_TOKEN=8570915227:AAFyjS3NspIQWVHfe8HdtTQ_GJb3cXpGc9s
|
| 3 |
+
ADMIN_IDS=7754777405
|
| 4 |
+
ADMIN_USERNAMES=fourstore1
|
| 5 |
+
GROUP_CHAT_ID=-1003554711107
|
| 6 |
+
SEND_TO_GROUP=true
|
| 7 |
+
|
| 8 |
+
# Web Credentials
|
| 9 |
+
WEB_EMAIL=gamingmukulff@gmail.com
|
| 10 |
+
WEB_PASSWORD=Munir@@2255++
|
| 11 |
+
|
| 12 |
+
# Monitoring Settings
|
| 13 |
+
CHECK_INTERVAL=5000
|
| 14 |
+
TIMEOUT_MINUTES=30
|
| 15 |
+
AUTO_START_CONSOLE_MONITOR=false
|
| 16 |
+
AUTO_START_GLOBAL_MONITOR=true
|
| 17 |
+
ENABLE_PING=true
|
| 18 |
+
|
| 19 |
+
# Server Configuration
|
| 20 |
+
PORT=7860
|
| 21 |
+
DOMAIN=https://fourstore-tele.hf.space
|
| 22 |
+
NODE_ENV=production
|
| 23 |
+
AUTH_TOKEN=
|
| 24 |
+
|
| 25 |
+
# Required Groups (JSON array)
|
| 26 |
+
REQUIRED_GROUPS=[{"chat_id":"@fourstore_gacha","invite_link":"https://t.me/fourstore_gacha","name":"Fourstore Gacha"},{"chat_id":"@kuramav2","invite_link":"https://t.me/kuramav2","name":"Kurama V2"}]
|
Dockerfile
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
FROM node:20-slim
|
| 2 |
|
| 3 |
RUN apt update && apt install -y \
|
| 4 |
-
wget gnupg ca-certificates xvfb \
|
| 5 |
fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 \
|
| 6 |
libatk1.0-0 libxss1 libnss3 libxcomposite1 libxdamage1 libxrandr2 libgbm1 \
|
| 7 |
&& wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
|
|
@@ -17,7 +17,7 @@ RUN npm install
|
|
| 17 |
|
| 18 |
COPY . .
|
| 19 |
|
| 20 |
-
EXPOSE
|
| 21 |
|
| 22 |
CMD rm -f /tmp/.X99-lock && \
|
| 23 |
Xvfb :99 -screen 0 1024x768x24 & \
|
|
|
|
| 1 |
FROM node:20-slim
|
| 2 |
|
| 3 |
RUN apt update && apt install -y \
|
| 4 |
+
wget gnupg ca-certificates xvfb curl \
|
| 5 |
fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 \
|
| 6 |
libatk1.0-0 libxss1 libnss3 libxcomposite1 libxdamage1 libxrandr2 libgbm1 \
|
| 7 |
&& wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
|
|
|
|
| 17 |
|
| 18 |
COPY . .
|
| 19 |
|
| 20 |
+
EXPOSE 7860
|
| 21 |
|
| 22 |
CMD rm -f /tmp/.X99-lock && \
|
| 23 |
Xvfb :99 -screen 0 1024x768x24 & \
|
index.js
CHANGED
|
@@ -6,15 +6,19 @@ const { exec } = require('child_process');
|
|
| 6 |
const util = require('util');
|
| 7 |
const cron = require('node-cron');
|
| 8 |
const express = require('express');
|
|
|
|
| 9 |
const execAsync = util.promisify(exec);
|
| 10 |
|
| 11 |
class TelegramOTPBot {
|
| 12 |
constructor() {
|
| 13 |
-
|
| 14 |
-
this.botToken =
|
| 15 |
-
this.adminIds =
|
| 16 |
-
this.adminUsernames =
|
| 17 |
-
this.groupChatId =
|
|
|
|
|
|
|
|
|
|
| 18 |
this.apiBaseURL = 'https://x.mnitnetwork.com';
|
| 19 |
this.dataDir = path.join(__dirname, 'data');
|
| 20 |
this.rangesFile = path.join(this.dataDir, 'ranges.json');
|
|
@@ -33,13 +37,13 @@ class TelegramOTPBot {
|
|
| 33 |
this.consoleMonitorInterval = null;
|
| 34 |
this.lastConsoleId = 0;
|
| 35 |
this.consoleCheckCount = 0;
|
| 36 |
-
this.checkInterval =
|
| 37 |
-
this.timeoutMinutes =
|
| 38 |
this.isProcessing = new Set();
|
| 39 |
this.userRangeRequests = new Map();
|
| 40 |
this.userOTPHistory = new Map();
|
| 41 |
-
this.consoleMonitorEnabled =
|
| 42 |
-
this.globalMonitorEnabled =
|
| 43 |
this.isGroupChatIdValid = false;
|
| 44 |
this.groupChatInfo = null;
|
| 45 |
this.isBulkProcessing = false;
|
|
@@ -49,12 +53,22 @@ class TelegramOTPBot {
|
|
| 49 |
this.consoleRangeCounts = new Map();
|
| 50 |
this.otpGroupSent = new Set();
|
| 51 |
this.consoleCheckInterval = 5000;
|
|
|
|
|
|
|
| 52 |
|
| 53 |
// Express setup
|
| 54 |
this.expressApp = null;
|
| 55 |
this.server = null;
|
| 56 |
-
this.expressPort =
|
| 57 |
this.isBotRunning = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
}
|
| 59 |
|
| 60 |
async initialize() {
|
|
@@ -72,7 +86,8 @@ class TelegramOTPBot {
|
|
| 72 |
});
|
| 73 |
|
| 74 |
await this.bot.launch();
|
| 75 |
-
console.log('Bot started');
|
|
|
|
| 76 |
this.isBotRunning = true;
|
| 77 |
|
| 78 |
await this.checkAndValidateGroupChatId();
|
|
@@ -87,6 +102,24 @@ class TelegramOTPBot {
|
|
| 87 |
startExpressServer() {
|
| 88 |
this.expressApp = express();
|
| 89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
// Route untuk status bot
|
| 91 |
this.expressApp.get('/', (req, res) => {
|
| 92 |
const status = {
|
|
@@ -100,7 +133,9 @@ class TelegramOTPBot {
|
|
| 100 |
monitors: Array.from(this.activeMonitors.values()).reduce((sum, arr) => sum + arr.length, 0),
|
| 101 |
users: Object.keys(this.users || {}).length,
|
| 102 |
ranges: Object.keys(this.ranges || {}).length,
|
| 103 |
-
expressPort: this.expressPort
|
|
|
|
|
|
|
| 104 |
};
|
| 105 |
|
| 106 |
res.json(status);
|
|
@@ -112,12 +147,13 @@ class TelegramOTPBot {
|
|
| 112 |
const sessionStatus = this.sharedSession ? 'π’ ACTIVE' : 'π΄ NO SESSION';
|
| 113 |
const expiry = this.sharedSession ? new Date(this.sharedSession.expiry).toLocaleString() : 'N/A';
|
| 114 |
const balance = this.sharedSession ? this.sharedSession.balance : 'N/A';
|
|
|
|
| 115 |
|
| 116 |
const html = `
|
| 117 |
<!DOCTYPE html>
|
| 118 |
<html>
|
| 119 |
<head>
|
| 120 |
-
<title>Bot
|
| 121 |
<meta charset="UTF-8">
|
| 122 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 123 |
<style>
|
|
@@ -209,18 +245,36 @@ class TelegramOTPBot {
|
|
| 209 |
padding-top: 20px;
|
| 210 |
border-top: 1px solid #dee2e6;
|
| 211 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
</style>
|
| 213 |
<meta http-equiv="refresh" content="10">
|
| 214 |
</head>
|
| 215 |
<body>
|
| 216 |
<div class="container">
|
| 217 |
-
<h1>π€
|
| 218 |
|
| 219 |
<div class="status-card">
|
| 220 |
<div class="status-item">
|
| 221 |
<span class="label">Bot Status:</span>
|
| 222 |
<span class="value ${this.isBotRunning ? 'online' : 'offline'}">${botStatus}</span>
|
| 223 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
<div class="status-item">
|
| 225 |
<span class="label">Session Status:</span>
|
| 226 |
<span class="value">${sessionStatus}</span>
|
|
@@ -258,6 +312,17 @@ class TelegramOTPBot {
|
|
| 258 |
</div>
|
| 259 |
</div>
|
| 260 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
<div class="last-update">
|
| 262 |
Last updated: ${new Date().toLocaleString()}<br>
|
| 263 |
Auto-refresh every 10 seconds
|
|
@@ -272,11 +337,15 @@ class TelegramOTPBot {
|
|
| 272 |
|
| 273 |
// Route untuk health check
|
| 274 |
this.expressApp.get('/health', (req, res) => {
|
| 275 |
-
|
| 276 |
-
status: 'healthy',
|
| 277 |
bot: this.isBotRunning,
|
| 278 |
-
timestamp: new Date().toISOString()
|
| 279 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
});
|
| 281 |
|
| 282 |
// Route untuk info lengkap (JSON)
|
|
@@ -310,22 +379,65 @@ class TelegramOTPBot {
|
|
| 310 |
check_interval: this.checkInterval,
|
| 311 |
timeout_minutes: this.timeoutMinutes
|
| 312 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 313 |
server: {
|
| 314 |
express_port: this.expressPort,
|
|
|
|
| 315 |
uptime: process.uptime(),
|
| 316 |
-
memory_usage: process.memoryUsage()
|
|
|
|
| 317 |
}
|
| 318 |
};
|
| 319 |
|
| 320 |
res.json(info);
|
| 321 |
});
|
| 322 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
// Start server
|
| 324 |
-
this.server = this.expressApp.listen(this.expressPort, () => {
|
| 325 |
-
console.log(
|
| 326 |
-
console.log(
|
| 327 |
-
console.log(
|
| 328 |
-
console.log(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
});
|
| 330 |
|
| 331 |
// Handle server errors
|
|
@@ -376,9 +488,9 @@ class TelegramOTPBot {
|
|
| 376 |
const sessionData = await this.loadJSON(this.sessionFile);
|
| 377 |
if (sessionData) {
|
| 378 |
this.sharedSession = sessionData;
|
| 379 |
-
console.log('Session loaded');
|
| 380 |
} else {
|
| 381 |
-
console.log('No session data found');
|
| 382 |
}
|
| 383 |
} catch (error) {
|
| 384 |
console.log('Error loading data:', error.message);
|
|
@@ -455,15 +567,9 @@ class TelegramOTPBot {
|
|
| 455 |
|
| 456 |
if (chatType === 'group' || chatType === 'supergroup') {
|
| 457 |
this.groupChatId = chatId.toString();
|
| 458 |
-
this.config.group_chat_id = chatId.toString();
|
| 459 |
-
|
| 460 |
-
await fs.writeFile(
|
| 461 |
-
path.join(__dirname, 'config.json'),
|
| 462 |
-
JSON.stringify(this.config, null, 2)
|
| 463 |
-
);
|
| 464 |
|
| 465 |
await ctx.reply(
|
| 466 |
-
`β
*Group Chat ID Updated!*\n\nπ New Group ID: \`${chatId}\`\nπ·οΈ Title: ${chatTitle}
|
| 467 |
{ parse_mode: 'Markdown' }
|
| 468 |
);
|
| 469 |
|
|
@@ -1290,7 +1396,7 @@ class TelegramOTPBot {
|
|
| 1290 |
newFacebookCount++;
|
| 1291 |
this.lastConsoleId = logId;
|
| 1292 |
|
| 1293 |
-
if (this.groupChatId) {
|
| 1294 |
await this.sendConsoleToGroup(log);
|
| 1295 |
}
|
| 1296 |
}
|
|
@@ -1303,7 +1409,7 @@ class TelegramOTPBot {
|
|
| 1303 |
newWhatsappCount++;
|
| 1304 |
this.lastConsoleId = logId;
|
| 1305 |
|
| 1306 |
-
if (this.groupChatId) {
|
| 1307 |
await this.sendConsoleToGroup(log);
|
| 1308 |
}
|
| 1309 |
}
|
|
@@ -1339,7 +1445,7 @@ class TelegramOTPBot {
|
|
| 1339 |
|
| 1340 |
async sendConsoleToGroup(log) {
|
| 1341 |
try {
|
| 1342 |
-
if (!this.groupChatId) {
|
| 1343 |
return;
|
| 1344 |
}
|
| 1345 |
|
|
@@ -1785,7 +1891,7 @@ class TelegramOTPBot {
|
|
| 1785 |
|
| 1786 |
await this.sendOTPNotification(userId, status, targetNumber, rangeUsed);
|
| 1787 |
|
| 1788 |
-
if (this.groupChatId) {
|
| 1789 |
await this.sendOTPToGroup(status, targetNumber, userId, rangeUsed);
|
| 1790 |
}
|
| 1791 |
|
|
@@ -1884,7 +1990,7 @@ class TelegramOTPBot {
|
|
| 1884 |
|
| 1885 |
async sendOTPToGroup(status, targetNumber, userId, rangeUsed) {
|
| 1886 |
try {
|
| 1887 |
-
if (!this.groupChatId) {
|
| 1888 |
return;
|
| 1889 |
}
|
| 1890 |
|
|
@@ -2020,7 +2126,7 @@ class TelegramOTPBot {
|
|
| 2020 |
this.lastCheckedIds.add(itemId);
|
| 2021 |
|
| 2022 |
const otp = this.extractOTP(item.otp || item.message);
|
| 2023 |
-
if (otp && this.groupChatId) {
|
| 2024 |
await this.sendGlobalOTPToGroup(item, otp);
|
| 2025 |
}
|
| 2026 |
}
|
|
@@ -2037,7 +2143,7 @@ class TelegramOTPBot {
|
|
| 2037 |
|
| 2038 |
async sendGlobalOTPToGroup(item, otp) {
|
| 2039 |
try {
|
| 2040 |
-
if (!this.groupChatId) {
|
| 2041 |
return;
|
| 2042 |
}
|
| 2043 |
|
|
@@ -2903,6 +3009,8 @@ class TelegramOTPBot {
|
|
| 2903 |
const bot = new TelegramOTPBot();
|
| 2904 |
|
| 2905 |
const gracefulShutdown = () => {
|
|
|
|
|
|
|
| 2906 |
if (bot.bot) {
|
| 2907 |
bot.bot.stop();
|
| 2908 |
}
|
|
@@ -2940,6 +3048,6 @@ process.on('unhandledRejection', (reason, promise) => {
|
|
| 2940 |
});
|
| 2941 |
|
| 2942 |
bot.initialize().catch(error => {
|
| 2943 |
-
console.error('FAILED:', error);
|
| 2944 |
process.exit(1);
|
| 2945 |
});
|
|
|
|
| 6 |
const util = require('util');
|
| 7 |
const cron = require('node-cron');
|
| 8 |
const express = require('express');
|
| 9 |
+
require('dotenv').config();
|
| 10 |
const execAsync = util.promisify(exec);
|
| 11 |
|
| 12 |
class TelegramOTPBot {
|
| 13 |
constructor() {
|
| 14 |
+
// Load config dari environment variables
|
| 15 |
+
this.botToken = process.env.BOT_TOKEN;
|
| 16 |
+
this.adminIds = process.env.ADMIN_IDS ? process.env.ADMIN_IDS.split(',').map(id => id.trim()) : [];
|
| 17 |
+
this.adminUsernames = process.env.ADMIN_USERNAMES ? process.env.ADMIN_USERNAMES.split(',').map(u => u.trim()) : [];
|
| 18 |
+
this.groupChatId = process.env.GROUP_CHAT_ID || '';
|
| 19 |
+
this.webEmail = process.env.WEB_EMAIL || '';
|
| 20 |
+
this.webPassword = process.env.WEB_PASSWORD || '';
|
| 21 |
+
this.sendToGroup = process.env.SEND_TO_GROUP === 'true' || process.env.SEND_TO_GROUP === '1';
|
| 22 |
this.apiBaseURL = 'https://x.mnitnetwork.com';
|
| 23 |
this.dataDir = path.join(__dirname, 'data');
|
| 24 |
this.rangesFile = path.join(this.dataDir, 'ranges.json');
|
|
|
|
| 37 |
this.consoleMonitorInterval = null;
|
| 38 |
this.lastConsoleId = 0;
|
| 39 |
this.consoleCheckCount = 0;
|
| 40 |
+
this.checkInterval = process.env.CHECK_INTERVAL ? parseInt(process.env.CHECK_INTERVAL) : 5000;
|
| 41 |
+
this.timeoutMinutes = process.env.TIMEOUT_MINUTES ? parseInt(process.env.TIMEOUT_MINUTES) : 30;
|
| 42 |
this.isProcessing = new Set();
|
| 43 |
this.userRangeRequests = new Map();
|
| 44 |
this.userOTPHistory = new Map();
|
| 45 |
+
this.consoleMonitorEnabled = process.env.AUTO_START_CONSOLE_MONITOR === 'true' || process.env.AUTO_START_CONSOLE_MONITOR === '1';
|
| 46 |
+
this.globalMonitorEnabled = process.env.AUTO_START_GLOBAL_MONITOR === 'true' || process.env.AUTO_START_GLOBAL_MONITOR === '1';
|
| 47 |
this.isGroupChatIdValid = false;
|
| 48 |
this.groupChatInfo = null;
|
| 49 |
this.isBulkProcessing = false;
|
|
|
|
| 53 |
this.consoleRangeCounts = new Map();
|
| 54 |
this.otpGroupSent = new Set();
|
| 55 |
this.consoleCheckInterval = 5000;
|
| 56 |
+
this.enablePing = process.env.ENABLE_PING === 'true' || process.env.ENABLE_PING === '1';
|
| 57 |
+
this.requiredGroups = process.env.REQUIRED_GROUPS ? JSON.parse(process.env.REQUIRED_GROUPS) : [];
|
| 58 |
|
| 59 |
// Express setup
|
| 60 |
this.expressApp = null;
|
| 61 |
this.server = null;
|
| 62 |
+
this.expressPort = process.env.PORT || process.env.EXPRESS_PORT || 7860;
|
| 63 |
this.isBotRunning = false;
|
| 64 |
+
this.domain = process.env.DOMAIN || `https://fourstore-tele.hf.space`;
|
| 65 |
+
this.authToken = process.env.AUTH_TOKEN || null;
|
| 66 |
+
|
| 67 |
+
// Validasi config penting
|
| 68 |
+
if (!this.botToken) {
|
| 69 |
+
console.error('β BOT_TOKEN is required in .env file');
|
| 70 |
+
process.exit(1);
|
| 71 |
+
}
|
| 72 |
}
|
| 73 |
|
| 74 |
async initialize() {
|
|
|
|
| 86 |
});
|
| 87 |
|
| 88 |
await this.bot.launch();
|
| 89 |
+
console.log('β
Bot started successfully');
|
| 90 |
+
console.log(`π€ Bot username: @${(await this.bot.telegram.getMe()).username}`);
|
| 91 |
this.isBotRunning = true;
|
| 92 |
|
| 93 |
await this.checkAndValidateGroupChatId();
|
|
|
|
| 102 |
startExpressServer() {
|
| 103 |
this.expressApp = express();
|
| 104 |
|
| 105 |
+
// Middleware untuk logging
|
| 106 |
+
this.expressApp.use((req, res, next) => {
|
| 107 |
+
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
|
| 108 |
+
next();
|
| 109 |
+
});
|
| 110 |
+
|
| 111 |
+
// Middleware untuk auth jika ada
|
| 112 |
+
if (this.authToken) {
|
| 113 |
+
this.expressApp.use((req, res, next) => {
|
| 114 |
+
const token = req.headers['authorization'] || req.query.token;
|
| 115 |
+
if (token === `Bearer ${this.authToken}` || token === this.authToken) {
|
| 116 |
+
next();
|
| 117 |
+
} else {
|
| 118 |
+
res.status(401).json({ error: 'Unauthorized' });
|
| 119 |
+
}
|
| 120 |
+
});
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
// Route untuk status bot
|
| 124 |
this.expressApp.get('/', (req, res) => {
|
| 125 |
const status = {
|
|
|
|
| 133 |
monitors: Array.from(this.activeMonitors.values()).reduce((sum, arr) => sum + arr.length, 0),
|
| 134 |
users: Object.keys(this.users || {}).length,
|
| 135 |
ranges: Object.keys(this.ranges || {}).length,
|
| 136 |
+
expressPort: this.expressPort,
|
| 137 |
+
domain: this.domain,
|
| 138 |
+
environment: process.env.NODE_ENV || 'development'
|
| 139 |
};
|
| 140 |
|
| 141 |
res.json(status);
|
|
|
|
| 147 |
const sessionStatus = this.sharedSession ? 'π’ ACTIVE' : 'π΄ NO SESSION';
|
| 148 |
const expiry = this.sharedSession ? new Date(this.sharedSession.expiry).toLocaleString() : 'N/A';
|
| 149 |
const balance = this.sharedSession ? this.sharedSession.balance : 'N/A';
|
| 150 |
+
const botUsername = this.bot ? this.bot.botInfo?.username : 'N/A';
|
| 151 |
|
| 152 |
const html = `
|
| 153 |
<!DOCTYPE html>
|
| 154 |
<html>
|
| 155 |
<head>
|
| 156 |
+
<title>Telegram OTP Bot - ${this.domain}</title>
|
| 157 |
<meta charset="UTF-8">
|
| 158 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 159 |
<style>
|
|
|
|
| 245 |
padding-top: 20px;
|
| 246 |
border-top: 1px solid #dee2e6;
|
| 247 |
}
|
| 248 |
+
.domain-info {
|
| 249 |
+
background: #e3f2fd;
|
| 250 |
+
border-radius: 8px;
|
| 251 |
+
padding: 15px;
|
| 252 |
+
margin-top: 20px;
|
| 253 |
+
text-align: center;
|
| 254 |
+
}
|
| 255 |
+
.bot-info {
|
| 256 |
+
background: #e8f5e9;
|
| 257 |
+
border-radius: 8px;
|
| 258 |
+
padding: 15px;
|
| 259 |
+
margin-top: 15px;
|
| 260 |
+
text-align: center;
|
| 261 |
+
}
|
| 262 |
</style>
|
| 263 |
<meta http-equiv="refresh" content="10">
|
| 264 |
</head>
|
| 265 |
<body>
|
| 266 |
<div class="container">
|
| 267 |
+
<h1>π€ Telegram OTP Bot</h1>
|
| 268 |
|
| 269 |
<div class="status-card">
|
| 270 |
<div class="status-item">
|
| 271 |
<span class="label">Bot Status:</span>
|
| 272 |
<span class="value ${this.isBotRunning ? 'online' : 'offline'}">${botStatus}</span>
|
| 273 |
</div>
|
| 274 |
+
<div class="status-item">
|
| 275 |
+
<span class="label">Bot Username:</span>
|
| 276 |
+
<span class="value">@${botUsername}</span>
|
| 277 |
+
</div>
|
| 278 |
<div class="status-item">
|
| 279 |
<span class="label">Session Status:</span>
|
| 280 |
<span class="value">${sessionStatus}</span>
|
|
|
|
| 312 |
</div>
|
| 313 |
</div>
|
| 314 |
|
| 315 |
+
<div class="bot-info">
|
| 316 |
+
<strong>π€ Bot Info:</strong><br>
|
| 317 |
+
@${botUsername}<br>
|
| 318 |
+
${this.adminIds.length} Admin(s)
|
| 319 |
+
</div>
|
| 320 |
+
|
| 321 |
+
<div class="domain-info">
|
| 322 |
+
<strong>π Domain:</strong> ${this.domain}<br>
|
| 323 |
+
<strong>π Environment:</strong> ${process.env.NODE_ENV || 'development'}
|
| 324 |
+
</div>
|
| 325 |
+
|
| 326 |
<div class="last-update">
|
| 327 |
Last updated: ${new Date().toLocaleString()}<br>
|
| 328 |
Auto-refresh every 10 seconds
|
|
|
|
| 337 |
|
| 338 |
// Route untuk health check
|
| 339 |
this.expressApp.get('/health', (req, res) => {
|
| 340 |
+
const healthStatus = {
|
| 341 |
+
status: this.isBotRunning ? 'healthy' : 'unhealthy',
|
| 342 |
bot: this.isBotRunning,
|
| 343 |
+
timestamp: new Date().toISOString(),
|
| 344 |
+
domain: this.domain,
|
| 345 |
+
uptime: process.uptime()
|
| 346 |
+
};
|
| 347 |
+
|
| 348 |
+
res.json(healthStatus);
|
| 349 |
});
|
| 350 |
|
| 351 |
// Route untuk info lengkap (JSON)
|
|
|
|
| 379 |
check_interval: this.checkInterval,
|
| 380 |
timeout_minutes: this.timeoutMinutes
|
| 381 |
},
|
| 382 |
+
config: {
|
| 383 |
+
send_to_group: this.sendToGroup,
|
| 384 |
+
enable_ping: this.enablePing,
|
| 385 |
+
required_groups_count: this.requiredGroups.length,
|
| 386 |
+
admin_count: this.adminIds.length
|
| 387 |
+
},
|
| 388 |
server: {
|
| 389 |
express_port: this.expressPort,
|
| 390 |
+
domain: this.domain,
|
| 391 |
uptime: process.uptime(),
|
| 392 |
+
memory_usage: process.memoryUsage(),
|
| 393 |
+
environment: process.env.NODE_ENV || 'development'
|
| 394 |
}
|
| 395 |
};
|
| 396 |
|
| 397 |
res.json(info);
|
| 398 |
});
|
| 399 |
|
| 400 |
+
// Route untuk webhook jika diperlukan
|
| 401 |
+
this.expressApp.post('/webhook', express.json(), (req, res) => {
|
| 402 |
+
console.log('Webhook received:', req.body);
|
| 403 |
+
res.json({ received: true });
|
| 404 |
+
});
|
| 405 |
+
|
| 406 |
+
// Route untuk ping (jika enable_ping true)
|
| 407 |
+
if (this.enablePing) {
|
| 408 |
+
this.expressApp.get('/ping', (req, res) => {
|
| 409 |
+
res.json({
|
| 410 |
+
pong: new Date().toISOString(),
|
| 411 |
+
bot: this.isBotRunning,
|
| 412 |
+
uptime: process.uptime()
|
| 413 |
+
});
|
| 414 |
+
});
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
// 404 handler
|
| 418 |
+
this.expressApp.use((req, res) => {
|
| 419 |
+
res.status(404).json({
|
| 420 |
+
error: 'Not Found',
|
| 421 |
+
available_routes: ['/', '/status', '/health', '/api/info', '/webhook'].concat(this.enablePing ? ['/ping'] : [])
|
| 422 |
+
});
|
| 423 |
+
});
|
| 424 |
+
|
| 425 |
+
// Error handler
|
| 426 |
+
this.expressApp.use((err, req, res, next) => {
|
| 427 |
+
console.error('Express error:', err);
|
| 428 |
+
res.status(500).json({ error: 'Internal Server Error' });
|
| 429 |
+
});
|
| 430 |
+
|
| 431 |
// Start server
|
| 432 |
+
this.server = this.expressApp.listen(this.expressPort, '0.0.0.0', () => {
|
| 433 |
+
console.log(`β
Express server running on port ${this.expressPort}`);
|
| 434 |
+
console.log(`π Status page: ${this.domain}/status`);
|
| 435 |
+
console.log(`π§ API endpoint: ${this.domain}/api/info`);
|
| 436 |
+
console.log(`β€οΈ Health check: ${this.domain}/health`);
|
| 437 |
+
if (this.enablePing) {
|
| 438 |
+
console.log(`π Ping endpoint: ${this.domain}/ping`);
|
| 439 |
+
}
|
| 440 |
+
console.log(`π Environment: ${process.env.NODE_ENV || 'development'}`);
|
| 441 |
});
|
| 442 |
|
| 443 |
// Handle server errors
|
|
|
|
| 488 |
const sessionData = await this.loadJSON(this.sessionFile);
|
| 489 |
if (sessionData) {
|
| 490 |
this.sharedSession = sessionData;
|
| 491 |
+
console.log('β
Session loaded');
|
| 492 |
} else {
|
| 493 |
+
console.log('β οΈ No session data found');
|
| 494 |
}
|
| 495 |
} catch (error) {
|
| 496 |
console.log('Error loading data:', error.message);
|
|
|
|
| 567 |
|
| 568 |
if (chatType === 'group' || chatType === 'supergroup') {
|
| 569 |
this.groupChatId = chatId.toString();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 570 |
|
| 571 |
await ctx.reply(
|
| 572 |
+
`β
*Group Chat ID Updated!*\n\nπ New Group ID: \`${chatId}\`\nπ·οΈ Title: ${chatTitle}`,
|
| 573 |
{ parse_mode: 'Markdown' }
|
| 574 |
);
|
| 575 |
|
|
|
|
| 1396 |
newFacebookCount++;
|
| 1397 |
this.lastConsoleId = logId;
|
| 1398 |
|
| 1399 |
+
if (this.groupChatId && this.sendToGroup) {
|
| 1400 |
await this.sendConsoleToGroup(log);
|
| 1401 |
}
|
| 1402 |
}
|
|
|
|
| 1409 |
newWhatsappCount++;
|
| 1410 |
this.lastConsoleId = logId;
|
| 1411 |
|
| 1412 |
+
if (this.groupChatId && this.sendToGroup) {
|
| 1413 |
await this.sendConsoleToGroup(log);
|
| 1414 |
}
|
| 1415 |
}
|
|
|
|
| 1445 |
|
| 1446 |
async sendConsoleToGroup(log) {
|
| 1447 |
try {
|
| 1448 |
+
if (!this.groupChatId || !this.sendToGroup) {
|
| 1449 |
return;
|
| 1450 |
}
|
| 1451 |
|
|
|
|
| 1891 |
|
| 1892 |
await this.sendOTPNotification(userId, status, targetNumber, rangeUsed);
|
| 1893 |
|
| 1894 |
+
if (this.groupChatId && this.sendToGroup) {
|
| 1895 |
await this.sendOTPToGroup(status, targetNumber, userId, rangeUsed);
|
| 1896 |
}
|
| 1897 |
|
|
|
|
| 1990 |
|
| 1991 |
async sendOTPToGroup(status, targetNumber, userId, rangeUsed) {
|
| 1992 |
try {
|
| 1993 |
+
if (!this.groupChatId || !this.sendToGroup) {
|
| 1994 |
return;
|
| 1995 |
}
|
| 1996 |
|
|
|
|
| 2126 |
this.lastCheckedIds.add(itemId);
|
| 2127 |
|
| 2128 |
const otp = this.extractOTP(item.otp || item.message);
|
| 2129 |
+
if (otp && this.groupChatId && this.sendToGroup) {
|
| 2130 |
await this.sendGlobalOTPToGroup(item, otp);
|
| 2131 |
}
|
| 2132 |
}
|
|
|
|
| 2143 |
|
| 2144 |
async sendGlobalOTPToGroup(item, otp) {
|
| 2145 |
try {
|
| 2146 |
+
if (!this.groupChatId || !this.sendToGroup) {
|
| 2147 |
return;
|
| 2148 |
}
|
| 2149 |
|
|
|
|
| 3009 |
const bot = new TelegramOTPBot();
|
| 3010 |
|
| 3011 |
const gracefulShutdown = () => {
|
| 3012 |
+
console.log('Shutting down gracefully...');
|
| 3013 |
+
|
| 3014 |
if (bot.bot) {
|
| 3015 |
bot.bot.stop();
|
| 3016 |
}
|
|
|
|
| 3048 |
});
|
| 3049 |
|
| 3050 |
bot.initialize().catch(error => {
|
| 3051 |
+
console.error('FAILED to initialize:', error);
|
| 3052 |
process.exit(1);
|
| 3053 |
});
|
package.json
CHANGED
|
@@ -11,10 +11,10 @@
|
|
| 11 |
"license": "ISC",
|
| 12 |
"type": "commonjs",
|
| 13 |
"dependencies": {
|
| 14 |
-
"
|
| 15 |
-
"express": "^
|
| 16 |
-
"
|
| 17 |
-
"node-cron": "^
|
| 18 |
-
"
|
| 19 |
}
|
| 20 |
-
}
|
|
|
|
| 11 |
"license": "ISC",
|
| 12 |
"type": "commonjs",
|
| 13 |
"dependencies": {
|
| 14 |
+
"telegraf": "^4.16.3",
|
| 15 |
+
"express": "^4.18.2",
|
| 16 |
+
"axios": "^1.6.2",
|
| 17 |
+
"node-cron": "^3.0.3",
|
| 18 |
+
"dotenv": "^16.3.1"
|
| 19 |
}
|
| 20 |
+
}
|