GSMArena scraper + minor code changes

This commit is contained in:
Lucas Gabriel 2024-09-06 21:56:19 -03:00
parent 4be9aa4aca
commit 6a61d86b6e
No known key found for this signature in database
GPG Key ID: D9B075FC6DC93985
6 changed files with 471 additions and 3 deletions

1
bot.js
View File

@ -37,7 +37,6 @@ const sendMessage = async (ctx, text, options = {}) => {
} }
}; };
// Função para iniciar o bot
const startBot = async () => { const startBot = async () => {
try { try {
await bot.launch(); await bot.launch();

View File

@ -57,7 +57,7 @@ module.exports = (bot) => {
parse_mode: 'Markdown', parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id reply_to_message_id: ctx.message.message_id
}); });
}, '', Strings.errorRetrievingStats); // No success message }, '', Strings.errorRetrievingStats);
}); });
bot.command('setbotname', spamwatchMiddleware, async (ctx) => { bot.command('setbotname', spamwatchMiddleware, async (ctx) => {

234
commands/gsmarena.js Normal file
View File

@ -0,0 +1,234 @@
// 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');
const { Markup } = require('telegraf');
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"]],
"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"]],
"main_camera_single": ["Main Camera", ["Single"]],
"main_camera_dual": ["Main Camera", ["Dual"]],
"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_features": ["Selfie Camera", ["Features"]],
"selfie_camera_video": ["Selfie Camera", ["Video"]],
"memory": ["Memory", ["Internal"]]
};
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",
"Launch": "launch_date",
"Network": "network",
"Weight": "weight",
"OS": "system",
"Display Resolution": "display_resolution",
"Display Type": "display_type",
"Display Size": "display_size",
"CPU": "platform_cpu",
"GPU": "platform_gpu",
"Chipset": "platform_chipset",
"Memory": "memory",
"Rear Camera (Single)": "main_camera_single",
"Rear Camera (Dual)": "main_camera_single",
"Rear Camera (Features)": "main_camera_single",
"Rear Camera (Video)": "main_camera_single",
"Front Camera (Single)": "selfie_camera_single",
"Front Camera (Dual)": "selfie_camera_single",
"Front Camera (Features)": "selfie_camera_single",
"Front Camera (Video)": "selfie_camera_single",
"3.5mm jack": "jack",
"USB": "usb",
"Sensors": "sensors",
"Battery": "battery",
"Charging": "charging"
};
const attributes = Object.entries(attributesDict)
.filter(([_, key]) => formattedPhone[key])
.map(([label, key]) => `<b>${label}:</b> <code>${formattedPhone[key]}</code>`)
.join("\n\n");
return `<b>${formattedPhone.name}</b>\n\n${attributes}`;
}
async function fetchHtml(url) {
try {
const response = await axios.get(`https://cors-bypass.amano.workers.dev/${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.");
}
const results = await searchPhone(phone);
if (results.length === 0) {
return ctx.reply("No phones found.");
}
const buttons = results.map((result) => {
return Markup.button.callback(result.name, `details:${result.url}:${ctx.from.id}`);
});
ctx.reply(`<a href="tg://user?id=${userId}">${userName}</a>, Select a device:`, Markup.inlineKeyboard(buttons, { columns: 2 }), {
parse_mode: 'HTML',
disable_web_page_preview: true
});
});
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("You are not allowed to interact with this.");
}
const phoneDetails = await checkPhoneDetails(url);
if (phoneDetails.name) {
const message = formatPhone(phoneDetails);
ctx.editMessageText(`Here are the details for the phone you requested, <a href="tg://user?id=${userId}">${userName}</a>:\n\n${message}`, {
parse_mode: "HTML"
});
} else {
ctx.editMessageText(`Unable to fetch phone details, <a href="tg://user?id=${userId}">${userName}</a>.`, {
parse_mode: "HTML"
});
}
});
};

View File

@ -6,7 +6,7 @@ async function getUserInfo(ctx) {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
userInfo = Strings.userInfo userInfo = Strings.userInfo
.replace('{userName}', ctx.from.first_name || Strings.unKnown) .replace('{userName}', `${ctx.from.first_name} ${ctx.from.last_name}` || Strings.unKnown)
.replace('{userId}', ctx.from.id || Strings.unKnown) .replace('{userId}', ctx.from.id || Strings.unKnown)
.replace('{userHandle}', ctx.from.username ? `@${ctx.from.username}` : Strings.varNone) .replace('{userHandle}', ctx.from.username ? `@${ctx.from.username}` : Strings.varNone)
.replace('{userPremium}', ctx.from.is_premium ? Strings.varYes : Strings.varNo) .replace('{userPremium}', ctx.from.is_premium ? Strings.varYes : Strings.varNo)

233
package-lock.json generated
View File

@ -9,6 +9,8 @@
"version": "1.0.0", "version": "1.0.0",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"axios": "^1.7.7",
"node-html-parser": "^6.1.13",
"nodemon": "^3.1.4", "nodemon": "^3.1.4",
"telegraf": "^4.16.3" "telegraf": "^4.16.3"
} }
@ -44,6 +46,23 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.7.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -62,6 +81,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"license": "ISC"
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -130,12 +155,52 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/css-select": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.5", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
@ -153,6 +218,82 @@
} }
} }
}, },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "BSD-2-Clause"
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/event-target-shim": { "node_modules/event-target-shim": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
@ -174,6 +315,40 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/follow-redirects": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.8.tgz",
"integrity": "sha512-xgrmBhBToVKay1q2Tao5LI26B83UhrB/vM1avwVSDzt8rx3rO6AizBAaF46EgksTVr+rFTQaqZZ9MVBfUe4nig==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fsevents": { "node_modules/fsevents": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@ -209,6 +384,15 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"license": "MIT",
"bin": {
"he": "bin/he"
}
},
"node_modules/ignore-by-default": { "node_modules/ignore-by-default": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
@ -257,6 +441,27 @@
"node": ">=0.12.0" "node": ">=0.12.0"
} }
}, },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@ -304,6 +509,16 @@
} }
} }
}, },
"node_modules/node-html-parser": {
"version": "6.1.13",
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz",
"integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==",
"license": "MIT",
"dependencies": {
"css-select": "^5.1.0",
"he": "1.2.0"
}
},
"node_modules/nodemon": { "node_modules/nodemon": {
"version": "3.1.4", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz",
@ -340,6 +555,18 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0"
},
"funding": {
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/p-timeout": { "node_modules/p-timeout": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
@ -361,6 +588,12 @@
"url": "https://github.com/sponsors/jonschlinkert" "url": "https://github.com/sponsors/jonschlinkert"
} }
}, },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/pstree.remy": { "node_modules/pstree.remy": {
"version": "1.1.8", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",

View File

@ -9,6 +9,8 @@
"author": "Lucas Gabriel (lucmsilva)", "author": "Lucas Gabriel (lucmsilva)",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"axios": "^1.7.7",
"node-html-parser": "^6.1.13",
"nodemon": "^3.1.4", "nodemon": "^3.1.4",
"telegraf": "^4.16.3" "telegraf": "^4.16.3"
} }