bsvp / bot /app.js
NexusV1's picture
Update bot/app.js
cbf0009 verified
Raw
History Blame Contribute Delete
11.7 kB
const fs = require('fs');
const path = require('path');
const { TelegramClient } = require('telegram');
const { StringSession } = require('telegram/sessions');
const { Api } = require('telegram');
const TelegramBot = require('node-telegram-bot-api');
const { Logger } = require('telegram/extensions');
const input = require('input');
// Custom logger implementation
class CustomLogger {
constructor(prefix) {
this.prefix = prefix;
}
log(level, message) {
// Implement your own logging if needed
// console.log(`[${this.prefix}] ${level}: ${message}`);
}
error(message) {
this.log('ERROR', message);
}
warn(message) {
this.log('WARN', message);
}
info(message) {
this.log('INFO', message);
}
debug(message) {
this.log('DEBUG', message);
}
}
// Bot token from environment
const BOT_TOKEN = process.env.BOT_TOKEN || '8019149324:AAGBAmRy0M-q6u0FqzREzwDtH-c5V-f9xoM';
// Create a new bot instance
const bot = new TelegramBot(BOT_TOKEN, { polling: true });
// Define conversation states
const STATES = {
IDLE: 'idle',
API_ID: 'api_id',
API_HASH: 'api_hash',
PHONE: 'phone',
CODE: 'code',
PASSWORD: 'password'
};
// Store user sessions and their current state
const userSessions = new Map();
// Validate phone number format
function isValidPhone(phone) {
return /^\+\d{10,15}$/.test(phone);
}
// Create a clean session object for a user
function createUserSession(userId) {
return {
userId,
state: STATES.IDLE,
apiId: null,
apiHash: null,
phone: null,
client: null,
sessionName: `aayco_${userId}`,
stringSession: null,
phoneCodeHash: null
};
}
// Clean up resources for a user session
async function cleanupSession(userId) {
const session = userSessions.get(userId);
if (!session) return;
try {
if (session.client) {
await session.client.disconnect();
}
// Remove session file if it exists
const sessionFile = `${session.sessionName}.session`;
if (fs.existsSync(sessionFile)) {
fs.unlinkSync(sessionFile);
}
} catch (error) {
console.error(`Error cleaning up session for user ${userId}:`, error);
} finally {
userSessions.delete(userId);
}
}
// Start command handler
bot.onText(/\/start/, async (msg) => {
const userId = msg.from.id;
await bot.sendMessage(userId,
"πŸ‘‹ Welcome to the Userbot Session Generator!\n\n" +
"Use /pair to start creating your session file.\n" +
"Use /cancel at any time to stop the process."
);
});
// Pair command handler
bot.onText(/\/pair/, async (msg) => {
const userId = msg.from.id;
// Check if user already has an active session
if (userSessions.has(userId)) {
const existingSession = userSessions.get(userId);
if (existingSession.state !== STATES.IDLE) {
await bot.sendMessage(userId,
"⚠️ You already have an active session process.\n" +
"Complete or /cancel it before starting a new one."
);
return;
}
}
// Create new session for user
const session = createUserSession(userId);
session.state = STATES.API_ID;
userSessions.set(userId, session);
await bot.sendMessage(userId,
"πŸ” Let's create your userbot session.\n" +
"Please provide your **API ID** (a number from my.telegram.org):\n" +
"Example: 1234567"
);
});
// Cancel command handler
bot.onText(/\/cancel/, async (msg) => {
const userId = msg.from.id;
if (userSessions.has(userId)) {
await cleanupSession(userId);
await bot.sendMessage(userId, "πŸ›‘ Session creation cancelled.");
} else {
await bot.sendMessage(userId, "There's no active session to cancel.");
}
});
// Handle all text messages
bot.on('message', async (msg) => {
if (msg.text && msg.text.startsWith('/')) return;
const userId = msg.from.id;
const text = msg.text?.trim();
if (!userSessions.has(userId) || !text) return;
const session = userSessions.get(userId);
try {
switch (session.state) {
case STATES.API_ID:
await handleApiId(userId, text);
break;
case STATES.API_HASH:
await handleApiHash(userId, text);
break;
case STATES.PHONE:
await handlePhone(userId, text);
break;
case STATES.CODE:
await handleCode(userId, text);
break;
case STATES.PASSWORD:
await handlePassword(userId, text);
break;
}
} catch (error) {
console.error(`Error handling message for user ${userId}:`, error);
await bot.sendMessage(userId,
`⚠️ An error occurred: ${error.message}\n` +
"Please try again with /pair."
);
await cleanupSession(userId);
}
});
// Process API ID input
async function handleApiId(userId, text) {
if (!text.match(/^\d+$/)) {
await bot.sendMessage(userId,
"❌ API ID must be a number.\n" +
"Please send a valid **API ID**:"
);
return;
}
const session = userSessions.get(userId);
session.apiId = parseInt(text, 10);
session.state = STATES.API_HASH;
await bot.sendMessage(userId,
"βœ… API ID received.\n" +
"Now provide your **API Hash** (a string from my.telegram.org):\n" +
"Example: abcdef1234567890abcdef1234567890"
);
}
// Process API Hash input
async function handleApiHash(userId, text) {
if (text.length < 32) {
await bot.sendMessage(userId,
"❌ API Hash must be at least 32 characters long.\n" +
"Please send a valid **API Hash**:"
);
return;
}
const session = userSessions.get(userId);
session.apiHash = text;
session.state = STATES.PHONE;
await bot.sendMessage(userId,
"βœ… API Hash received.\n" +
"Now provide your **phone number** (with country code):\n" +
"Example: +12025550123"
);
}
// Process phone number input
async function handlePhone(userId, phone) {
if (!isValidPhone(phone)) {
await bot.sendMessage(userId,
"❌ Invalid phone number format.\n" +
"Please send a valid phone number (e.g., +12025550123):"
);
return;
}
const session = userSessions.get(userId);
session.phone = phone;
try {
// Create a new StringSession
const stringSession = new StringSession("");
// Create a new TelegramClient with custom logger
const client = new TelegramClient(
stringSession,
session.apiId,
session.apiHash,
{
connectionRetries: 5,
baseLogger: new CustomLogger('GramJS'),
useWSS: false,
autoReconnect: true
}
);
session.client = client;
// Connect and send code
await client.connect();
const result = await client.invoke(
new Api.auth.SendCode({
phoneNumber: session.phone,
apiId: session.apiId,
apiHash: session.apiHash,
settings: new Api.CodeSettings({})
})
);
session.phoneCodeHash = result.phoneCodeHash;
session.state = STATES.CODE;
await bot.sendMessage(userId,
"βœ… Code request sent to your phone.\n" +
"Please enter the verification code you received:"
);
} catch (error) {
console.error('Error in handlePhone:', error);
let errorMessage = error.message;
if (error.errorMessage === 'PHONE_NUMBER_INVALID') {
errorMessage = "The phone number is invalid. Please check and try again.";
} else if (error.errorMessage === 'PHONE_NUMBER_BANNED') {
errorMessage = "This phone number is banned from Telegram.";
} else if (error.errorMessage.includes('FLOOD')) {
errorMessage = "Too many attempts. Please wait before trying again.";
}
await bot.sendMessage(userId,
`❌ Error sending code: ${errorMessage}\n` +
"Please try again with /pair or contact support."
);
await cleanupSession(userId);
}
}
// Process verification code input
async function handleCode(userId, code) {
if (!code.match(/^\d+$/)) {
await bot.sendMessage(userId,
"❌ Code must be a number.\n" +
"Please enter the verification code:"
);
return;
}
const session = userSessions.get(userId);
try {
// Sign in with the code
const result = await session.client.invoke(
new Api.auth.SignIn({
phoneNumber: session.phone,
phoneCodeHash: session.phoneCodeHash,
phoneCode: code
})
);
if (result._ === 'auth.authorizationSignUpRequired') {
throw new Error("This phone number is not registered. Please sign up first.");
}
await finishSession(userId);
} catch (error) {
console.error('Error in handleCode:', error);
if (error.errorMessage === "SESSION_PASSWORD_NEEDED") {
session.state = STATES.PASSWORD;
await bot.sendMessage(userId,
"πŸ”’ Your account has two-factor authentication enabled.\n" +
"Please enter your 2FA password:"
);
} else {
let errorMessage = error.message;
if (error.errorMessage === 'PHONE_CODE_INVALID') {
errorMessage = "The verification code is invalid.";
} else if (error.errorMessage === 'PHONE_CODE_EXPIRED') {
errorMessage = "The verification code has expired. Please request a new one.";
}
await bot.sendMessage(userId,
`❌ Sign-in failed: ${errorMessage}\n` +
"Please try again with /pair."
);
await cleanupSession(userId);
}
}
}
// Process 2FA password input
async function handlePassword(userId, password) {
const session = userSessions.get(userId);
try {
// Sign in with 2FA password
await session.client.invoke(
new Api.auth.CheckPassword({
password: password
})
);
await finishSession(userId);
} catch (error) {
console.error('Error in handlePassword:', error);
let errorMessage = error.message;
if (error.errorMessage === 'PASSWORD_HASH_INVALID') {
errorMessage = "The 2FA password is incorrect.";
}
await bot.sendMessage(userId,
`❌ 2FA authentication failed: ${errorMessage}\n` +
"Please try again with /pair."
);
await cleanupSession(userId);
}
}
// Complete the session creation and send the file
async function finishSession(userId) {
const session = userSessions.get(userId);
try {
await bot.sendMessage(userId,
"πŸŽ‰ Successfully signed in!\n" +
"Generating your session file..."
);
const sessionString = session.client.session.save();
const sessionFile = `aayco_${userId}.session`;
fs.writeFileSync(sessionFile, sessionString);
await bot.sendDocument(userId, sessionFile, {
caption: "Here's your session file for your userbot. Keep it safe!",
filename: 'aayco.session'
});
await cleanupSession(userId);
} catch (error) {
console.error('Error in finishSession:', error);
await bot.sendMessage(userId,
`❌ Error creating session file: ${error.message}\n` +
"Please try again with /pair."
);
await cleanupSession(userId);
}
}
// Start the bot
console.log("Starting bot...");
// Error handling
bot.on('polling_error', (error) => {
console.error('Polling error:', error);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});
// Graceful shutdown
process.on('SIGINT', async () => {
console.log('Shutting down...');
for (const [userId, session] of userSessions.entries()) {
try {
await cleanupSession(userId);
} catch (error) {
console.error(`Error cleaning up session for user ${userId}:`, error);
}
}
bot.stopPolling();
process.exit(0);
});