rf: js -> ts

This commit is contained in:
Aidan 2025-04-24 18:49:51 -04:00
parent 33c9120361
commit efadb51905
32 changed files with 333 additions and 246 deletions

View File

@ -3,6 +3,5 @@ npm-debug.log
.git .git
.gitignore .gitignore
.env .env
config.env
*.md *.md
!README.md !README.md

5
.gitignore vendored
View File

@ -136,11 +136,12 @@ dist
lastfm.json lastfm.json
sw-blocklist.txt sw-blocklist.txt
package-lock.json package-lock.json
bun.lock
bun.lockb
tmp/ tmp/
# Executables # Executables
*.exe *.exe
yt-dlp yt-dlp
ffmpeg ffmpeg
# Bun
bun.lock*

View File

@ -13,6 +13,6 @@ COPY . .
RUN chmod +x /usr/src/app/src/plugins/yt-dlp/yt-dlp 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"] CMD ["npm", "start"]

View File

@ -27,7 +27,7 @@ First, clone the repo with Git:
git clone --recurse-submodules https://github.com/ABOCN/TelegramBot 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``. 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 ### 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** 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. 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** 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** 3. **Run the container**
```bash ```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] > [!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. - **botSource**: Put the link to your bot source code.
- **botPrivacy**: Put the link to your bot privacy policy. - **botPrivacy**: Put the link to your bot privacy policy.

View File

@ -4,6 +4,6 @@ services:
container_name: kowalski container_name: kowalski
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- ./config.env:/usr/src/app/config.env:ro - ./.env:/usr/src/app/.env:ro
environment: environment:
- NODE_ENV=production - NODE_ENV=production

View File

@ -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"
} }

View File

