Moved everything to /src

This commit is contained in:
Luquinhas 2024-12-08 19:55:35 -03:00
parent dec0390280
commit 1072b641c8
29 changed files with 10 additions and 2 deletions

64
src/commands/admin.js Normal file
View file

@ -0,0 +1,64 @@
const Config = require('../props/config.json');
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
async function collectInfo(ctx) {
const Strings = getStrings(ctx.from.language_code);
const chatId = ctx.chat.id || Strings.unKnown;
const adminId = ctx.from.id || Strings.unKnown;
const userId = parseInt(ctx.message.text.split(' ')[1], 10);
const admins = await ctx.telegram.getChatAdministrators(chatId);
const isAdmin = admins.some(admin => admin.user.id === adminId);
const onCrew = Config.admins.includes(adminId);
return { Strings, chatId, userId, isAdmin, onCrew };
}
async function handleMember(ctx, action, successMessage, errorMessage) {
const { Strings, chatId, userId, isAdmin, onCrew } = await collectInfo(ctx);
if (onCrew || isAdmin) {
if (isNaN(userId)) {
return ctx.reply(Strings.invalidId, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
try {
await action(chatId, userId);
const report = successMessage.replace('{userId}', userId);
ctx.reply(report, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (err) {
const error = errorMessage.replace('{tgErr}', err.message);
ctx.reply(error, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
} else {
ctx.reply(Strings.noPermission, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
}
module.exports = (bot) => {
bot.command('ban', spamwatchMiddleware, (ctx) => {
handleMember(ctx, (chatId, userId) => ctx.telegram.kickChatMember(chatId, userId),
getStrings(ctx.from.language_code).banSuccess,
getStrings(ctx.from.language_code).banErr
);
});
bot.command('unban', spamwatchMiddleware, (ctx) => {
handleMember(ctx, (chatId, userId) => ctx.telegram.unbanChatMember(chatId, userId),
getStrings(ctx.from.language_code).unBanSuccess,
getStrings(ctx.from.language_code).unBanErr
);
});
};

67
src/commands/cat.js Normal file
View file

@ -0,0 +1,67 @@
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require('axios');
module.exports = (bot) => {
// bot.command("cat", spamwatchMiddleware, async (ctx) => {
// const Strings = getStrings(ctx.from.language_code);
// const userInput = ctx.message.text.split(' ').slice(1).join(' ').replace(/\s+/g, '');
// let request = "";
// if (userInput && userInput.includes("gif")) {
// request = `/gif${userInput.replace("gif", "")}`;
// const apiUrl = `https://cataas.com/cat${request}`;
// try {
// await ctx.replyWithAnimation(apiUrl, {
// caption: `🐱`,
// parse_mode: 'Markdown',
// reply_to_message_id: ctx.message.message_id
// });
// } catch (error) {
// ctx.reply(Strings.catGifErr, {
// parse_mode: 'Markdown',
// reply_to_message_id: ctx.message.message_id
// });
// };
// } else {
// request = userInput ? `/${userInput}` : '';
// const apiUrl = `https://cataas.com/cat${request}`;
// try {
// await ctx.replyWithPhoto(apiUrl, {
// caption: `🐱`,
// parse_mode: 'Markdown',
// reply_to_message_id: ctx.message.message_id
// });
// } catch (error) {
// ctx.reply(Strings.catImgErr, {
// parse_mode: 'Markdown',
// reply_to_message_id: ctx.message.message_id
// });
// };
// };
// });
bot.command("cat", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const apiUrl = "https://cataas.com/cat?json=true";
const response = await axios.get(apiUrl);
const data = response.data;
const imageUrl = `https://cataas.com/cat/${data._id}`;
try {
await ctx.replyWithPhoto(imageUrl, {
caption: `🐱`,
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
ctx.reply(Strings.catImgErr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
});
};

223
src/commands/crew.js Normal file
View file

@ -0,0 +1,223 @@
const Config = require('../props/config.json');
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const os = require('os');
const { exec } = require('child_process');
const { error } = require('console');
function getGitCommitHash() {
return new Promise((resolve, reject) => {
exec('git rev-parse --short HEAD', (error, stdout, stderr) => {
if (error) {
reject(`Error: ${stderr}`);
} else {
resolve(stdout.trim());
}
});
});
}
function updateBot() {
return new Promise((resolve, reject) => {
exec('git pull && echo "A" >> restart.txt', (error, stdout, stderr) => {
if (error) {
reject(`Error: ${stderr}`);
} else {
resolve(stdout.trim());
}
});
});
}
function formatUptime(uptime) {
const hours = Math.floor(uptime / 3600);
const minutes = Math.floor((uptime % 3600) / 60);
const seconds = Math.floor(uptime % 60);
return `${hours}h ${minutes}m ${seconds}s`;
}
function getSystemInfo() {
const { platform, release, arch, cpus, totalmem, freemem, loadavg, uptime } = os;
const [cpu] = cpus();
return `*Server Stats*\n\n` +
`*OS:* \`${platform()} ${release()}\`\n` +
`*Arch:* \`${arch()}\`\n` +
`*Node.js Version:* \`${process.version}\`\n` +
`*CPU:* \`${cpu.model}\`\n` +
`*CPU Cores:* \`${cpus().length} cores\`\n` +
`*RAM:* \`${(freemem() / (1024 ** 3)).toFixed(2)} GB / ${(totalmem() / (1024 ** 3)).toFixed(2)} GB\`\n` +
`*Load Average:* \`${loadavg().map(avg => avg.toFixed(2)).join(', ')}\`\n` +
`*Uptime:* \`${formatUptime(uptime())}\`\n\n`;
}
async function handleAdminCommand(ctx, action, successMessage, errorMessage) {
const Strings = getStrings(ctx.from.language_code);
const userId = ctx.from.id;
if (Config.admins.includes(userId)) {
try {
await action();
ctx.reply(successMessage, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
ctx.reply(errorMessage.replace('{error}', error.message), {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
} else {
ctx.reply(Strings.botAdminOnly, {
reply_to_message_id: ctx.message.message_id
});
}
}
module.exports = (bot) => {
bot.command('getbotstats', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
handleAdminCommand(ctx, async () => {
const stats = getSystemInfo();
await ctx.reply(stats, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}, '', Strings.errorRetrievingStats);
});
bot.command('getbotcommit', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
handleAdminCommand(ctx, async () => {
try {
const commitHash = await getGitCommitHash();
await ctx.reply(Strings.currentCommit.replace('{commitHash}', commitHash), {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
ctx.reply(Strings.errorRetrievingCommit.replace('{error}', error), {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
}, '', Strings.errorRetrievingCommit);
});
bot.command('updatebot', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
handleAdminCommand(ctx, async () => {
try {
const result = await updateBot();
await ctx.reply(Strings.botUpdated.replace('{result}', result), {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
ctx.reply(Strings.errorUpdatingBot.replace('{error}', error), {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
}, '', Strings.errorUpdatingBot);
});
bot.command('setbotname', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const botName = ctx.message.text.split(' ').slice(1).join(' ');
handleAdminCommand(ctx, async () => {
await ctx.telegram.setMyName(botName);
}, Strings.botNameChanged.replace('{botName}', botName), Strings.botNameErr.replace('{error}', error));
});
bot.command('setbotdesc', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const botDesc = ctx.message.text.split(' ').slice(1).join(' ');
handleAdminCommand(ctx, async () => {
await ctx.telegram.setMyDescription(botDesc);
}, Strings.botDescChanged.replace('{botDesc}', botDesc), Strings.botDescErr.replace('{error}', error));
});
bot.command('botkickme', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
handleAdminCommand(ctx, async () => {
ctx.reply(Strings.kickingMyself, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
await ctx.telegram.leaveChat(ctx.chat.id);
}, '', Strings.kickingMyselfErr);
});
bot.command('getfile', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const botFile = ctx.message.text.split(' ').slice(1).join(' ');
handleAdminCommand(ctx, async () => {
try {
await ctx.replyWithDocument({
source: botFile,
caption: botFile
});
} catch (error) {
ctx.reply(Strings.fileError.replace('{error}', error.message), {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
}, '', Strings.fileError);
});
bot.command('run', spamwatchMiddleware, async (ctx) => {
const command = ctx.message.text.split(' ').slice(1).join(' ');
handleAdminCommand(ctx, async () => {
if (!command) {
return ctx.reply('Por favor, forneça um comando para executar.');
}
exec(command, (error, stdout, stderr) => {
if (error) {
return ctx.reply(`\`${error.message}\``, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
if (stderr) {
return ctx.reply(`\`${stderr}\``, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
ctx.reply(`\`${stdout}\``, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
});
}, '', "Nope!");
});
bot.command('eval', spamwatchMiddleware, async (ctx) => {
const code = ctx.message.text.split(' ').slice(1).join(' ');
if (!code) {
return ctx.reply('Por favor, forneça um código para avaliar.');
}
try {
const result = eval(code);
ctx.reply(`Result: ${result}`, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
ctx.reply(`Error: ${error.message}`, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
});
bot.command('crash', spamwatchMiddleware, async (ctx) => {
handleAdminCommand(ctx, async () => {
ctx.reply(null);
}, '', "Nope!");
});
};

26
src/commands/dog.js Normal file
View file

@ -0,0 +1,26 @@
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require('axios');
module.exports = (bot) => {
bot.command("dog", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const apiUrl = "https://dog.ceo/api/breeds/image/random";
const response = await axios.get(apiUrl);
const data = response.data;
try {
await ctx.replyWithPhoto(data.message, {
caption: `🐶`,
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
ctx.reply(Strings.dogImgErr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
});
};

139
src/commands/fun.js Normal file
View file

@ -0,0 +1,139 @@
const resources = require('../props/resources.json');
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
function sendRandomReply(ctx, gifUrl, textKey, notTextKey) {
const Strings = getStrings(ctx.from.language_code);
const shouldSendGif = Math.random() < 0.5;
if (shouldSendGif) {
ctx.replyWithAnimation(gifUrl, {
caption: Strings[textKey],
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
}).catch(err => {
gifErr = gifErr.replace('{err}', err);
ctx.reply(Strings.gifErr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
});
} else {
ctx.reply(Strings[notTextKey], {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
}
async function handleDiceCommand(ctx, emoji, delay) {
const Strings = getStrings(ctx.from.language_code);
const result = await ctx.sendDice({ emoji, reply_to_message_id: ctx.message.message_id });
const botResponse = Strings.funEmojiResult
.replace('{emoji}', result.dice.emoji)
.replace('{value}', result.dice.value);
setTimeout(() => {
ctx.reply(botResponse, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}, delay);
}
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
module.exports = (bot) => {
bot.command('random', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const randomValue = getRandomInt(11);
const randomVStr = Strings.randomNum.replace('{number}', randomValue);
ctx.reply(
randomVStr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
});
bot.command('dice', spamwatchMiddleware, async (ctx) => {
await handleDiceCommand(ctx, undefined, 4000);
});
bot.command('slot', spamwatchMiddleware, async (ctx) => {
await handleDiceCommand(ctx, '🎰', 3000);
});
bot.command('ball', spamwatchMiddleware, async (ctx) => {
await handleDiceCommand(ctx, '⚽', 3000);
});
bot.command('dart', spamwatchMiddleware, async (ctx) => {
await handleDiceCommand(ctx, '🎯', 3000);
});
bot.command('bowling', spamwatchMiddleware, async (ctx) => {
await handleDiceCommand(ctx, '🎳', 3000);
});
bot.command('idice', spamwatchMiddleware, async (ctx) => {
ctx.replyWithSticker(
resources.infiniteDice, {
reply_to_message_id: ctx.message.message_id
});
});
bot.command('furry', spamwatchMiddleware, async (ctx) => {
sendRandomReply(ctx, resources.furryGif, 'isFurry', 'isNtFurry');
});
bot.command('gay', spamwatchMiddleware, async (ctx) => {
sendRandomReply(ctx, resources.gayFlag, 'isGay', 'isNtGay');
});
bot.command('soggy', spamwatchMiddleware, async (ctx) => {
const userInput = ctx.message.text.split(' ')[1];
switch (true) {
case (userInput === "2" || userInput === "thumb"):
ctx.replyWithPhoto(
resources.soggyCat2, {
caption: resources.soggyCat2,
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
break;
case (userInput === "3" || userInput === "sticker"):
ctx.replyWithSticker(
resources.soggyCatSticker, {
reply_to_message_id: ctx.message.message_id
});
break;
case (userInput === "4" || userInput === "alt"):
ctx.replyWithPhoto(
resources.soggyCatAlt, {
caption: resources.soggyCatAlt,
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
break;
default:
ctx.replyWithPhoto(
resources.soggyCat, {
caption: resources.soggyCat,
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
break;
};
});
};

245
src/commands/gsmarena.js Normal file
View file

@ -0,0 +1,245 @@
// Ported and improved from Hitalo's PyKorone bot
// Copyright (c) 2024 Hitalo M. (https://github.com/HitaloM)
// Original code license: BSD-3-Clause
// With some help from GPT (I don't really like AI but whatever)
// If this were a kang, I would not be giving credits to him!
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require('axios');
const { parse } = require('node-html-parser');
class PhoneSearchResult {
constructor(name, url) {
this.name = name;
this.url = url;
Object.freeze(this);
}
}
const HEADERS = {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
};
function getDataFromSpecs(specsData, category, attributes) {
const details = specsData?.specs?.[category] || {};
return attributes
.map(attr => details[attr] || null)
.filter(Boolean)
.join("\n");
}
function parseSpecs(specsData) {
const categories = {
"status": ["Launch", ["Status"]],
"network": ["Network", ["Technology"]],
"system": ["Platform", ["OS"]],
"models": ["Misc", ["Models"]],
"weight": ["Body", ["Weight"]],
"jack": ["Sound", ["3.5mm jack"]],
"usb": ["Comms", ["USB"]],
"sensors": ["Features", ["Sensors"]],
"battery": ["Battery", ["Type"]],
"charging": ["Battery", ["Charging"]],
"display_type": ["Display", ["Type"]],
"display_size": ["Display", ["Size"]],
"display_resolution": ["Display", ["Resolution"]],
"platform_chipset": ["Platform", ["Chipset"]],
"platform_cpu": ["Platform", ["CPU"]],
"platform_gpu": ["Platform", ["GPU"]],
"memory": ["Memory", ["Internal"]],
"main_camera_single": ["Main Camera", ["Single"]],
"main_camera_dual": ["Main Camera", ["Dual"]],
"main_camera_triple": ["Main Camera", ["Triple"]],
"main_camera_quad": ["Main Camera", ["Quad"]],
"main_camera_features": ["Main Camera", ["Features"]],
"main_camera_video": ["Main Camera", ["Video"]],
"selfie_camera_single": ["Selfie Camera", ["Single"]],
"selfie_camera_dual": ["Selfie Camera", ["Dual"]],
"selfie_camera_triple": ["Selfie Camera", ["Triple"]],
"selfie_camera_quad": ["Selfie Camera", ["Quad"]],
"selfie_camera_features": ["Selfie Camera", ["Features"]],
"selfie_camera_video": ["Selfie Camera", ["Video"]]
};
const parsedData = Object.keys(categories).reduce((acc, key) => {
const [cat, attrs] = categories[key];
acc[key] = getDataFromSpecs(specsData, cat, attrs) || "";
return acc;
}, {});
parsedData["name"] = specsData.name || "";
parsedData["url"] = specsData.url || "";
return parsedData;
}
function formatPhone(phone) {
const formattedPhone = parseSpecs(phone);
const attributesDict = {
"Status": "status",
"Network": "network",
"OS": "system",
"Models": "models",
"Weight": "weight",
"3.5mm jack": "jack",
"USB": "usb",
"Sensors": "sensors",
"Battery": "battery",
"Charging": "charging",
"Display Type": "display_type",
"Display Size": "display_size",
"Display Resolution": "display_resolution",
"Chipset": "platform_chipset",
"CPU": "platform_cpu",
"GPU": "platform_gpu",
"Memory": "memory",
"Rear Camera (Single)": "main_camera_single",
"Rear Camera (Dual)": "main_camera_dual",
"Rear Camera (Triple)": "main_camera_triple",
"Rear Camera (Quad)": "main_camera_quad",
"Rear Camera (Features)": "main_camera_features",
"Rear Camera (Video)": "main_camera_video",
"Front Camera (Single)": "selfie_camera_single",
"Front Camera (Dual)": "selfie_camera_dual",
"Front Camera (Triple)": "selfie_camera_triple",
"Front Camera (Quad)": "selfie_camera_quad",
"Front Camera (Features)": "selfie_camera_features",
"Front Camera (Video)": "selfie_camera_video"
};
const attributes = Object.entries(attributesDict)
.filter(([_, key]) => formattedPhone[key])
.map(([label, key]) => `<b>${label}:</b> <code>${formattedPhone[key]}</code>`)
.join("\n\n");
const deviceUrl = `<b>GSMArena page:</b> ${formattedPhone.url}`;
const deviceImage = phone.picture ? `<b>Device Image</b>: ${phone.picture}` : '';
return `<b>\n\nName: </b><code>${formattedPhone.name}</code>\n\n${attributes}\n\n${deviceImage}\n\n${deviceUrl}`;
}
async function fetchHtml(url) {
try {
const response = await axios.get(url, { headers: HEADERS });
return response.data;
} catch (error) {
console.error("Error fetching HTML:", error);
throw error;
}
}
async function searchPhone(phone) {
try {
const searchUrl = `https://m.gsmarena.com/results.php3?sQuickSearch=yes&sName=${encodeURIComponent(phone)}`;
const htmlContent = await fetchHtml(searchUrl);
const root = parse(htmlContent);
const foundPhones = root.querySelectorAll('.general-menu.material-card ul li');
return foundPhones.map((phoneTag) => {
const name = phoneTag.querySelector('img')?.getAttribute('title') || "";
const url = phoneTag.querySelector('a')?.getAttribute('href') || "";
return new PhoneSearchResult(name, url);
});
} catch (error) {
console.error("Error searching for phone:", error);
return [];
}
}
async function checkPhoneDetails(url) {
try {
const htmlContent = await fetchHtml(`https://www.gsmarena.com/${url}`);
const root = parse(htmlContent);
const specsTables = root.querySelectorAll('table[cellspacing="0"]');
const specsData = extractSpecs(specsTables);
const metaScripts = root.querySelectorAll('script[language="javascript"]');
const meta = metaScripts.length ? metaScripts[0].text.split("\n") : [];
const name = extractMetaData(meta, "ITEM_NAME");
const picture = extractMetaData(meta, "ITEM_IMAGE");
return { ...specsData, name, picture, url: `https://www.gsmarena.com/${url}` };
} catch (error) {
console.error("Error fetching phone details:", error);
return {};
}
}
function extractSpecs(specsTables) {
return {
specs: specsTables.reduce((acc, table) => {
const feature = table.querySelector('th')?.text.trim() || "";
table.querySelectorAll('tr').forEach((tr) => {
const header = tr.querySelector('.ttl')?.text.trim() || "info";
let detail = tr.querySelector('.nfo')?.text.trim() || "";
detail = detail.replace(/\s*\n\s*/g, " / ").trim();
if (!acc[feature]) {
acc[feature] = {};
}
acc[feature][header] = acc[feature][header]
? `${acc[feature][header]} / ${detail}`
: detail;
});
return acc;
}, {})
};
}
function extractMetaData(meta, key) {
const line = meta.find((line) => line.includes(key));
return line ? line.split('"')[1] : "";
}
module.exports = (bot) => {
bot.command(['d', 'device'], spamwatchMiddleware, async (ctx) => {
const userId = ctx.from.id;
const userName = ctx.from.first_name;
const phone = ctx.message.text.split(" ").slice(1).join(" ");
if (!phone) {
return ctx.reply("Please provide the phone name.", { reply_to_message_id: ctx.message.message_id });
}
const results = await searchPhone(phone);
if (results.length === 0) {
return ctx.reply("No phones found.", { reply_to_message_id: ctx.message.message_id });
}
const testUser = `<a href="tg://user?id=${userId}">${userName}</a>, Select a device:`;
const options = {
parse_mode: 'HTML',
disable_web_page_preview: true,
reply_markup: {
inline_keyboard: results.map(result => [{ text: result.name, callback_data: `details:${result.url}:${ctx.from.id}` }])
}
};
ctx.reply(testUser, options);
});
bot.action(/details:(.+):(.+)/, async (ctx) => {
const url = ctx.match[1];
const userId = parseInt(ctx.match[2]);
const userName = ctx.from.first_name;
const callbackQueryUserId = ctx.update.callback_query.from.id;
if (userId !== callbackQueryUserId) {
return ctx.answerCbQuery(`${userName}, you are not allowed to interact with this.`);
}
ctx.answerCbQuery();
const phoneDetails = await checkPhoneDetails(url);
if (phoneDetails.name) {
const message = formatPhone(phoneDetails);
ctx.editMessageText(`<b><a href="tg://user?id=${userId}">${userName}</a>, there are the details of your device:</b>` + message, { parse_mode: 'HTML', disable_web_page_preview: false });
} else {
ctx.reply("Error fetching phone details.", { reply_to_message_id: ctx.message.message_id });
}
});
};

86
src/commands/help.js Normal file
View file

@ -0,0 +1,86 @@
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
async function sendHelpMessage(ctx, isEditing) {
const Strings = getStrings(ctx.from.language_code);
const options = {
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: Strings.mainCommands, callback_data: 'helpMain' }, { text: Strings.usefulCommands, callback_data: 'helpUseful' }],
[{ text: Strings.interactiveEmojis, callback_data: 'helpInteractive' }, { text: Strings.funnyCommands, callback_data: 'helpFunny' }],
[{ text: Strings.lastFm, callback_data: 'helpLast' }, { text: Strings.animalCommands, callback_data: 'helpAnimals' }],
[{ text: Strings.ytDlp, callback_data: 'helpYouTube' }, { text: Strings.myLittlePony, callback_data: 'helpMLP' }]
]
}
};
const helpText = Strings.lynxHelp;
if (isEditing) {
await ctx.editMessageText(helpText, options);
} else {
await ctx.reply(helpText, options);
}
}
module.exports = (bot) => {
bot.help(spamwatchMiddleware, async (ctx) => {
await sendHelpMessage(ctx);
});
bot.on('callback_query', async (ctx) => {
const callbackData = ctx.callbackQuery.data;
const Strings = getStrings(ctx.from.language_code);
const options = {
parse_mode: 'Markdown',
disable_web_page_preview: true,
reply_markup: JSON.stringify({
inline_keyboard: [
[{ text: Strings.goBack, callback_data: 'helpBack' }],
]
})
};
switch (callbackData) {
case 'helpMain':
await ctx.answerCbQuery();
await ctx.editMessageText(Strings.mainCommandsDesc, options);
break;
case 'helpUseful':
await ctx.answerCbQuery();
await ctx.editMessageText(Strings.usefulCommandsDesc, options);
break;
case 'helpInteractive':
await ctx.answerCbQuery();
await ctx.editMessageText(Strings.interactiveEmojisDesc, options);
break;
case 'helpFunny':
await ctx.answerCbQuery();
await ctx.editMessageText(Strings.funnyCommandsDesc, options);
break;
case 'helpLast':
await ctx.answerCbQuery();
await ctx.editMessageText(Strings.lastFmDesc, options);
break;
case 'helpYouTube':
await ctx.answerCbQuery();
await ctx.editMessageText(Strings.ytDlpDesc, options);
break;
case 'helpAnimals':
await ctx.answerCbQuery();
await ctx.editMessageText(Strings.animalCommandsDesc, options);
break;
case 'helpMLP':
await ctx.answerCbQuery();
await ctx.editMessageText(Strings.myLittlePonyDesc, options);
break;
case 'helpBack':
await ctx.answerCbQuery();
await sendHelpMessage(ctx, true);
break;
default:
await ctx.answerCbQuery(Strings.invalidOption);
break;
}
});
}

75
src/commands/http.js Normal file
View file

@ -0,0 +1,75 @@
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require('axios');
module.exports = (bot) => {
bot.command("http", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const userInput = ctx.message.text.split(' ')[1];
const apiUrl = "https://status.js.org/codes.json";
if (!userInput || isNaN(userInput)) {
return ctx.reply(Strings.httpCodeInvalid, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
try {
const response = await axios.get(apiUrl);
const data = response.data;
const codesArray = Array.isArray(data) ? data : Object.values(data);
const codeInfo = codesArray.find(item => item.code === parseInt(userInput));
if (codeInfo) {
const message = Strings.httpCodeResult
.replace("{code}", codeInfo.code)
.replace("{message}", codeInfo.message)
.replace("{description}", codeInfo.description);
await ctx.reply(message, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} else {
await ctx.reply(Strings.httpCodeNotFound, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
} catch (error) {
const message = Strings.httpCodeErr.replace("{error}", error);
ctx.reply(message, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
});
bot.command("httpcat", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const userInput = ctx.message.text.split(' ').slice(1).join(' ').replace(/\s+/g, '');
if (!userInput || isNaN(userInput)) {
return ctx.reply(Strings.catImgErr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
const apiUrl = `https://http.cat/${userInput}`;
try {
await ctx.replyWithPhoto(apiUrl, {
caption: `🐱 ${apiUrl}`,
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
ctx.reply(Strings.catImgErr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
});
};

63
src/commands/info.js Normal file
View file

@ -0,0 +1,63 @@
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
async function getUserInfo(ctx) {
const Strings = getStrings(ctx.from.language_code);
let lastName = ctx.from.last_name;
if (lastName === undefined) {
lastName = " ";
}
userInfo = Strings.userInfo
.replace('{userName}', `${ctx.from.first_name} ${lastName}` || Strings.unKnown)
.replace('{userId}', ctx.from.id || Strings.unKnown)
.replace('{userHandle}', ctx.from.username ? `@${ctx.from.username}` : Strings.varNone)
.replace('{userPremium}', ctx.from.is_premium ? Strings.varYes : Strings.varNo)
.replace('{userLang}', ctx.from.language_code || Strings.unKnown);
return userInfo;
}
async function getChatInfo(ctx) {
const Strings = getStrings(ctx.from.language_code);
if (ctx.chat.type === 'group' || ctx.chat.type === 'supergroup') {
chatInfo = Strings.chatInfo
.replace('{chatId}', ctx.chat.id || Strings.unKnown)
.replace('{chatName}', ctx.chat.title || Strings.unKnown)
.replace('{chatHandle}', ctx.chat.username ? `@${ctx.chat.username}` : Strings.varNone)
.replace('{chatMembersCount}', await ctx.getChatMembersCount(ctx.chat.id || Strings.unKnown))
.replace('{chatType}', ctx.chat.type || Strings.unKnown)
.replace('{isForum}', ctx.chat.is_forum ? Strings.varYes : Strings.varNo);
return chatInfo;
} else {
return ctx.reply(
Strings.groupOnly, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
}
}
module.exports = (bot) => {
bot.command('chatinfo', spamwatchMiddleware, async (ctx) => {
const chatInfo = await getChatInfo(ctx);
ctx.reply(
chatInfo, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
}
);
});
bot.command('userinfo', spamwatchMiddleware, async (ctx) => {
const userInfo = await getUserInfo(ctx);
ctx.reply(
userInfo, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
}
);
});
};

182
src/commands/lastfm.js Normal file
View file

@ -0,0 +1,182 @@
const fs = require('fs');
const axios = require('axios');
const Config = require('../props/config.json');
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const scrobbler_url = 'http://ws.audioscrobbler.com/2.0/';
const api_key = Config.lastKey;
const dbFile = 'props/lastfm.json';
let users = {};
function loadUsers() {
if (!fs.existsSync(dbFile)) {
console.log(`WARN: Last.fm user database ${dbFile} not found. Creating a new one.`);
saveUsers();
return;
}
try {
const data = fs.readFileSync(dbFile, 'utf-8');
users = JSON.parse(data);
} catch (err) {
console.log("WARN: Error loading the Last.fm user database:", err);
users = {};
}
}
function saveUsers() {
try {
fs.writeFileSync(dbFile, JSON.stringify(users, null, 2), 'utf-8');
} catch (err) {
console.error("WARN: Error saving Last.fm users:", err);
}
}
module.exports = (bot) => {
loadUsers();
bot.command('setuser', (ctx) => {
const userId = ctx.from.id;
const Strings = getStrings(ctx.from.language_code);
const lastUser = ctx.message.text.split(' ')[1];
if (!lastUser) {
return ctx.reply(Strings.lastFmNoUser, {
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
};
users[userId] = lastUser;
saveUsers();
const message = Strings.lastFmUserSet.replace('{lastUser}', lastUser);
ctx.reply(message, {
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
});
bot.command(['lt', 'lmu', 'last', 'lfm'], spamwatchMiddleware, async (ctx) => {
const userId = ctx.from.id;
const Strings = getStrings(ctx.from.language_code);
const lastfmUser = users[userId];
if (!lastfmUser) {
return ctx.reply(Strings.lastFmNoSet, {
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
};
try {
const response = await axios.get(scrobbler_url, {
params: {
method: 'user.getRecentTracks',
user: lastfmUser,
api_key,
format: 'json',
limit: 1
},
headers: {
'User-Agent': "lynx-@LynxBR_bot-node-telegram-bot"
}
});
const track = response.data.recenttracks.track[0];
if (!track) {
const noRecent = Strings.lastFmNoRecent.replace('{lastfmUser}', lastfmUser);
return ctx.reply(noRecent, {
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
};
const trackName = track.name;
const artistName = track.artist['#text'];
const nowPlaying = track['@attr'] && track['@attr'].nowplaying ? Strings.lastFmListeningNow : Strings.lastFmLastPlayed;
const imageExtralarge = track.image.find(img => img.size === 'extralarge');
const imageMega = track.image.find(img => img.size === 'mega');
const imageUrl = (imageExtralarge && imageExtralarge['#text']) || (imageMega && imageMega['#text']) || '';
const trackUrl = `https://www.last.fm/music/${encodeURIComponent(artistName)}/_/${encodeURIComponent(trackName)}`;
const artistUrl = `https://www.last.fm/music/${encodeURIComponent(artistName)}`;
const userUrl = `https://www.last.fm/user/${encodeURIComponent(lastfmUser)}`;
let num_plays = '';
try {
const response_plays = await axios.get(scrobbler_url, {
params: {
method: 'track.getInfo',
api_key,
track: trackName,
artist: artistName,
username: lastfmUser,
format: 'json',
},
headers: {
'User-Agent': "lynx-@LynxBR_bot-node-telegram-bot"
}
});
num_plays = response_plays.data.track.userplaycount;
if (!num_plays || num_plays === undefined) {
num_plays = 0;
};
} catch (err) {
console.log(err)
const message = Strings.lastFmErr
.replace("{lastfmUser}", `[${lastfmUser}](${userUrl})`)
.replace("{err}", err);
ctx.reply(message, {
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
};
const message = Strings.lastFmStatusFor
.replace("{lastfmUser}", `[${lastfmUser}](${userUrl})`)
.replace("{nowPlaying}", nowPlaying)
.replace("{trackName}", `[${trackName}](${trackUrl})`)
.replace("{artistName}", `[${artistName}](${artistUrl})`)
.replace("{plays}", `${num_plays}`);
if (imageUrl) {
ctx.replyWithPhoto(imageUrl, {
caption: message,
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
} else {
ctx.reply(message, {
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
};
} catch (err) {
const userUrl = `https://www.last.fm/user/${encodeURIComponent(lastfmUser)}`;
const message = Strings.lastFmErr
.replace("{lastfmUser}", `[${lastfmUser}](${userUrl})`)
.replace("{err}", err);
ctx.reply(message, {
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
};
});
};

26
src/commands/main.js Normal file
View file

@ -0,0 +1,26 @@
const resources = require('../props/resources.json');
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
module.exports = (bot) => {
bot.start(spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
ctx.replyWithPhoto(
resources.lunaCat, {
caption: Strings.lynxWelcome,
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
});
bot.command('privacy', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
ctx.reply(
Strings.lynxPrivacy, {
parse_mode: 'Markdown',
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
});
};

View file

@ -0,0 +1,73 @@
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
async function downloadModule(moduleId) {
try {
const downloadUrl = `https://api.modarchive.org/downloads.php?moduleid=${moduleId}`;
const response = await axios({
url: downloadUrl,
method: 'GET',
responseType: 'stream',
});
const disposition = response.headers['content-disposition'];
let fileName = moduleId;
if (disposition && disposition.includes('filename=')) {
fileName = disposition
.split('filename=')[1]
.split(';')[0]
.replace(/['"]/g, '');
}
const filePath = path.resolve(__dirname, fileName);
const writer = fs.createWriteStream(filePath);
response.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', () => resolve({ filePath, fileName }));
writer.on('error', reject);
});
} catch (error) {
return null;
}
}
module.exports = (bot) => {
bot.command(['modarchive', 'tma'], spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const args = ctx.message.text.split(' ');
if (args.length !== 2) {
return ctx.reply(Strings.maInvalidModule, {
parse_mode: "Markdown",
reply_to_message_id: ctx.message.message_id
});
}
const moduleId = args[1];
const result = await downloadModule(moduleId);
if (result) {
const { filePath, fileName } = result;
await ctx.replyWithDocument({
source: filePath,
caption: fileName,
});
fs.unlinkSync(filePath);
} else {
ctx.reply(Strings.maDownloadError, {
parse_mode: "Markdown",
reply_to_message_id: ctx.message.message_id
});
}
});
};

165
src/commands/ponyapi.js Normal file
View file

@ -0,0 +1,165 @@
const { spawn } = require('child_process');
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require("axios");
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
module.exports = (bot) => {
bot.command("mlp", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
ctx.reply(Strings.myLittlePonyDesc, {
parse_mode: 'Markdown',
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
});
bot.command("mlpchar", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const userInput = ctx.message.text.split(' ').slice(1).join(' ');
if (!userInput) {
ctx.reply(Strings.ponyApiNoCharName, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
return;
};
const capitalizedInput = capitalizeFirstLetter(userInput);
const apiUrl = `http://ponyapi.net/v1/character/${capitalizedInput}`;
try {
const response = await axios(apiUrl);
const charactersArray = [];
if (Array.isArray(response.data.data)) {
response.data.data.forEach(character => {
let aliases = [];
if (character.alias) {
if (typeof character.alias === 'string') {
aliases.push(character.alias);
} else if (Array.isArray(character.alias)) {
aliases = aliases.concat(character.alias);
}
}
charactersArray.push({
name: character.name,
alias: aliases.length > 0 ? aliases.join(', ') : 'N/A',
url: character.url,
sex: character.sex,
residence: character.residence ? character.residence.replace(/\n/g, ' / ') : 'N/A',
occupation: character.occupation ? character.occupation.replace(/\n/g, ' / ') : 'N/A',
kind: character.kind ? character.kind.join(', ') : 'N/A',
image: character.image
});
});
};
if (charactersArray.length > 0) {
const result = Strings.ponyApiCharRes
.replace("{input}", userInput)
.replace("{name}", charactersArray[0].name)
.replace("{alias}", charactersArray[0].alias)
.replace("{url}", charactersArray[0].url)
.replace("{sex}", charactersArray[0].sex)
.replace("{residence}", charactersArray[0].residence)
.replace("{occupation}", charactersArray[0].occupation)
.replace("{kind}", charactersArray[0].kind);
ctx.replyWithPhoto(charactersArray[0].image[0], {
caption: `${result}`,
parse_mode: 'Markdown',
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
} else {
ctx.reply(Strings.ponyApiNoCharFound, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
} catch (error) {
console.error(error);
ctx.reply(Strings.ponyApiErr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
});
bot.command("mlpep", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
const userInput = ctx.message.text.split(' ').slice(1).join(' ');
if (!userInput) {
ctx.reply(Strings.ponyApiNoEpisodeNum, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
return;
};
const apiUrl = `http://ponyapi.net/v1/episode/by-overall/${userInput}`;
try {
const response = await axios(apiUrl);
const episodeArray = [];
if (Array.isArray(response.data.data)) {
response.data.data.forEach(episode => {
episodeArray.push({
name: episode.name,
image: episode.image,
url: episode.url,
season: episode.season,
episode: episode.episode,
overall: episode.overall,
airdate: episode.airdate,
storyby: episode.storyby ? episode.storyby.replace(/\n/g, ' / ') : 'N/A',
writtenby: episode.writtenby ? episode.writtenby.replace(/\n/g, ' / ') : 'N/A',
storyboard: episode.storyboard ? episode.storyboard.replace(/\n/g, ' / ') : 'N/A',
});
});
};
if (episodeArray.length > 0) {
const result = Strings.ponyApiEpRes
.replace("{input}", userInput)
.replace("{name}", episodeArray[0].name)
.replace("{url}", episodeArray[0].url)
.replace("{season}", episodeArray[0].season)
.replace("{episode}", episodeArray[0].episode)
.replace("{overall}", episodeArray[0].overall)
.replace("{airdate}", episodeArray[0].airdate)
.replace("{storyby}", episodeArray[0].storyby)
.replace("{writtenby}", episodeArray[0].writtenby)
.replace("{storyboard}", episodeArray[0].storyboard);
ctx.replyWithPhoto(episodeArray[0].image, {
caption: `${result}`,
parse_mode: 'Markdown',
disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id
});
} else {
ctx.reply(Strings.ponyApiNoEpisodeFound, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
} catch (error) {
console.error(error);
ctx.reply(Strings.ponyApiErr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
};
});
};

29
src/commands/quotes.js Normal file
View file

@ -0,0 +1,29 @@
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require('axios');
module.exports = (bot) => {
bot.command("quote", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code);
try {
const response = await axios.get('https://quotes-api-self.vercel.app/quote');
const data = response.data;
const escapedQuote = data.quote.replace(/([\\_*~`>.!-])/g, '\\$1');
const escapedAuthor = `- ${data.author}.`.replace(/([\\_*~`>.!-])/g, '\\$1');
const escapedData = `${Strings.quoteResult}\n>*${escapedQuote}*\n_${escapedAuthor}_`;
ctx.reply(escapedData, {
reply_to_message_id: ctx.message.message_id,
parse_mode: 'MarkdownV2'
});
} catch (error) {
console.error(error);
ctx.reply(Strings.quoteErr, {
reply_to_message_id: ctx.message.id,
parse_mode: 'MarkdownV2'
});
};
});
};

111
src/commands/weather.js Normal file
View file

@ -0,0 +1,111 @@
// Ported and improved from BubbalooTeam's PyCoala bot
// Copyright (c) 2024 BubbalooTeam. (https://github.com/BubbalooTeam)
// Minor code changes by lucmsilva (https://github.com/lucmsilva651)
const axios = require('axios');
const Config = require('../props/config.json');
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const statusEmojis = {
0: '⛈', 1: '⛈', 2: '⛈', 3: '⛈', 4: '⛈', 5: '🌨', 6: '🌨', 7: '🌨',
8: '🌨', 9: '🌨', 10: '🌨', 11: '🌧', 12: '🌧', 13: '🌨', 14: '🌨',
15: '🌨', 16: '🌨', 17: '⛈', 18: '🌧', 19: '🌫', 20: '🌫', 21: '🌫',
22: '🌫', 23: '🌬', 24: '🌬', 25: '🌨', 26: '☁️', 27: '🌥', 28: '🌥',
29: '⛅️', 30: '⛅️', 31: '🌙', 32: '☀️', 33: '🌤', 34: '🌤', 35: '⛈',
36: '🔥', 37: '🌩', 38: '🌩', 39: '🌧', 40: '🌧', 41: '❄️', 42: '❄️',
43: '❄️', 44: 'n/a', 45: '🌧', 46: '🌨', 47: '🌩'
};
const getStatusEmoji = (statusCode) => statusEmojis[statusCode] || 'n/a';
function getLocaleUnit(userLang) {
const fahrenheitCountries = ['US', 'BS', 'BZ', 'KY', 'LR'];
const languagePrefix = userLang.split('-')[0];
const countryCode = userLang.split('-')[1];
if (languagePrefix === 'en' || (countryCode && fahrenheitCountries.includes(countryCode))) {
return { temperatureUnit: 'F', speedUnit: 'mph', apiUnit: 'e' };
} else {
return { temperatureUnit: 'C', speedUnit: 'km/h', apiUnit: 'm' };
}
}
module.exports = (bot) => {
bot.command(['clima', 'weather'], spamwatchMiddleware, async (ctx) => {
const userLang = ctx.from.language_code || "en-US";
const Strings = getStrings(userLang);
const args = ctx.message.text;
if (args.length < 9) {
return ctx.reply(Strings.provideLocation, {
parse_mode: "Markdown",
reply_to_message_id: ctx.message.message_id
});
}
const location = args.slice(9);
const apiKey = Config.weatherKey;
try {
const locationResponse = await axios.get('https://api.weather.com/v3/location/search', {
params: {
apiKey: apiKey,
format: 'json',
language: userLang,
query: location,
},
});
const locationData = locationResponse.data.location;
if (!locationData || !locationData.address) {
return ctx.reply(Strings.invalidLocation, {
parse_mode: "Markdown",
reply_to_message_id: ctx.message.message_id
});
}
const addressFirst = locationData.address[0];
const latFirst = locationData.latitude[0];
const lonFirst = locationData.longitude[0];
const { temperatureUnit, speedUnit, apiUnit } = getLocaleUnit(userLang);
const weatherResponse = await axios.get('https://api.weather.com/v3/aggcommon/v3-wx-observations-current', {
params: {
apiKey: apiKey,
format: 'json',
language: userLang,
geocode: `${latFirst},${lonFirst}`,
units: apiUnit,
},
});
const weatherData = weatherResponse.data['v3-wx-observations-current'];
const { temperature, temperatureFeelsLike, relativeHumidity, windSpeed, iconCode, wxPhraseLong } = weatherData;
const weatherMessage = Strings.weatherStatus
.replace('{addressFirst}', addressFirst)
.replace('{getStatusEmoji(iconCode)}', getStatusEmoji(iconCode))
.replace('{wxPhraseLong}', wxPhraseLong)
.replace('{temperature}', temperature)
.replace('{temperatureFeelsLike}', temperatureFeelsLike)
.replace('{temperatureUnit}', temperatureUnit)
.replace('{temperatureUnit2}', temperatureUnit)
.replace('{relativeHumidity}', relativeHumidity)
.replace('{windSpeed}', windSpeed)
.replace('{speedUnit}', speedUnit);
ctx.reply(weatherMessage, {
parse_mode: "Markdown",
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
const message = Strings.weatherErr.replace('{error}', error.message);
ctx.reply(message, {
parse_mode: "Markdown",
reply_to_message_id: ctx.message.message_id
});
}
});
};

36
src/commands/wiki.js Normal file
View file

@ -0,0 +1,36 @@
const axios = require("axios");
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function mediaWikiToMarkdown(input) {
input = input.replace(/===(.*?)===/g, '*$1*');
input = input.replace(/==(.*?)==/g, '*$1*');
input = input.replace(/=(.*?)=/g, '*$1*');
input = input.replace(/'''(.*?)'''/g, '**$1**');
input = input.replace(/''(.*?)''/g, '_$1_');
input = input.replace(/^\*\s/gm, '- ');
input = input.replace(/^\#\s/gm, '1. ');
input = input.replace(/{{Quote(.*?)}}/g, "```\n$1```\n");
input = input.replace(/\[\[(.*?)\|?(.*?)\]\]/g, (_, link, text) => {
const sanitizedLink = link.replace(/ /g, '_');
return text ? `[${text}](${sanitizedLink})` : `[${sanitizedLink}](${sanitizedLink})`;
});
input = input.replace(/\[\[File:(.*?)\|.*?\]\]/g, '![$1](https://en.wikipedia.org/wiki/File:$1)');
return input;
}
module.exports = (bot) => {
bot.command("wiki", async (ctx) => {
const userInput = capitalizeFirstLetter(ctx.message.text.split(' ')[1]);
const apiUrl = `https://en.wikipedia.org/w/index.php?title=${userInput}&action=raw`;
const response = await axios(apiUrl, { headers: { 'Accept': "text/plain" } });
const convertedResponse = response.data.replace(/<\/?div>/g, "").replace(/{{Infobox.*?}}/s, "");
const result = mediaWikiToMarkdown(convertedResponse).slice(0, 2048);
ctx.reply(result, { parse_mode: 'Markdown', disable_web_page_preview: true, reply_to_message_id: ctx.message.message_id });
});
};

169
src/commands/youtube.js Normal file
View file

@ -0,0 +1,169 @@
const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const { execFile } = require('child_process');
const os = require('os');
const fs = require('fs');
const path = require('path');
const ytDlpPaths = {
linux: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp'),
win32: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp.exe'),
darwin: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp_macos'),
};
const getYtDlpPath = () => {
const platform = os.platform();
return ytDlpPaths[platform] || ytDlpPaths.linux;
};
const ffmpegPaths = {
linux: '/usr/bin/ffmpeg',
win32: path.resolve(__dirname, '../plugins/ffmpeg/bin/ffmpeg.exe'),
};
const getFfmpegPath = () => {
const platform = os.platform();
return ffmpegPaths[platform] || ffmpegPaths.linux;
};
const downloadFromYoutube = async (command, args) => {
return new Promise((resolve, reject) => {
execFile(command, args, (error, stdout, stderr) => {
if (error) {
reject({ error, stdout, stderr });
} else {
resolve({ stdout, stderr });
}
});
});
};
const getApproxSize = async (command, videoUrl) => {
const args = [videoUrl, '--compat-opt', 'manifest-filesize-approx', '-O', 'filesize_approx'];
try {
const { stdout } = await downloadFromYoutube(command, args);
const sizeInBytes = parseInt(stdout.trim(), 10);
if (!isNaN(sizeInBytes)) {
return sizeInBytes / (1024 * 1024);
} else {
throw new Error('Invalid size received from yt-dlp');
}
} catch (error) {
throw error;
}
};
module.exports = (bot) => {
bot.command(['yt', 'ytdl'], spamwatchMiddleware, async (ctx) => {
const strings = getStrings(ctx.from.language_code);
const ytDlpPath = getYtDlpPath();
const userId = ctx.from.id;
const videoUrl = ctx.message.text.split(' ').slice(1).join(' ');
const mp4File = `tmp/${userId}.mp4`;
const tempMp4File = `tmp/${userId}.f137.mp4`;
const tempWebmFile = `tmp/${userId}.f251.webm`;
const cmdArgs = "--max-filesize 2G --no-playlist --cookies props/cookies.txt --merge-output-format mp4 -o";
const dlpCommand = ytDlpPath;
const ffmpegPath = getFfmpegPath();
const ffmpegArgs = ['-i', tempMp4File, '-i', tempWebmFile, '-c:v copy -c:a copy -strict -2', mp4File];
try {
const downloadingMessage = await ctx.reply(strings.ytCheckingSize, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
});
if (fs.existsSync(ytDlpPath)) {
const approxSizeInMB = await Promise.race([
getApproxSize(ytDlpPath, videoUrl)
]);
await ctx.telegram.editMessageText(
ctx.chat.id,
downloadingMessage.message_id,
null,
strings.ytDownloading, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
},
);
const dlpArgs = [videoUrl, ...cmdArgs.split(' '), mp4File];
await downloadFromYoutube(dlpCommand, dlpArgs);
await ctx.telegram.editMessageText(
ctx.chat.id,
downloadingMessage.message_id,
null,
strings.ytUploading, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
},
);
if(fs.existsSync(tempMp4File)){
await downloadFromYoutube(ffmpegPath, ffmpegArgs);
}
if (fs.existsSync(mp4File)) {
const message = strings.ytUploadDesc
.replace("{userId}", userId)
.replace("{userName}", ctx.from.first_name);
try {
await ctx.replyWithVideo({
source: mp4File,
caption: `${message}`,
parse_mode: 'Markdown',
});
if (approxSizeInMB >= 50) {
await ctx.telegram.editMessageText(
ctx.chat.id,
downloadingMessage.message_id,
null,
strings.ytUploadLimit2, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
},
);
}
fs.unlinkSync(mp4File);
} catch (error) {
await ctx.reply(`\`${error.message}\``, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
});
fs.unlinkSync(mp4File);
}
} else {
await ctx.reply(mp4File, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
});
}
} else {
await ctx.telegram.editMessageText(
ctx.chat.id,
downloadingMessage.message_id,
null,
strings.ytFileErr, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
},
);
}
} catch (error) {
console.error(error);
await ctx.reply(`\`${error.message}\``, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id,
});
}
});
};