Skip to content

Commit

Permalink
added events and new stalk command also help updated
Browse files Browse the repository at this point in the history
  • Loading branch information
1dev-hridoy committed Nov 22, 2024
1 parent 47c088f commit 63dc53c
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 71 deletions.
39 changes: 34 additions & 5 deletions bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ const chalk = require('chalk');
const { connectToDatabase } = require('./db');
const schedule = require('node-schedule');
const { updateUserXP } = require('./commands/rank');
const fetch = require('node-fetch');

const bot = new TelegramBot(process.env.BOT_TOKEN, { polling: true });

// Load commands
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));

Expand All @@ -21,6 +23,18 @@ for (const file of commandFiles) {

bot.commands = commands;

// Load event handlers
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));

const events = {};

for (const file of eventFiles) {
const event = require(path.join(eventsPath, file));
events[event.name] = event;
}

// Utility functions
function rainbowText(text) {
const colors = ['red', 'magenta', 'blue', 'cyan', 'green', 'yellow'];
return text.split('').map((char, i) => {
Expand Down Expand Up @@ -208,10 +222,23 @@ async function startBot() {
const chatId = msg.chat.id;
const groupName = msg.chat.title;
const memberCount = await bot.getChatMemberCount(chatId);

for (const newMember of msg.new_chat_members) {
await welcome.execute(bot, newMember, groupName, memberCount)
.catch(error => console.error('Error executing welcome:', error));
if (events.welcome) {
await events.welcome.execute(bot, msg, groupName, memberCount)
.catch(error => console.error('Error executing welcome:', error));
}
}
});

bot.on('left_chat_member', async (msg) => {
const chatId = msg.chat.id;
const groupName = msg.chat.title;
const memberCount = await bot.getChatMemberCount(chatId);

if (events.goodbye) {
await events.goodbye.execute(bot, msg, groupName, memberCount)
.catch(error => console.error('Error executing goodbye:', error));
}
});

Expand All @@ -220,8 +247,10 @@ async function startBot() {
const groupName = msg.chat.title;
const memberCount = await bot.getChatMemberCount(chatId);

await goodbye.execute(bot, msg.left_chat_member, groupName, memberCount)
.catch(error => console.error('Error executing goodbye:', error));
if (events.goodbye) {
await events.goodbye.execute(bot, msg.left_chat_member, groupName, memberCount)
.catch(error => console.error('Error executing goodbye:', error));
}
});

bot.on('left_chat_participant', async (msg) => {
Expand Down
137 changes: 71 additions & 66 deletions commands/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,87 +5,92 @@ module.exports = {
adminOnly: false,
ownerOnly: false,
category: 'Utility',
description: 'Show all commands or info about a specific command',
guide: 'Use /help for all commands, /help <category> for category commands, or /help <command> for specific info',
execute: async (bot, msg, args, db) => {
description: 'Show all available commands',
guide: 'Use /help to see all commands',
execute: async (bot, msg) => {
const chatId = msg.chat.id;
const commands = bot.commands;

if (!commands) {
return bot.sendMessage(chatId, 'Error: Commands not properly loaded. Please contact the bot administrator.');
return bot.sendMessage(chatId, 'Error: Commands not available. Please try again later.');
}

if (args.length === 0) {
// Show all categories
let helpMessage = '*Command Categories:*\n\n';
const categories = new Set();

// Safely collect categories
Object.values(commands).forEach(cmd => {
if (cmd && cmd.category) {
categories.add(cmd.category);
const createCommandList = (cmds) => {
const categories = {};
Object.entries(cmds).forEach(([name, cmd]) => {
if (!categories[cmd.category]) {
categories[cmd.category] = [];
}
categories[cmd.category].push(name);
});

if (categories.size === 0) {
categories.add('Uncategorized');
}

categories.forEach(category => {
helpMessage += `/${category.toLowerCase()} - ${category} commands\n`;
});

helpMessage += '\nUse /help <category> to see commands in a specific category.';
helpMessage += '\nUse /help <command> for more information on a specific command.';
helpMessage += `\n\nTotal commands: ${Object.keys(commands).length}`;

await bot.sendMessage(chatId, helpMessage, { parse_mode: 'Markdown' });
} else {
const searchTerm = args[0].toLowerCase();
const categoryCommands = Object.entries(commands).filter(([_, cmd]) =>
cmd && cmd.category && cmd.category.toLowerCase() === searchTerm
);
let commandList = '';
for (const [category, cmds] of Object.entries(categories)) {
commandList += `╭───✿ ${category}\n`;
for (let i = 0; i < cmds.length; i += 2) {
commandList += `│♡${cmds[i]}${cmds[i+1] ? ` ♡${cmds[i+1]}` : ''}\n`;
}
commandList += `╰───────────✿\n`;
}
return commandList;
};

if (categoryCommands.length > 0) {
// Show commands for a specific category
let helpMessage = `*${searchTerm.charAt(0).toUpperCase() + searchTerm.slice(1)} Commands:*\n\n`;

categoryCommands.forEach(([name, command]) => {
helpMessage += `/${name} - ${command.description || 'No description available'}\n`;
});
const getBotInfo = async () => {
try {
const botInfo = await bot.getMe();
const ownerId = process.env.OWNER_ID;
let ownerName = 'Unknown';

helpMessage += '\nUse /help <command> for more information on a specific command.';
helpMessage += `\n\nTotal ${searchTerm} commands: ${categoryCommands.length}`;
helpMessage += `\nTotal commands: ${Object.keys(commands).length}`;
if (ownerId) {
try {
const chatMember = await bot.getChatMember(ownerId, ownerId);
ownerName = chatMember.user.first_name || 'Unknown';
} catch (error) {
console.error('Error fetching owner info:', error);
}
}

await bot.sendMessage(chatId, helpMessage, { parse_mode: 'Markdown' });
} else {
// Show info for a specific command
const command = commands[searchTerm];
return `Nexalo ♡\nMy sensei\n${ownerName}\nfb.com/hridoy.py`;
} catch (error) {
console.error('Error fetching bot info:', error);
return 'Unable to fetch bot and owner information.';
}
};

if (command) {
const helpMessage = `*/${searchTerm}*\n\n` +
`Description: ${command.description || 'No description available'}\n` +
`Category: ${command.category || 'Uncategorized'}\n` +
`Usage: ${command.guide || 'No usage guide available'}\n` +
`Admin Only: ${command.adminOnly ? 'Yes' : 'No'}\n` +
`Owner Only: ${command.ownerOnly ? 'Yes' : 'No'}\n\n` +
`Total commands: ${Object.keys(commands).length}`;
try {
const commandList = createCommandList(commands);
const botInfo = await getBotInfo();
const totalCommands = Object.keys(commands).length;

await bot.sendMessage(chatId, helpMessage, { parse_mode: 'Markdown' });
} else {
const similarCommands = Object.keys(commands).filter(cmd => cmd.includes(searchTerm));
let errorMessage = `Command /${searchTerm} not found. Use /help to see all available categories.`;

if (similarCommands.length > 0) {
errorMessage += '\n\nDid you mean:\n' + similarCommands.map(cmd => `/${cmd}`).join('\n');
}
const finalMessage = `${commandList}
╭───✿ SUPPORT GC
│If you don't know how to
│use Nexalo or face any
│problem then please join
│Nino ♡ Nexalo Support gc by click the below button
├──────────✿
├─────✿
│» Total Cmds ${totalCommands} cmds.
│» Type /help <cmd> to learn
│how to use the command.
├─────✿
${botInfo}
╰─────────────✿`;

errorMessage += `\n\nTotal commands: ${Object.keys(commands).length}`;
const keyboard = {
inline_keyboard: [
[{ text: 'Join Support Group', url: 'https://t.me/example_support_group' }]
]
};

await bot.sendMessage(chatId, errorMessage);
}
}
await bot.sendMessage(chatId, finalMessage, {
parse_mode: 'Markdown',
reply_markup: JSON.stringify(keyboard)
});
} catch (error) {
console.error('Error in help command:', error);
await bot.sendMessage(chatId, 'An error occurred while fetching the help information. Please try again later.');
}
}
};
};

55 changes: 55 additions & 0 deletions commands/stalk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const { escapeMarkdown } = require('../utils/markdown');

module.exports = {
name: 'stalk',
adminOnly: false,
ownerOnly: false,
category: 'Utility',
description: 'Show user information',
guide: 'Use /stalk to see your own info, or reply to a message with /stalk to see that user\'s info',
execute: async (bot, msg) => {
const chatId = msg.chat.id;
let targetUser;

if (msg.reply_to_message) {
targetUser = msg.reply_to_message.from;
} else {
targetUser = msg.from;
}

try {
const userInfo = await bot.getUserProfilePhotos(targetUser.id, 0, 1);
const chatMember = await bot.getChatMember(chatId, targetUser.id);

const createUserInfo = (user) => {
const fullName = escapeMarkdown(`${user.first_name || ''} ${user.last_name || ''}`.trim());
const username = user.username ? escapeMarkdown(`@${user.username}`) : 'Not set';
const userLink = `tg://user?id=${user.id}`;
const bio = escapeMarkdown(chatMember.user.bio || 'Not available');

return `*User Information*
🆔 *User ID:* \`${user.id}\`
👤 *Full Name:* ${fullName}
🌟 *Username:* ${username}
📝 *Bio:* ${bio}
🔗 *Contact:* [${fullName}](${userLink})`;
};

const userInfoText = createUserInfo(targetUser);

if (userInfo && userInfo.photos && userInfo.photos.length > 0) {
const photo = userInfo.photos[0][0];
await bot.sendPhoto(chatId, photo.file_id, {
caption: userInfoText,
parse_mode: 'Markdown'
});
} else {
await bot.sendMessage(chatId, userInfoText, { parse_mode: 'Markdown' });
}
} catch (error) {
console.error('Error in stalk command:', error);
await bot.sendMessage(chatId, 'An error occurred while fetching user information. Please try again later.');
}
}
};

49 changes: 49 additions & 0 deletions events/goodbye.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const fetch = require('node-fetch');

async function execute(bot, msg, groupName, memberCount) {
const chatId = msg.chat.id;
const leftMember = msg.left_chat_member;
const username = leftMember.username || leftMember.first_name || 'User';
const userId = leftMember.id;

// Get user's profile photos
let userProfilePhoto = 'https://nexalo.xyz/assets/nexa.png'; // Default image
try {
const userPhotos = await bot.getUserProfilePhotos(userId, 0, 1);
if (userPhotos.total_count > 0) {
const fileId = userPhotos.photos[0][0].file_id;
const file = await bot.getFile(fileId);
userProfilePhoto = `https://api.telegram.org/file/bot${bot.token}/${file.file_path}`;
}
} catch (error) {
console.error('Error getting user profile photo:', error);
}

try {
// Fetch the goodbye image from the API
const apiUrl = `https://api.nexalo.xyz/goodbye?api=na_T51VHMGBMZJO7S2B&name=${encodeURIComponent(username)}&text=${encodeURIComponent(`Goodbye ${username}`)}&image=${encodeURIComponent(userProfilePhoto)}`;
const response = await fetch(apiUrl);
const imageBuffer = await response.buffer();

// Create a mention of the user
const userMention = `<a href="tg://user?id=${userId}">${username}</a>`;

// Send the goodbye message with the image and user mention
await bot.sendPhoto(chatId, imageBuffer, {
caption: `Goodbye, ${userMention}! 👋\nWe're sad to see you go. You were our ${memberCount + 1}th member.\n\nWe hope you enjoyed your time in ${groupName} and wish you all the best!`,
parse_mode: 'HTML'
});
} catch (error) {
console.error('Error in goodbye event:', error);
// Send a text-only goodbye message as fallback, still with user mention
const userMention = `<a href="tg://user?id=${userId}">${username}</a>`;
await bot.sendMessage(chatId, `Goodbye, ${userMention}! 👋\nWe're sad to see you go. You were our ${memberCount + 1}th member.\n\nWe hope you enjoyed your time in ${groupName} and wish you all the best!`, {
parse_mode: 'HTML'
});
}
}

module.exports = {
name: 'goodbye',
execute
};
36 changes: 36 additions & 0 deletions events/welcome.js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const fetch = require('node-fetch');

async function execute(bot, msg, groupName, memberCount) {
const chatId = msg.chat.id;
const newMember = msg.new_chat_member;
const username = newMember.username || newMember.first_name || 'New member';
const userId = newMember.id;

try {
// Fetch the welcome image from the API
const apiUrl = `https://api.nexalo.xyz/welcome_v2?api=na_T51VHMGBMZJO7S2B&name=${encodeURIComponent(username)}&text=${encodeURIComponent(`Welcome to ${groupName}`)}`;
const response = await fetch(apiUrl);
const imageBuffer = await response.buffer();

// Create a mention of the user
const userMention = `<a href="tg://user?id=${userId}">${username}</a>`;

// Send the welcome message with the image and user mention
await bot.sendPhoto(chatId, imageBuffer, {
caption: `Welcome to ${groupName}, ${userMention}! 🎉\nYou're our ${memberCount}th member! 🌟\n\nWe're excited to have you join us. Feel free to introduce yourself and join the conversation!`,
parse_mode: 'HTML'
});
} catch (error) {
console.error('Error in welcome event:', error);
// Send a text-only welcome message as fallback, still with user mention
const userMention = `<a href="tg://user?id=${userId}">${username}</a>`;
await bot.sendMessage(chatId, `Welcome to ${groupName}, ${userMention}! 🎉\nYou're our ${memberCount}th member! 🌟\n\nWe're excited to have you join us. Feel free to introduce yourself and join the conversation!`, {
parse_mode: 'HTML'
});
}
}

module.exports = {
name: 'welcome',
execute
};
9 changes: 9 additions & 0 deletions utils/markdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function escapeMarkdown(text) {
return text.replace(/[_*[\]()~`>#+=|{}.!-]/g, '\\$&');
}

module.exports = {
escapeMarkdown
};


0 comments on commit 63dc53c

Please sign in to comment.