@ -4,6 +4,7 @@
}, },
"dependencies": { "dependencies": {
"@dotenvx/dotenvx": "^1.28.0", "@dotenvx/dotenvx": "^1.28.0",
"@types/node": "^22.15.0",
"axios": "^1.7.9", "axios": "^1.7.9",
"node-html-parser": "^7.0.1", "node-html-parser": "^7.0.1",
"nodemon": "^3.1.7", "nodemon": "^3.1.7",

View File

@ -1,13 +1,13 @@
const { Telegraf } = require('telegraf'); import { Telegraf } from 'telegraf';
const path = require('path'); import path from 'path';
const fs = require('fs'); import fs from 'fs';
const { isOnSpamWatch } = require('./spamwatch/spamwatch.js'); import { isOnSpamWatch } from './spamwatch/spamwatch';
require('@dotenvx/dotenvx').config({ path: "config.env" }); import '@dotenvx/dotenvx';
require('./plugins/ytDlpWrapper.js'); import './plugins/ytDlpWrapper';
// Ensures bot token is set, and not default value // Ensures bot token is set, and not default value
if (!process.env.botToken || process.env.botToken === 'InsertYourBotTokenHere') { 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) process.exit(1)
} }
@ -19,10 +19,13 @@ const loadCommands = () => {
const commandsPath = path.join(__dirname, 'commands'); const commandsPath = path.join(__dirname, 'commands');
try { try {
const files = fs.readdirSync(commandsPath); const files = fs.readdirSync(commandsPath)
.filter(file => file.endsWith('.ts') || file.endsWith('.js'));
files.forEach((file) => { files.forEach((file) => {
try { 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') { if (typeof command === 'function') {
command(bot, isOnSpamWatch); command(bot, isOnSpamWatch);
} }
@ -43,7 +46,7 @@ const startBot = async () => {
restartCount = 0; restartCount = 0;
} catch (error) { } catch (error) {
console.error('Failed to start bot:', error.message); console.error('Failed to start bot:', error.message);
if (restartCount < maxRetries) { if (restartCount < Number(maxRetries)) {
restartCount++; restartCount++;
console.log(`Retrying to start bot... Attempt ${restartCount}`); console.log(`Retrying to start bot... Attempt ${restartCount}`);
setTimeout(startBot, 5000); setTimeout(startBot, 5000);

View File

@ -1,10 +1,12 @@
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const axios = require("axios"); import axios from 'axios';
module.exports = (bot) => { const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
export default (bot) => {
bot.command("duck", spamwatchMiddleware, async (ctx) => { bot.command("duck", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
try { try {

View File

@ -1,11 +1,13 @@
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const axios = require('axios'); import axios from 'axios';
const { verifyInput } = require('../plugins/verifyInput.js'); import verifyInput from '../plugins/verifyInput';
async function getDeviceList() { const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
async function getDeviceList({ Strings, ctx }) {
try { try {
const response = await axios.get(Resources.codenameApi); const response = await axios.get(Resources.codenameApi);
return response.data return response.data
@ -20,7 +22,7 @@ async function getDeviceList() {
} }
} }
module.exports = (bot) => { export default (bot) => {
bot.command(['codename', 'whatis'], spamwatchMiddleware, async (ctx) => { bot.command(['codename', 'whatis'], spamwatchMiddleware, async (ctx) => {
const userInput = ctx.message.text.split(" ").slice(1).join(" "); const userInput = ctx.message.text.split(" ").slice(1).join(" ");
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
@ -30,7 +32,7 @@ module.exports = (bot) => {
return; return;
} }
const jsonRes = await getDeviceList() const jsonRes = await getDeviceList({ Strings, ctx })
const phoneSearch = Object.keys(jsonRes).find((codename) => codename === userInput); const phoneSearch = Object.keys(jsonRes).find((codename) => codename === userInput);
if (!phoneSearch) { if (!phoneSearch) {

View File

@ -1,9 +1,11 @@
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const os = require('os'); import os from 'os';
const { exec } = require('child_process'); import { exec } from 'child_process';
const { error } = require('console'); import { error } from 'console';
const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
function getGitCommitHash() { function getGitCommitHash() {
return new Promise((resolve, reject) => { 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) => { bot.command('getbotstats', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
handleAdminCommand(ctx, async () => { handleAdminCommand(ctx, async () => {

View File

@ -1,7 +1,9 @@
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
function sendRandomReply(ctx, gifUrl, textKey) { function sendRandomReply(ctx, gifUrl, textKey) {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
@ -16,8 +18,8 @@ function sendRandomReply(ctx, gifUrl, textKey) {
parse_mode: 'Markdown', parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id reply_to_message_id: ctx.message.message_id
}).catch(err => { }).catch(err => {
gifErr = gifErr.replace('{err}', err); const gifErr = Strings.gifErr.replace('{err}', err);
ctx.reply(Strings.gifErr, { ctx.reply(gifErr, {
parse_mode: 'Markdown', parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id reply_to_message_id: ctx.message.message_id
}); });
@ -51,7 +53,7 @@ function getRandomInt(max) {
return Math.floor(Math.random() * (max + 1)); return Math.floor(Math.random() * (max + 1));
} }
module.exports = (bot) => { export default (bot) => {
bot.command('random', spamwatchMiddleware, async (ctx) => { bot.command('random', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
const randomValue = getRandomInt(11); const randomValue = getRandomInt(11);

View File

@ -4,18 +4,23 @@
// With some help from GPT (I don't really like AI but whatever) // 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! // If this were a kang, I would not be giving credits to him!
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
import axios from 'axios';
import { parse } from 'node-html-parser';
const axios = require('axios'); const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
const { parse } = require('node-html-parser');
class PhoneSearchResult { interface PhoneSearchResult {
constructor(name, url) { name: string;
this.name = name; url: string;
this.url = url;
Object.freeze(this);
} }
interface PhoneDetails {
specs: Record<string, Record<string, string>>;
name?: string;
url?: string;
picture?: string;
} }
const HEADERS = { const HEADERS = {
@ -32,7 +37,7 @@ function getDataFromSpecs(specsData, category, attributes) {
.join("\n"); .join("\n");
} }
function parseSpecs(specsData) { function parseSpecs(specsData: PhoneDetails): PhoneDetails {
const categories = { const categories = {
"status": ["Launch", ["Status"]], "status": ["Launch", ["Status"]],
"network": ["Network", ["Technology"]], "network": ["Network", ["Technology"]],
@ -69,7 +74,7 @@ function parseSpecs(specsData) {
const [cat, attrs] = categories[key]; const [cat, attrs] = categories[key];
acc[key] = getDataFromSpecs(specsData, cat, attrs) || ""; acc[key] = getDataFromSpecs(specsData, cat, attrs) || "";
return acc; return acc;
}, {}); }, { specs: {} } as PhoneDetails);
parsedData["name"] = specsData.name || ""; parsedData["name"] = specsData.name || "";
parsedData["url"] = specsData.url || ""; parsedData["url"] = specsData.url || "";
@ -77,7 +82,7 @@ function parseSpecs(specsData) {
return parsedData; return parsedData;
} }
function formatPhone(phone) { function formatPhone(phone: PhoneDetails) {
const formattedPhone = parseSpecs(phone); const formattedPhone = parseSpecs(phone);
const attributesDict = { const attributesDict = {
"Status": "status", "Status": "status",
@ -132,7 +137,7 @@ async function fetchHtml(url) {
} }
} }
async function searchPhone(phone) { async function searchPhone(phone: string): Promise<PhoneSearchResult[]> {
try { try {
const searchUrl = `https://m.gsmarena.com/results.php3?sQuickSearch=yes&sName=${encodeURIComponent(phone)}`; const searchUrl = `https://m.gsmarena.com/results.php3?sQuickSearch=yes&sName=${encodeURIComponent(phone)}`;
const htmlContent = await fetchHtml(searchUrl); const htmlContent = await fetchHtml(searchUrl);
@ -142,7 +147,7 @@ async function searchPhone(phone) {
return foundPhones.map((phoneTag) => { return foundPhones.map((phoneTag) => {
const name = phoneTag.querySelector('img')?.getAttribute('title') || ""; const name = phoneTag.querySelector('img')?.getAttribute('title') || "";
const url = phoneTag.querySelector('a')?.getAttribute('href') || ""; const url = phoneTag.querySelector('a')?.getAttribute('href') || "";
return new PhoneSearchResult(name, url); return { name, url };
}); });
} catch (error) { } catch (error) {
console.error("Error searching for phone:", 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}` }; return { ...specsData, name, picture, url: `https://www.gsmarena.com/${url}` };
} catch (error) { } catch (error) {
console.error("Error fetching phone details:", error); console.error("Error fetching phone details:", error);
return {}; return { specs: {}, name: "", url: "", picture: "" };
} }
} }
@ -201,7 +206,7 @@ function getUsername(ctx){
return userName; return userName;
} }
module.exports = (bot) => { export default (bot) => {
bot.command(['d', 'device'], spamwatchMiddleware, async (ctx) => { bot.command(['d', 'device'], spamwatchMiddleware, async (ctx) => {
const userId = ctx.from.id; const userId = ctx.from.id;
const userName = getUsername(ctx); const userName = getUsername(ctx);

View File

@ -1,6 +1,17 @@
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); 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) { async function sendHelpMessage(ctx, isEditing) {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
@ -11,8 +22,8 @@ async function sendHelpMessage(ctx, isEditing) {
function getMessageId(ctx) { function getMessageId(ctx) {
return ctx.message?.message_id || ctx.callbackQuery?.message?.message_id; return ctx.message?.message_id || ctx.callbackQuery?.message?.message_id;
}; };
const createOptions = (ctx, includeReplyTo = false) => { const createOptions = (ctx, includeReplyTo = false): MessageOptions => {
const options = { const options: MessageOptions = {
parse_mode: 'Markdown', parse_mode: 'Markdown',
disable_web_page_preview: true, disable_web_page_preview: true,
reply_markup: { reply_markup: {
@ -39,9 +50,9 @@ async function sendHelpMessage(ctx, isEditing) {
}; };
} }
module.exports = (bot) => { export default (bot) => {
bot.help(spamwatchMiddleware, async (ctx) => { bot.help(spamwatchMiddleware, async (ctx) => {
await sendHelpMessage(ctx); await sendHelpMessage(ctx, false);
}); });
bot.command("about", spamwatchMiddleware, async (ctx) => { bot.command("about", spamwatchMiddleware, async (ctx) => {

View File

@ -1,11 +1,13 @@
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const axios = require('axios'); import axios from 'axios';
const { verifyInput } = require('../plugins/verifyInput.js'); import verifyInput from '../plugins/verifyInput';
module.exports = (bot) => { const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
export default (bot) => {
bot.command("http", spamwatchMiddleware, async (ctx) => { bot.command("http", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
const userInput = ctx.message.text.split(' ')[1]; const userInput = ctx.message.text.split(' ')[1];

View File

@ -1,6 +1,8 @@
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
async function getUserInfo(ctx) { async function getUserInfo(ctx) {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
@ -9,7 +11,7 @@ async function getUserInfo(ctx) {
lastName = " "; lastName = " ";
} }
userInfo = Strings.userInfo const userInfo = Strings.userInfo
.replace('{userName}', `${ctx.from.first_name} ${lastName}` || Strings.varStrings.varUnknown) .replace('{userName}', `${ctx.from.first_name} ${lastName}` || Strings.varStrings.varUnknown)
.replace('{userId}', ctx.from.id || Strings.varStrings.varUnknown) .replace('{userId}', ctx.from.id || Strings.varStrings.varUnknown)
.replace('{userHandle}', ctx.from.username ? `@${ctx.from.username}` : Strings.varStrings.varNone) .replace('{userHandle}', ctx.from.username ? `@${ctx.from.username}` : Strings.varStrings.varNone)
@ -22,7 +24,7 @@ async function getUserInfo(ctx) {
async function getChatInfo(ctx) { async function getChatInfo(ctx) {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
if (ctx.chat.type === 'group' || ctx.chat.type === 'supergroup') { 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('{chatId}', ctx.chat.id || Strings.varStrings.varUnknown)
.replace('{chatName}', ctx.chat.title || Strings.varStrings.varUnknown) .replace('{chatName}', ctx.chat.title || Strings.varStrings.varUnknown)
.replace('{chatHandle}', ctx.chat.username ? `@${ctx.chat.username}` : Strings.varStrings.varNone) .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) => { bot.command('chatinfo', spamwatchMiddleware, async (ctx) => {
const chatInfo = await getChatInfo(ctx); const chatInfo = await getChatInfo(ctx);
ctx.reply( ctx.reply(

View File

@ -1,9 +1,11 @@
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const fs = require('fs'); import fs from 'fs';
const axios = require('axios'); import axios from 'axios';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
const scrobbler_url = Resources.lastFmApi; const scrobbler_url = Resources.lastFmApi;
const api_key = process.env.lastKey; const api_key = process.env.lastKey;
@ -35,7 +37,7 @@ function saveUsers() {
} }
} }
async function getFromMusicBrainz(mbid) { async function getFromMusicBrainz(mbid: string) {
try { try {
const response = await axios.get(`${Resources.musicBrainzApi}${mbid}`); const response = await axios.get(`${Resources.musicBrainzApi}${mbid}`);
const imgObjLarge = response.data.images[0]?.thumbnails?.['1200']; const imgObjLarge = response.data.images[0]?.thumbnails?.['1200'];
@ -58,7 +60,7 @@ function getFromLast(track) {
return imageUrl; return imageUrl;
} }
module.exports = (bot) => { export default (bot) => {
loadUsers(); loadUsers();
bot.command('setuser', (ctx) => { bot.command('setuser', (ctx) => {
@ -149,7 +151,7 @@ module.exports = (bot) => {
const artistUrl = `https://www.last.fm/music/${encodeURIComponent(artistName)}`; const artistUrl = `https://www.last.fm/music/${encodeURIComponent(artistName)}`;
const userUrl = `https://www.last.fm/user/${encodeURIComponent(lastfmUser)}`; const userUrl = `https://www.last.fm/user/${encodeURIComponent(lastfmUser)}`;
let num_plays = ''; let num_plays = 0;
try { try {
const response_plays = await axios.get(scrobbler_url, { const response_plays = await axios.get(scrobbler_url, {
params: { params: {
@ -164,11 +166,8 @@ module.exports = (bot) => {
'User-Agent': `@${botInfo.username}-node-telegram-bot` 'User-Agent': `@${botInfo.username}-node-telegram-bot`
} }
}); });
num_plays = response_plays.data.track.userplaycount;
if (!num_plays || num_plays === undefined) { num_plays = response_plays.data.track.userplaycount;
num_plays = 0;
};
} catch (err) { } catch (err) {
console.log(err) console.log(err)
const message = Strings.lastFm.apiErr const message = Strings.lastFm.apiErr

View File

@ -1,9 +1,11 @@
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
module.exports = (bot) => { const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
bot.start(spamwatchMiddleware, async (ctx) => {
export default (bot: any) => {
bot.start(spamwatchMiddleware, async (ctx: any) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
const botInfo = await ctx.telegram.getMe(); const botInfo = await ctx.telegram.getMe();
const startMsg = Strings.botWelcome.replace(/{botName}/g, botInfo.first_name); 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 Strings = getStrings(ctx.from.language_code);
const message = Strings.botPrivacy.replace("{botPrivacy}", process.env.botPrivacy); const message = Strings.botPrivacy.replace("{botPrivacy}", process.env.botPrivacy);

View File

@ -1,12 +1,19 @@
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const axios = require('axios'); import axios from 'axios';
const fs = require('fs'); import fs from 'fs';
const path = require('path'); import path from 'path';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); 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<ModuleResult | null> {
try { try {
const downloadUrl = `${Resources.modArchiveApi}${moduleId}`; const downloadUrl = `${Resources.modArchiveApi}${moduleId}`;
const response = await axios({ 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) => { bot.command(['modarchive', 'tma'], spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
const moduleId = ctx.message.text.split(' ')[1]; const moduleId = ctx.message.text.split(' ')[1];
if (moduleId == NaN || null) { if (Number.isNaN(moduleId) || null) {
return ctx.reply(Strings.maInvalidModule, { return ctx.reply(Strings.maInvalidModule, {
parse_mode: "Markdown", parse_mode: "Markdown",
reply_to_message_id: ctx.message.message_id reply_to_message_id: ctx.message.message_id

View File

@ -1,15 +1,56 @@
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const axios = require("axios"); import axios from 'axios';
const { verifyInput } = require('../plugins/verifyInput.js'); 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) { function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1); return string.charAt(0).toUpperCase() + string.slice(1);
} }
module.exports = (bot) => { export default (bot) => {
bot.command("mlp", spamwatchMiddleware, async (ctx) => { bot.command("mlp", spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
@ -34,11 +75,11 @@ module.exports = (bot) => {
try { try {
const response = await axios(apiUrl); const response = await axios(apiUrl);
const charactersArray = []; const charactersArray: Character[] = [];
if (Array.isArray(response.data.data)) { if (Array.isArray(response.data.data)) {
response.data.data.forEach(character => { response.data.data.forEach(character => {
let aliases = []; let aliases: string[] = [];
if (character.alias) { if (character.alias) {
if (typeof character.alias === 'string') { if (typeof character.alias === 'string') {
aliases.push(character.alias); aliases.push(character.alias);
@ -107,7 +148,7 @@ module.exports = (bot) => {
try { try {
const response = await axios(apiUrl); const response = await axios(apiUrl);
const episodeArray = []; const episodeArray: Episode[] = [];
if (Array.isArray(response.data.data)) { if (Array.isArray(response.data.data)) {
response.data.data.forEach(episode => { response.data.data.forEach(episode => {
@ -175,15 +216,15 @@ module.exports = (bot) => {
try { try {
const response = await axios(apiUrl); const response = await axios(apiUrl);
const comicArray = []; const comicArray: Comic[] = [];
if (Array.isArray(response.data.data)) { if (Array.isArray(response.data.data)) {
response.data.data.forEach(comic => { response.data.data.forEach(comic => {
let letterers = []; let letterers: string[] = [];
if (comic.letterer) { if (comic.letterer) {
if (typeof comic.letterer === 'string') { if (typeof comic.letterer === 'string') {
letterers.push(comic.letterer); letterers.push(comic.letterer);
} else if (Array.isArray(comic.letterer)) { } else if (Array.isArray(comic.letterer)) {
letterers = aliases.concat(comic.letterer); letterers = letterers.concat(comic.letterer);
} }
} }
comicArray.push({ comicArray.push({

View File

@ -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'
// });
// };
// });
// };

32
src/commands/quotes.ts Normal file
View File

@ -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'
});
};
});
};
*/

View File

@ -1,15 +1,17 @@
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const axios = require("axios"); import axios from 'axios';
module.exports = (bot) => { const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
export default (bot) => {
bot.command(["rpony", "randompony", "mlpart"], spamwatchMiddleware, async (ctx) => { bot.command(["rpony", "randompony", "mlpart"], spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
try { try {
const response = await axios(Resources.randomPonyApi); const response = await axios(Resources.randomPonyApi);
let tags = []; let tags: string[] = [];
if (response.data.pony.tags) { if (response.data.pony.tags) {
if (typeof response.data.pony.tags === 'string') { if (typeof response.data.pony.tags === 'string') {

View File

@ -2,12 +2,14 @@
// Copyright (c) 2024 BubbalooTeam. (https://github.com/BubbalooTeam) // Copyright (c) 2024 BubbalooTeam. (https://github.com/BubbalooTeam)
// Minor code changes by lucmsilva (https://github.com/lucmsilva651) // Minor code changes by lucmsilva (https://github.com/lucmsilva651)
const Resources = require('../props/resources.json'); import Resources from '../props/resources.json';
const axios = require('axios'); import axios from 'axios';
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const { verifyInput } = require('../plugins/verifyInput.js'); import verifyInput from '../plugins/verifyInput';
const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
const statusEmojis = { const statusEmojis = {
0: '⛈', 1: '⛈', 2: '⛈', 3: '⛈', 4: '⛈', 5: '🌨', 6: '🌨', 7: '🌨', 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) => { bot.command(['clima', 'weather'], spamwatchMiddleware, async (ctx) => {
const userLang = ctx.from.language_code || "en-US"; const userLang = ctx.from.language_code || "en-US";
const Strings = getStrings(userLang); const Strings = getStrings(userLang);

View File

@ -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 });
// });
// };

38
src/commands/wiki.ts Normal file
View File

@ -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 });
});
};
*/

View File

@ -1,10 +1,12 @@
const { getStrings } = require('../plugins/checkLang.js'); import { getStrings } from '../plugins/checklang';
const { isOnSpamWatch } = require('../spamwatch/spamwatch.js'); import { isOnSpamWatch } from '../spamwatch/spamwatch';
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch); import spamwatchMiddlewareModule from '../spamwatch/Middleware';
const { execFile } = require('child_process'); import { execFile } from 'child_process';
const os = require('os'); import os from 'os';
const fs = require('fs'); import fs from 'fs';
const path = require('path'); import path from 'path';
const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch);
const ytDlpPaths = { const ytDlpPaths = {
linux: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp'), linux: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp'),
@ -28,7 +30,7 @@ const getFfmpegPath = () => {
return ffmpegPaths[platform] || ffmpegPaths.linux; 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) => { return new Promise((resolve, reject) => {
execFile(command, args, (error, stdout, stderr) => { execFile(command, args, (error, stdout, stderr) => {
if (error) { if (error) {
@ -40,8 +42,8 @@ const downloadFromYoutube = async (command, args) => {
}); });
}; };
const getApproxSize = async (command, videoUrl) => { const getApproxSize = async (command: string, videoUrl: string): Promise<number> => {
let args = []; let args: string[] = [];
if (fs.existsSync(path.resolve(__dirname, "../props/cookies.txt"))) { 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")]; args = [videoUrl, '--compat-opt', 'manifest-filesize-approx', '-O', 'filesize_approx', '--cookies', path.resolve(__dirname, "../props/cookies.txt")];
} else { } 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) => { bot.command(['yt', 'ytdl', 'sdl', 'video', 'dl'], spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
const ytDlpPath = getYtDlpPath(); const ytDlpPath = getYtDlpPath();
@ -198,11 +200,8 @@ module.exports = (bot) => {
} }
} catch (error) { } catch (error) {
const errMsg = Strings.ytDownload.uploadErr.replace("{error}", error) const errMsg = Strings.ytDownload.uploadErr.replace("{error}", error)
await ctx.telegram.editMessageText( // will no longer edit the message as the message context is not outside the try block
ctx.chat.id, await ctx.reply(errMsg, {
downloadingMessage.message_id,
null,
errMsg, {
parse_mode: 'Markdown', parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id, reply_to_message_id: ctx.message.message_id,
}, },

View File

@ -17,6 +17,4 @@ function getStrings(languageCode) {
} }
} }
module.exports = { export { getStrings };
getStrings
};

View File

@ -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
};

View File

@ -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;
}

View File

@ -1,7 +1,7 @@
const axios = require('axios'); import axios from 'axios';
const fs = require('fs'); import fs from 'fs';
const path = require('path'); import path from 'path';
const os = require('os'); import os from 'os';
const downloadDir = path.resolve(__dirname, 'yt-dlp'); const downloadDir = path.resolve(__dirname, 'yt-dlp');