From efadb519059676107064a1f01238c61ba5b031a2 Mon Sep 17 00:00:00 2001 From: Aidan Date: Thu, 24 Apr 2025 18:49:51 -0400 Subject: [PATCH] rf: js -> ts --- .dockerignore | 1 - config.env.example => .env.example | 0 .gitignore | 7 +- Dockerfile | 2 +- README.md | 12 ++-- docker-compose.yml | 2 +- nodemon.json | 5 +- package.json | 1 + src/{bot.js => bot.ts} | 23 ++++--- src/commands/{animal.js => animal.ts} | 14 ++-- src/commands/{codename.js => codename.ts} | 20 +++--- src/commands/{crew.js => crew.ts} | 16 +++-- src/commands/{fun.js => fun.ts} | 16 +++-- src/commands/{gsmarena.js => gsmarena.ts} | 39 ++++++----- src/commands/{help.js => help.ts} | 25 +++++-- src/commands/{http.js => http.ts} | 16 +++-- src/commands/{info.js => info.ts} | 14 ++-- src/commands/{lastfm.js => lastfm.ts} | 25 ++++--- src/commands/{main.js => main.ts} | 14 ++-- src/commands/{modarchive.js => modarchive.ts} | 27 +++++--- src/commands/{ponyapi.js => ponyapi.ts} | 67 +++++++++++++++---- src/commands/quotes.js | 28 -------- src/commands/quotes.ts | 32 +++++++++ src/commands/{randompony.js => randompony.ts} | 16 +++-- src/commands/{weather.js => weather.ts} | 16 +++-- src/commands/wiki.js | 36 ---------- src/commands/wiki.ts | 38 +++++++++++ src/commands/{youtube.js => youtube.ts} | 31 +++++---- src/plugins/{checklang.js => checklang.ts} | 4 +- src/plugins/verifyInput.js | 14 ---- src/plugins/verifyInput.ts | 10 +++ .../{ytDlpWrapper.js => ytDlpWrapper.ts} | 8 +-- 32 files changed, 333 insertions(+), 246 deletions(-) rename config.env.example => .env.example (100%) rename src/{bot.js => bot.ts} (77%) rename src/commands/{animal.js => animal.ts} (91%) rename src/commands/{codename.js => codename.ts} (73%) rename src/commands/{crew.js => crew.ts} (95%) rename src/commands/{fun.js => fun.ts} (86%) rename src/commands/{gsmarena.js => gsmarena.ts} (91%) rename src/commands/{help.js => help.ts} (85%) rename src/commands/{http.js => http.ts} (84%) rename src/commands/{info.js => info.ts} (85%) rename src/commands/{lastfm.js => lastfm.ts} (92%) rename src/commands/{main.js => main.ts} (60%) rename src/commands/{modarchive.js => modarchive.ts} (73%) rename src/commands/{ponyapi.js => ponyapi.ts} (86%) delete mode 100644 src/commands/quotes.js create mode 100644 src/commands/quotes.ts rename src/commands/{randompony.js => randompony.ts} (72%) rename src/commands/{weather.js => weather.ts} (90%) delete mode 100644 src/commands/wiki.js create mode 100644 src/commands/wiki.ts rename src/commands/{youtube.js => youtube.ts} (89%) rename src/plugins/{checklang.js => checklang.ts} (94%) delete mode 100644 src/plugins/verifyInput.js create mode 100644 src/plugins/verifyInput.ts rename src/plugins/{ytDlpWrapper.js => ytDlpWrapper.ts} (91%) diff --git a/.dockerignore b/.dockerignore index ba231c9..33e390a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,6 +3,5 @@ npm-debug.log .git .gitignore .env -config.env *.md !README.md \ No newline at end of file diff --git a/config.env.example b/.env.example similarity index 100% rename from config.env.example rename to .env.example diff --git a/.gitignore b/.gitignore index ba85ba8..6b42f1f 100644 --- a/.gitignore +++ b/.gitignore @@ -136,11 +136,12 @@ dist lastfm.json sw-blocklist.txt package-lock.json -bun.lock -bun.lockb tmp/ # Executables *.exe yt-dlp -ffmpeg \ No newline at end of file +ffmpeg + +# Bun +bun.lock* \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 473f9b7..7971682 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,6 @@ COPY . . RUN chmod +x /usr/src/app/src/plugins/yt-dlp/yt-dlp -VOLUME /usr/src/app/config.env +VOLUME /usr/src/app/.env CMD ["npm", "start"] \ No newline at end of file diff --git a/README.md b/README.md index 2c5f02a..9435a9a 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ First, clone the repo with Git: git clone --recurse-submodules https://github.com/ABOCN/TelegramBot ``` -Next, inside the repository directory, create a `config.env` file with some content, which you can see the [example .env file](config.env.example) to fill info with. To see the meaning of each one, see [the Functions section](#configenv-functions). +Next, inside the repository directory, create an `.env` file with some content, which you can see the [example .env file](.env.example) to fill info with. To see the meaning of each one, see [the Functions section](#env-functions). After editing the file, save all changes and run the bot with ``bun start``. @@ -48,7 +48,7 @@ You can also run Kowalski using Docker, which simplifies the setup process. Make ### Using Docker Compose -1. **Make sure to setup your `config.env` file first!** +1. **Make sure to setup your `.env` file first!** 2. **Run the container** @@ -60,7 +60,7 @@ You can also run Kowalski using Docker, which simplifies the setup process. Make If you prefer to use Docker directly, you can use these instructions instead. -1. **Make sure to setup your `config.env` file first!** +1. **Make sure to setup your `.env` file first!** 2. **Build the image** @@ -71,13 +71,13 @@ If you prefer to use Docker directly, you can use these instructions instead. 3. **Run the container** ```bash - docker run -d --name kowalski --restart unless-stopped -v $(pwd)/config.env:/usr/src/app/config.env:ro kowalski + docker run -d --name kowalski --restart unless-stopped -v $(pwd)/.env:/usr/src/app/.env:ro kowalski ``` -## config.env Functions +## .env Functions > [!IMPORTANT] -> Take care of your ``config.env`` file, as it is so much important and needs to be secret (like your passwords), as anyone can do whatever they want to the bot with this token! +> Take care of your ``.env`` file, as it is so much important and needs to be secret (like your passwords), as anyone can do whatever they want to the bot with this token! - **botSource**: Put the link to your bot source code. - **botPrivacy**: Put the link to your bot privacy policy. diff --git a/docker-compose.yml b/docker-compose.yml index 981d90a..0aab44a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,6 @@ services: container_name: kowalski restart: unless-stopped volumes: - - ./config.env:/usr/src/app/config.env:ro + - ./.env:/usr/src/app/.env:ro environment: - NODE_ENV=production \ No newline at end of file diff --git a/nodemon.json b/nodemon.json index d7508b0..918bcb8 100644 --- a/nodemon.json +++ b/nodemon.json @@ -1,3 +1,6 @@ { - "ignore": ["src/props/*.json", "src/props/*.txt"] + "ignore": ["src/props/*.json", "src/props/*.txt"], + "watch": ["src"], + "ext": "ts,js", + "exec": "bun src/bot.ts" } \ No newline at end of file diff --git a/package.json b/package.json index 379cc96..a9dab99 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ }, "dependencies": { "@dotenvx/dotenvx": "^1.28.0", + "@types/node": "^22.15.0", "axios": "^1.7.9", "node-html-parser": "^7.0.1", "nodemon": "^3.1.7", diff --git a/src/bot.js b/src/bot.ts similarity index 77% rename from src/bot.js rename to src/bot.ts index f053de7..3422e56 100644 --- a/src/bot.js +++ b/src/bot.ts @@ -1,13 +1,13 @@ -const { Telegraf } = require('telegraf'); -const path = require('path'); -const fs = require('fs'); -const { isOnSpamWatch } = require('./spamwatch/spamwatch.js'); -require('@dotenvx/dotenvx').config({ path: "config.env" }); -require('./plugins/ytDlpWrapper.js'); +import { Telegraf } from 'telegraf'; +import path from 'path'; +import fs from 'fs'; +import { isOnSpamWatch } from './spamwatch/spamwatch'; +import '@dotenvx/dotenvx'; +import './plugins/ytDlpWrapper'; // Ensures bot token is set, and not default value if (!process.env.botToken || process.env.botToken === 'InsertYourBotTokenHere') { - console.error('Bot token is not set. Please set the bot token in the config.env file.') + console.error('Bot token is not set. Please set the bot token in the .env file.') process.exit(1) } @@ -19,10 +19,13 @@ const loadCommands = () => { const commandsPath = path.join(__dirname, 'commands'); try { - const files = fs.readdirSync(commandsPath); + const files = fs.readdirSync(commandsPath) + .filter(file => file.endsWith('.ts') || file.endsWith('.js')); + files.forEach((file) => { try { - const command = require(path.join(commandsPath, file)); + const commandPath = path.join(commandsPath, file); + const command = require(commandPath).default || require(commandPath); if (typeof command === 'function') { command(bot, isOnSpamWatch); } @@ -43,7 +46,7 @@ const startBot = async () => { restartCount = 0; } catch (error) { console.error('Failed to start bot:', error.message); - if (restartCount < maxRetries) { + if (restartCount < Number(maxRetries)) { restartCount++; console.log(`Retrying to start bot... Attempt ${restartCount}`); setTimeout(startBot, 5000); diff --git a/src/commands/animal.js b/src/commands/animal.ts similarity index 91% rename from src/commands/animal.js rename to src/commands/animal.ts index 332e0e3..b3e0dd1 100644 --- a/src/commands/animal.js +++ b/src/commands/animal.ts @@ -1,10 +1,12 @@ -const Resources = require('../props/resources.json'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -const axios = require("axios"); +import Resources from '../props/resources.json'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import axios from 'axios'; -module.exports = (bot) => { +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +export default (bot) => { bot.command("duck", spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); try { diff --git a/src/commands/codename.js b/src/commands/codename.ts similarity index 73% rename from src/commands/codename.js rename to src/commands/codename.ts index 138ae51..ed0844e 100644 --- a/src/commands/codename.js +++ b/src/commands/codename.ts @@ -1,11 +1,13 @@ -const Resources = require('../props/resources.json'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -const axios = require('axios'); -const { verifyInput } = require('../plugins/verifyInput.js'); +import Resources from '../props/resources.json'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import axios from 'axios'; +import verifyInput from '../plugins/verifyInput'; -async function getDeviceList() { +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +async function getDeviceList({ Strings, ctx }) { try { const response = await axios.get(Resources.codenameApi); return response.data @@ -20,7 +22,7 @@ async function getDeviceList() { } } -module.exports = (bot) => { +export default (bot) => { bot.command(['codename', 'whatis'], spamwatchMiddleware, async (ctx) => { const userInput = ctx.message.text.split(" ").slice(1).join(" "); const Strings = getStrings(ctx.from.language_code); @@ -30,7 +32,7 @@ module.exports = (bot) => { return; } - const jsonRes = await getDeviceList() + const jsonRes = await getDeviceList({ Strings, ctx }) const phoneSearch = Object.keys(jsonRes).find((codename) => codename === userInput); if (!phoneSearch) { diff --git a/src/commands/crew.js b/src/commands/crew.ts similarity index 95% rename from src/commands/crew.js rename to src/commands/crew.ts index e2282ea..3ae431e 100644 --- a/src/commands/crew.js +++ b/src/commands/crew.ts @@ -1,9 +1,11 @@ -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -const os = require('os'); -const { exec } = require('child_process'); -const { error } = require('console'); +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import os from 'os'; +import { exec } from 'child_process'; +import { error } from 'console'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); function getGitCommitHash() { return new Promise((resolve, reject) => { @@ -74,7 +76,7 @@ async function handleAdminCommand(ctx, action, successMessage, errorMessage) { } } -module.exports = (bot) => { +export default (bot) => { bot.command('getbotstats', spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); handleAdminCommand(ctx, async () => { diff --git a/src/commands/fun.js b/src/commands/fun.ts similarity index 86% rename from src/commands/fun.js rename to src/commands/fun.ts index 0c64bbe..b4dcef8 100644 --- a/src/commands/fun.js +++ b/src/commands/fun.ts @@ -1,7 +1,9 @@ -const Resources = require('../props/resources.json'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); +import Resources from '../props/resources.json'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); function sendRandomReply(ctx, gifUrl, textKey) { const Strings = getStrings(ctx.from.language_code); @@ -16,8 +18,8 @@ function sendRandomReply(ctx, gifUrl, textKey) { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id }).catch(err => { - gifErr = gifErr.replace('{err}', err); - ctx.reply(Strings.gifErr, { + const gifErr = Strings.gifErr.replace('{err}', err); + ctx.reply(gifErr, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id }); @@ -51,7 +53,7 @@ function getRandomInt(max) { return Math.floor(Math.random() * (max + 1)); } -module.exports = (bot) => { +export default (bot) => { bot.command('random', spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); const randomValue = getRandomInt(11); diff --git a/src/commands/gsmarena.js b/src/commands/gsmarena.ts similarity index 91% rename from src/commands/gsmarena.js rename to src/commands/gsmarena.ts index 23478c3..43a20ed 100644 --- a/src/commands/gsmarena.js +++ b/src/commands/gsmarena.ts @@ -4,18 +4,23 @@ // 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('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import axios from 'axios'; +import { parse } from 'node-html-parser'; -const axios = require('axios'); -const { parse } = require('node-html-parser'); +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); -class PhoneSearchResult { - constructor(name, url) { - this.name = name; - this.url = url; - Object.freeze(this); - } +interface PhoneSearchResult { + name: string; + url: string; +} + +interface PhoneDetails { + specs: Record>; + name?: string; + url?: string; + picture?: string; } const HEADERS = { @@ -32,7 +37,7 @@ function getDataFromSpecs(specsData, category, attributes) { .join("\n"); } -function parseSpecs(specsData) { +function parseSpecs(specsData: PhoneDetails): PhoneDetails { const categories = { "status": ["Launch", ["Status"]], "network": ["Network", ["Technology"]], @@ -69,7 +74,7 @@ function parseSpecs(specsData) { const [cat, attrs] = categories[key]; acc[key] = getDataFromSpecs(specsData, cat, attrs) || ""; return acc; - }, {}); + }, { specs: {} } as PhoneDetails); parsedData["name"] = specsData.name || ""; parsedData["url"] = specsData.url || ""; @@ -77,7 +82,7 @@ function parseSpecs(specsData) { return parsedData; } -function formatPhone(phone) { +function formatPhone(phone: PhoneDetails) { const formattedPhone = parseSpecs(phone); const attributesDict = { "Status": "status", @@ -132,7 +137,7 @@ async function fetchHtml(url) { } } -async function searchPhone(phone) { +async function searchPhone(phone: string): Promise { try { const searchUrl = `https://m.gsmarena.com/results.php3?sQuickSearch=yes&sName=${encodeURIComponent(phone)}`; const htmlContent = await fetchHtml(searchUrl); @@ -142,7 +147,7 @@ async function searchPhone(phone) { return foundPhones.map((phoneTag) => { const name = phoneTag.querySelector('img')?.getAttribute('title') || ""; const url = phoneTag.querySelector('a')?.getAttribute('href') || ""; - return new PhoneSearchResult(name, url); + return { name, url }; }); } catch (error) { console.error("Error searching for phone:", error); @@ -164,7 +169,7 @@ async function checkPhoneDetails(url) { return { ...specsData, name, picture, url: `https://www.gsmarena.com/${url}` }; } catch (error) { console.error("Error fetching phone details:", error); - return {}; + return { specs: {}, name: "", url: "", picture: "" }; } } @@ -201,7 +206,7 @@ function getUsername(ctx){ return userName; } -module.exports = (bot) => { +export default (bot) => { bot.command(['d', 'device'], spamwatchMiddleware, async (ctx) => { const userId = ctx.from.id; const userName = getUsername(ctx); diff --git a/src/commands/help.js b/src/commands/help.ts similarity index 85% rename from src/commands/help.js rename to src/commands/help.ts index b4cc44b..95ea804 100644 --- a/src/commands/help.js +++ b/src/commands/help.ts @@ -1,6 +1,17 @@ -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +interface MessageOptions { + parse_mode: string; + disable_web_page_preview: boolean; + reply_markup: { + inline_keyboard: { text: any; callback_data: string; }[][]; + }; + reply_to_message_id?: number; +} async function sendHelpMessage(ctx, isEditing) { const Strings = getStrings(ctx.from.language_code); @@ -11,8 +22,8 @@ async function sendHelpMessage(ctx, isEditing) { function getMessageId(ctx) { return ctx.message?.message_id || ctx.callbackQuery?.message?.message_id; }; - const createOptions = (ctx, includeReplyTo = false) => { - const options = { + const createOptions = (ctx, includeReplyTo = false): MessageOptions => { + const options: MessageOptions = { parse_mode: 'Markdown', disable_web_page_preview: true, reply_markup: { @@ -39,9 +50,9 @@ async function sendHelpMessage(ctx, isEditing) { }; } -module.exports = (bot) => { +export default (bot) => { bot.help(spamwatchMiddleware, async (ctx) => { - await sendHelpMessage(ctx); + await sendHelpMessage(ctx, false); }); bot.command("about", spamwatchMiddleware, async (ctx) => { diff --git a/src/commands/http.js b/src/commands/http.ts similarity index 84% rename from src/commands/http.js rename to src/commands/http.ts index 1382ad6..5e47a49 100644 --- a/src/commands/http.js +++ b/src/commands/http.ts @@ -1,11 +1,13 @@ -const Resources = require('../props/resources.json'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -const axios = require('axios'); -const { verifyInput } = require('../plugins/verifyInput.js'); +import Resources from '../props/resources.json'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import axios from 'axios'; +import verifyInput from '../plugins/verifyInput'; -module.exports = (bot) => { +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +export default (bot) => { bot.command("http", spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); const userInput = ctx.message.text.split(' ')[1]; diff --git a/src/commands/info.js b/src/commands/info.ts similarity index 85% rename from src/commands/info.js rename to src/commands/info.ts index eed4874..a19651c 100644 --- a/src/commands/info.js +++ b/src/commands/info.ts @@ -1,6 +1,8 @@ -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); async function getUserInfo(ctx) { const Strings = getStrings(ctx.from.language_code); @@ -9,7 +11,7 @@ async function getUserInfo(ctx) { lastName = " "; } - userInfo = Strings.userInfo + const userInfo = Strings.userInfo .replace('{userName}', `${ctx.from.first_name} ${lastName}` || Strings.varStrings.varUnknown) .replace('{userId}', ctx.from.id || Strings.varStrings.varUnknown) .replace('{userHandle}', ctx.from.username ? `@${ctx.from.username}` : Strings.varStrings.varNone) @@ -22,7 +24,7 @@ async function getUserInfo(ctx) { async function getChatInfo(ctx) { const Strings = getStrings(ctx.from.language_code); if (ctx.chat.type === 'group' || ctx.chat.type === 'supergroup') { - chatInfo = Strings.chatInfo + const chatInfo = Strings.chatInfo .replace('{chatId}', ctx.chat.id || Strings.varStrings.varUnknown) .replace('{chatName}', ctx.chat.title || Strings.varStrings.varUnknown) .replace('{chatHandle}', ctx.chat.username ? `@${ctx.chat.username}` : Strings.varStrings.varNone) @@ -40,7 +42,7 @@ async function getChatInfo(ctx) { } } -module.exports = (bot) => { +export default (bot) => { bot.command('chatinfo', spamwatchMiddleware, async (ctx) => { const chatInfo = await getChatInfo(ctx); ctx.reply( diff --git a/src/commands/lastfm.js b/src/commands/lastfm.ts similarity index 92% rename from src/commands/lastfm.js rename to src/commands/lastfm.ts index 1b1976f..39d6c8d 100644 --- a/src/commands/lastfm.js +++ b/src/commands/lastfm.ts @@ -1,9 +1,11 @@ -const Resources = require('../props/resources.json'); -const fs = require('fs'); -const axios = require('axios'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); +import Resources from '../props/resources.json'; +import fs from 'fs'; +import axios from 'axios'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); const scrobbler_url = Resources.lastFmApi; const api_key = process.env.lastKey; @@ -35,7 +37,7 @@ function saveUsers() { } } -async function getFromMusicBrainz(mbid) { +async function getFromMusicBrainz(mbid: string) { try { const response = await axios.get(`${Resources.musicBrainzApi}${mbid}`); const imgObjLarge = response.data.images[0]?.thumbnails?.['1200']; @@ -58,7 +60,7 @@ function getFromLast(track) { return imageUrl; } -module.exports = (bot) => { +export default (bot) => { loadUsers(); bot.command('setuser', (ctx) => { @@ -149,7 +151,7 @@ module.exports = (bot) => { const artistUrl = `https://www.last.fm/music/${encodeURIComponent(artistName)}`; const userUrl = `https://www.last.fm/user/${encodeURIComponent(lastfmUser)}`; - let num_plays = ''; + let num_plays = 0; try { const response_plays = await axios.get(scrobbler_url, { params: { @@ -164,11 +166,8 @@ module.exports = (bot) => { 'User-Agent': `@${botInfo.username}-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.lastFm.apiErr diff --git a/src/commands/main.js b/src/commands/main.ts similarity index 60% rename from src/commands/main.js rename to src/commands/main.ts index 975762d..2729173 100644 --- a/src/commands/main.js +++ b/src/commands/main.ts @@ -1,9 +1,11 @@ -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; -module.exports = (bot) => { - bot.start(spamwatchMiddleware, async (ctx) => { +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +export default (bot: any) => { + bot.start(spamwatchMiddleware, async (ctx: any) => { const Strings = getStrings(ctx.from.language_code); const botInfo = await ctx.telegram.getMe(); const startMsg = Strings.botWelcome.replace(/{botName}/g, botInfo.first_name); @@ -14,7 +16,7 @@ module.exports = (bot) => { }); }); - bot.command('privacy', spamwatchMiddleware, async (ctx) => { + bot.command('privacy', spamwatchMiddleware, async (ctx: any) => { const Strings = getStrings(ctx.from.language_code); const message = Strings.botPrivacy.replace("{botPrivacy}", process.env.botPrivacy); diff --git a/src/commands/modarchive.js b/src/commands/modarchive.ts similarity index 73% rename from src/commands/modarchive.js rename to src/commands/modarchive.ts index 4e89370..eac76a8 100644 --- a/src/commands/modarchive.js +++ b/src/commands/modarchive.ts @@ -1,12 +1,19 @@ -const Resources = require('../props/resources.json'); -const axios = require('axios'); -const fs = require('fs'); -const path = require('path'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); +import Resources from '../props/resources.json'; +import axios from 'axios'; +import fs from 'fs'; +import path from 'path'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; -async function downloadModule(moduleId) { +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +interface ModuleResult { + filePath: string; + fileName: string; +} + +async function downloadModule(moduleId: string): Promise { try { const downloadUrl = `${Resources.modArchiveApi}${moduleId}`; const response = await axios({ @@ -39,12 +46,12 @@ async function downloadModule(moduleId) { } } -module.exports = (bot) => { +export default (bot) => { bot.command(['modarchive', 'tma'], spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); const moduleId = ctx.message.text.split(' ')[1]; - if (moduleId == NaN || null) { + if (Number.isNaN(moduleId) || null) { return ctx.reply(Strings.maInvalidModule, { parse_mode: "Markdown", reply_to_message_id: ctx.message.message_id diff --git a/src/commands/ponyapi.js b/src/commands/ponyapi.ts similarity index 86% rename from src/commands/ponyapi.js rename to src/commands/ponyapi.ts index e5fbf94..dfa2e1c 100644 --- a/src/commands/ponyapi.js +++ b/src/commands/ponyapi.ts @@ -1,15 +1,56 @@ -const Resources = require('../props/resources.json'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -const axios = require("axios"); -const { verifyInput } = require('../plugins/verifyInput.js'); +import Resources from '../props/resources.json'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import axios from 'axios'; +import verifyInput from '../plugins/verifyInput'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +interface Character { + id: string; + name: string; + alias: string; + url: string; + sex: string; + residence: string; + occupation: string; + kind: string; + image: string[]; +} + +interface Episode { + id: string; + name: string; + image: string; + url: string; + season: string; + episode: string; + overall: string; + airdate: string; + storyby: string; + writtenby: string; + storyboard: string; +} + +interface Comic { + id: string; + name: string; + series: string; + image: string; + url: string; + writer: string; + artist: string; + colorist: string; + letterer: string; + editor: string; +} function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } -module.exports = (bot) => { +export default (bot) => { bot.command("mlp", spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); @@ -34,11 +75,11 @@ module.exports = (bot) => { try { const response = await axios(apiUrl); - const charactersArray = []; + const charactersArray: Character[] = []; if (Array.isArray(response.data.data)) { response.data.data.forEach(character => { - let aliases = []; + let aliases: string[] = []; if (character.alias) { if (typeof character.alias === 'string') { aliases.push(character.alias); @@ -107,7 +148,7 @@ module.exports = (bot) => { try { const response = await axios(apiUrl); - const episodeArray = []; + const episodeArray: Episode[] = []; if (Array.isArray(response.data.data)) { response.data.data.forEach(episode => { @@ -175,15 +216,15 @@ module.exports = (bot) => { try { const response = await axios(apiUrl); - const comicArray = []; + const comicArray: Comic[] = []; if (Array.isArray(response.data.data)) { response.data.data.forEach(comic => { - let letterers = []; + let letterers: string[] = []; if (comic.letterer) { if (typeof comic.letterer === 'string') { letterers.push(comic.letterer); } else if (Array.isArray(comic.letterer)) { - letterers = aliases.concat(comic.letterer); + letterers = letterers.concat(comic.letterer); } } comicArray.push({ diff --git a/src/commands/quotes.js b/src/commands/quotes.js deleted file mode 100644 index ff31469..0000000 --- a/src/commands/quotes.js +++ /dev/null @@ -1,28 +0,0 @@ -// const Resources = require('../props/resources.json'); -// const { getStrings } = require('../plugins/checkLang.js'); -// const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -// const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -// const escape = require('markdown-escape'); -// 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(Resources.quoteApi); -// const data = response.data; - -// ctx.reply(escape(`${escape(Strings.quoteResult)}\n> *${escape(data.quote)}*\n_${escape(data.author)}_`), { -// reply_to_message_id: ctx.message.message_id, -// parse_mode: 'Markdown' -// }); -// } catch (error) { -// console.error(error); -// ctx.reply(Strings.quoteErr, { -// reply_to_message_id: ctx.message.id, -// parse_mode: 'MarkdownV2' -// }); -// }; -// }); -// }; diff --git a/src/commands/quotes.ts b/src/commands/quotes.ts new file mode 100644 index 0000000..4c59f2a --- /dev/null +++ b/src/commands/quotes.ts @@ -0,0 +1,32 @@ +/* +import Resources from '../props/resources.json'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import escape from 'markdown-escape'; +import axios from 'axios'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +export default (bot) => { + bot.command("quote", spamwatchMiddleware, async (ctx) => { + const Strings = getStrings(ctx.from.language_code); + + try { + const response = await axios.get(Resources.quoteApi); + const data = response.data; + + ctx.reply(escape(`${escape(Strings.quoteResult)}\n> *${escape(data.quote)}*\n_${escape(data.author)}_`), { + reply_to_message_id: ctx.message.message_id, + parse_mode: 'Markdown' + }); + } catch (error) { + console.error(error); + ctx.reply(Strings.quoteErr, { + reply_to_message_id: ctx.message.id, + parse_mode: 'MarkdownV2' + }); + }; + }); +}; +*/ \ No newline at end of file diff --git a/src/commands/randompony.js b/src/commands/randompony.ts similarity index 72% rename from src/commands/randompony.js rename to src/commands/randompony.ts index 1be1e73..0ca140d 100644 --- a/src/commands/randompony.js +++ b/src/commands/randompony.ts @@ -1,15 +1,17 @@ -const Resources = require('../props/resources.json'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -const axios = require("axios"); +import Resources from '../props/resources.json'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import axios from 'axios'; -module.exports = (bot) => { +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); + +export default (bot) => { bot.command(["rpony", "randompony", "mlpart"], spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); try { const response = await axios(Resources.randomPonyApi); - let tags = []; + let tags: string[] = []; if (response.data.pony.tags) { if (typeof response.data.pony.tags === 'string') { diff --git a/src/commands/weather.js b/src/commands/weather.ts similarity index 90% rename from src/commands/weather.js rename to src/commands/weather.ts index be1ebe9..716726c 100644 --- a/src/commands/weather.js +++ b/src/commands/weather.ts @@ -2,12 +2,14 @@ // Copyright (c) 2024 BubbalooTeam. (https://github.com/BubbalooTeam) // Minor code changes by lucmsilva (https://github.com/lucmsilva651) -const Resources = require('../props/resources.json'); -const axios = require('axios'); -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -const { verifyInput } = require('../plugins/verifyInput.js'); +import Resources from '../props/resources.json'; +import axios from 'axios'; +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import verifyInput from '../plugins/verifyInput'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); const statusEmojis = { 0: '⛈', 1: '⛈', 2: '⛈', 3: '⛈', 4: '⛈', 5: '🌨', 6: '🌨', 7: '🌨', @@ -31,7 +33,7 @@ function getLocaleUnit(countryCode) { } } -module.exports = (bot) => { +export default (bot) => { bot.command(['clima', 'weather'], spamwatchMiddleware, async (ctx) => { const userLang = ctx.from.language_code || "en-US"; const Strings = getStrings(userLang); diff --git a/src/commands/wiki.js b/src/commands/wiki.js deleted file mode 100644 index e6f7f2f..0000000 --- a/src/commands/wiki.js +++ /dev/null @@ -1,36 +0,0 @@ -// 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 }); -// }); -// }; diff --git a/src/commands/wiki.ts b/src/commands/wiki.ts new file mode 100644 index 0000000..f6ca6d0 --- /dev/null +++ b/src/commands/wiki.ts @@ -0,0 +1,38 @@ +/* +import axios from "axios"; + +function capitalizeFirstLetter(string: string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +function mediaWikiToMarkdown(input: string) { + 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; +} + +export default (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 }); + }); +}; +*/ \ No newline at end of file diff --git a/src/commands/youtube.js b/src/commands/youtube.ts similarity index 89% rename from src/commands/youtube.js rename to src/commands/youtube.ts index d3fa755..9fa6364 100644 --- a/src/commands/youtube.js +++ b/src/commands/youtube.ts @@ -1,10 +1,12 @@ -const { getStrings } = require('../plugins/checkLang.js'); -const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); -const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); -const { execFile } = require('child_process'); -const os = require('os'); -const fs = require('fs'); -const path = require('path'); +import { getStrings } from '../plugins/checklang'; +import { isOnSpamWatch } from '../spamwatch/spamwatch'; +import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import { execFile } from 'child_process'; +import os from 'os'; +import fs from 'fs'; +import path from 'path'; + +const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); const ytDlpPaths = { linux: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp'), @@ -28,7 +30,7 @@ const getFfmpegPath = () => { return ffmpegPaths[platform] || ffmpegPaths.linux; }; -const downloadFromYoutube = async (command, args) => { +const downloadFromYoutube = async (command: string, args: string[]): Promise<{ stdout: string; stderr: string }> => { return new Promise((resolve, reject) => { execFile(command, args, (error, stdout, stderr) => { if (error) { @@ -40,8 +42,8 @@ const downloadFromYoutube = async (command, args) => { }); }; -const getApproxSize = async (command, videoUrl) => { - let args = []; +const getApproxSize = async (command: string, videoUrl: string): Promise => { + let args: string[] = []; if (fs.existsSync(path.resolve(__dirname, "../props/cookies.txt"))) { args = [videoUrl, '--compat-opt', 'manifest-filesize-approx', '-O', 'filesize_approx', '--cookies', path.resolve(__dirname, "../props/cookies.txt")]; } else { @@ -60,7 +62,7 @@ const getApproxSize = async (command, videoUrl) => { } }; -module.exports = (bot) => { +export default (bot) => { bot.command(['yt', 'ytdl', 'sdl', 'video', 'dl'], spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); const ytDlpPath = getYtDlpPath(); @@ -198,11 +200,8 @@ module.exports = (bot) => { } } catch (error) { const errMsg = Strings.ytDownload.uploadErr.replace("{error}", error) - await ctx.telegram.editMessageText( - ctx.chat.id, - downloadingMessage.message_id, - null, - errMsg, { + // will no longer edit the message as the message context is not outside the try block + await ctx.reply(errMsg, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id, }, diff --git a/src/plugins/checklang.js b/src/plugins/checklang.ts similarity index 94% rename from src/plugins/checklang.js rename to src/plugins/checklang.ts index bd8f126..a8d1b79 100644 --- a/src/plugins/checklang.js +++ b/src/plugins/checklang.ts @@ -17,6 +17,4 @@ function getStrings(languageCode) { } } -module.exports = { - getStrings -}; \ No newline at end of file +export { getStrings }; \ No newline at end of file diff --git a/src/plugins/verifyInput.js b/src/plugins/verifyInput.js deleted file mode 100644 index feae352..0000000 --- a/src/plugins/verifyInput.js +++ /dev/null @@ -1,14 +0,0 @@ -function verifyInput(ctx, userInput, message, verifyNaN = false) { - if (!userInput || (verifyNaN && isNaN(userInput))) { - ctx.reply(message, { - parse_mode: "Markdown", - reply_to_message_id: ctx.message.message_id - }); - return true; - } - return false; -} - -module.exports = { - verifyInput -}; \ No newline at end of file diff --git a/src/plugins/verifyInput.ts b/src/plugins/verifyInput.ts new file mode 100644 index 0000000..b1355fd --- /dev/null +++ b/src/plugins/verifyInput.ts @@ -0,0 +1,10 @@ +export default function verifyInput(ctx: any, userInput: string, message: string, verifyNaN = false) { + if (!userInput || (verifyNaN && isNaN(Number(userInput)))) { // not sure why isNaN is used here, but the input should be a number + ctx.reply(message, { + parse_mode: "Markdown", + reply_to_message_id: ctx.message.message_id + }); + return true; + } + return false; +} diff --git a/src/plugins/ytDlpWrapper.js b/src/plugins/ytDlpWrapper.ts similarity index 91% rename from src/plugins/ytDlpWrapper.js rename to src/plugins/ytDlpWrapper.ts index 8d2298e..2313b4c 100644 --- a/src/plugins/ytDlpWrapper.js +++ b/src/plugins/ytDlpWrapper.ts @@ -1,7 +1,7 @@ -const axios = require('axios'); -const fs = require('fs'); -const path = require('path'); -const os = require('os'); +import axios from 'axios'; +import fs from 'fs'; +import path from 'path'; +import os from 'os'; const downloadDir = path.resolve(__dirname, 'yt-dlp');