diff --git a/src/commands/http.ts b/src/commands/http.ts index 5e47a49..8dc6853 100644 --- a/src/commands/http.ts +++ b/src/commands/http.ts @@ -4,12 +4,13 @@ import { isOnSpamWatch } from '../spamwatch/spamwatch'; import spamwatchMiddlewareModule from '../spamwatch/Middleware'; import axios from 'axios'; import verifyInput from '../plugins/verifyInput'; +import { Context, Telegraf } from 'telegraf'; const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); -export default (bot) => { - bot.command("http", spamwatchMiddleware, async (ctx) => { - const Strings = getStrings(ctx.from.language_code); +export default (bot: Telegraf) => { + bot.command("http", spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { + const Strings = getStrings(ctx.from?.language_code || 'en'); const userInput = ctx.message.text.split(' ')[1]; const apiUrl = Resources.httpApi; const { invalidCode } = Strings.httpCodes @@ -31,11 +32,13 @@ export default (bot) => { .replace("{description}", codeInfo.description); await ctx.reply(message, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); } else { await ctx.reply(Strings.httpCodes.notFound, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); }; @@ -43,13 +46,14 @@ export default (bot) => { const message = Strings.httpCodes.fetchErr.replace("{error}", error); ctx.reply(message, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); }; }); - bot.command("httpcat", spamwatchMiddleware, async (ctx) => { - const Strings = getStrings(ctx.from.language_code); + bot.command("httpcat", spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { + const Strings = getStrings(ctx.from?.language_code || 'en'); const userInput = ctx.message.text.split(' ').slice(1).join(' ').replace(/\s+/g, ''); const { invalidCode } = Strings.httpCodes @@ -63,11 +67,13 @@ export default (bot) => { await ctx.replyWithPhoto(apiUrl, { caption: `🐱 ${apiUrl}`, parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); } catch (error) { ctx.reply(Strings.catImgErr, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); } diff --git a/src/commands/info.ts b/src/commands/info.ts index a19651c..416240a 100644 --- a/src/commands/info.ts +++ b/src/commands/info.ts @@ -1,64 +1,70 @@ import { getStrings } from '../plugins/checklang'; import { isOnSpamWatch } from '../spamwatch/spamwatch'; import spamwatchMiddlewareModule from '../spamwatch/Middleware'; +import { Context, Telegraf } from 'telegraf'; const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); -async function getUserInfo(ctx) { - const Strings = getStrings(ctx.from.language_code); - let lastName = ctx.from.last_name; +async function getUserInfo(ctx: Context & { message: { text: string } }) { + const Strings = getStrings(ctx.from?.language_code || 'en'); + let lastName = ctx.from?.last_name; if (lastName === undefined) { lastName = " "; } 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) - .replace('{userPremium}', ctx.from.is_premium ? Strings.varStrings.varYes : Strings.varStrings.varNo) - .replace('{userLang}', ctx.from.language_code || Strings.varStrings.varUnknown); + .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) + .replace('{userPremium}', ctx.from?.is_premium ? Strings.varStrings.varYes : Strings.varStrings.varNo) + .replace('{userLang}', ctx.from?.language_code || Strings.varStrings.varUnknown); return userInfo; } -async function getChatInfo(ctx) { - const Strings = getStrings(ctx.from.language_code); - if (ctx.chat.type === 'group' || ctx.chat.type === 'supergroup') { +async function getChatInfo(ctx: Context & { message: { text: string } }) { + const Strings = getStrings(ctx.from?.language_code || 'en'); + if (ctx.chat?.type === 'group' || ctx.chat?.type === 'supergroup') { 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) - .replace('{chatMembersCount}', await ctx.getChatMembersCount(ctx.chat.id || Strings.varStrings.varUnknown)) - .replace('{chatType}', ctx.chat.type || Strings.varStrings.varUnknown) - .replace('{isForum}', ctx.chat.is_forum ? Strings.varStrings.varYes : Strings.varStrings.varNo); + .replace('{chatId}', ctx.chat?.id || Strings.varStrings.varUnknown) + .replace('{chatName}', ctx.chat?.title || Strings.varStrings.varUnknown) + // @ts-ignore + .replace('{chatHandle}', ctx.chat?.username ? `@${ctx.chat?.username}` : Strings.varStrings.varNone) + .replace('{chatMembersCount}', await ctx.getChatMembersCount()) + .replace('{chatType}', ctx.chat?.type || Strings.varStrings.varUnknown) + // @ts-ignore + .replace('{isForum}', ctx.chat?.is_forum ? Strings.varStrings.varYes : Strings.varStrings.varNo); return chatInfo; } else { return ctx.reply( Strings.groupOnly, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); } } -export default (bot) => { - bot.command('chatinfo', spamwatchMiddleware, async (ctx) => { +export default (bot: Telegraf) => { + bot.command('chatinfo', spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { const chatInfo = await getChatInfo(ctx); ctx.reply( chatInfo, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id } ); }); - bot.command('userinfo', spamwatchMiddleware, async (ctx) => { + bot.command('userinfo', spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { const userInfo = await getUserInfo(ctx); ctx.reply( userInfo, { parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id, + // @ts-ignore + reply_to_message_id: ctx.message.message_id } ); }); diff --git a/src/commands/ponyapi.ts b/src/commands/ponyapi.ts index dfa2e1c..25fc473 100644 --- a/src/commands/ponyapi.ts +++ b/src/commands/ponyapi.ts @@ -4,6 +4,7 @@ import { isOnSpamWatch } from '../spamwatch/spamwatch'; import spamwatchMiddlewareModule from '../spamwatch/Middleware'; import axios from 'axios'; import verifyInput from '../plugins/verifyInput'; +import { Telegraf, Context } from 'telegraf'; const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); @@ -50,19 +51,20 @@ function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } -export default (bot) => { - bot.command("mlp", spamwatchMiddleware, async (ctx) => { - const Strings = getStrings(ctx.from.language_code); +export default (bot: Telegraf) => { + bot.command("mlp", spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { + const Strings = getStrings(ctx.from?.language_code || 'en'); ctx.reply(Strings.ponyApi.helpDesc, { parse_mode: 'Markdown', + // @ts-ignore disable_web_page_preview: true, reply_to_message_id: ctx.message.message_id }); }); - bot.command("mlpchar", spamwatchMiddleware, async (ctx) => { - const Strings = getStrings(ctx.from.language_code); + bot.command("mlpchar", spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { + const Strings = getStrings(ctx.from?.language_code || 'en'); const userInput = ctx.message.text.split(' ').slice(1).join(' ').replace(" ", "+"); const { noCharName } = Strings.ponyApi @@ -116,12 +118,14 @@ export default (bot) => { ctx.replyWithPhoto(charactersArray[0].image[0], { caption: `${result}`, parse_mode: 'Markdown', + // @ts-ignore disable_web_page_preview: true, reply_to_message_id: ctx.message.message_id }); } else { ctx.reply(Strings.ponyApi.noCharFound, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); }; @@ -129,13 +133,14 @@ export default (bot) => { const message = Strings.ponyApi.apiErr.replace('{error}', error.message); ctx.reply(message, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); }; }); - bot.command("mlpep", spamwatchMiddleware, async (ctx) => { - const Strings = getStrings(ctx.from.language_code); + bot.command("mlpep", spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { + const Strings = getStrings(ctx.from?.language_code || 'en'); const userInput = ctx.message.text.split(' ').slice(1).join(' ').replace(" ", "+"); const { noEpisodeNum } = Strings.ponyApi @@ -184,12 +189,14 @@ export default (bot) => { ctx.replyWithPhoto(episodeArray[0].image, { caption: `${result}`, parse_mode: 'Markdown', + // @ts-ignore disable_web_page_preview: true, reply_to_message_id: ctx.message.message_id }); } else { ctx.reply(Strings.ponyApi.noEpisodeFound, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); }; @@ -197,13 +204,14 @@ export default (bot) => { const message = Strings.ponyApi.apiErr.replace('{error}', error.message); ctx.reply(message, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); }; }); - bot.command("mlpcomic", spamwatchMiddleware, async (ctx) => { - const Strings = getStrings(ctx.from.language_code); + bot.command("mlpcomic", spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { + const Strings = getStrings(ctx.from?.language_code || 'en'); const userInput = ctx.message.text.split(' ').slice(1).join(' ').replace(" ", "+"); const { noComicName } = Strings.ponyApi @@ -257,12 +265,14 @@ export default (bot) => { ctx.replyWithPhoto(comicArray[0].image, { caption: `${result}`, parse_mode: 'Markdown', + // @ts-ignore disable_web_page_preview: true, reply_to_message_id: ctx.message.message_id }); } else { ctx.reply(Strings.ponyApi.noComicFound, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); }; @@ -270,6 +280,7 @@ export default (bot) => { const message = Strings.ponyApi.apiErr.replace('{error}', error.message); ctx.reply(message, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); }; diff --git a/src/commands/randompony.ts b/src/commands/randompony.ts index 0ca140d..3ecf4b4 100644 --- a/src/commands/randompony.ts +++ b/src/commands/randompony.ts @@ -3,12 +3,14 @@ import { getStrings } from '../plugins/checklang'; import { isOnSpamWatch } from '../spamwatch/spamwatch'; import spamwatchMiddlewareModule from '../spamwatch/Middleware'; import axios from 'axios'; +import { Telegraf, Context } from 'telegraf'; const spamwatchMiddleware = spamwatchMiddlewareModule(isOnSpamWatch); -export default (bot) => { - bot.command(["rpony", "randompony", "mlpart"], spamwatchMiddleware, async (ctx) => { - const Strings = getStrings(ctx.from.language_code); +export default (bot: Telegraf) => { + // TODO: this would greatly benefit from a loading message + bot.command(["rpony", "randompony", "mlpart"], spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => { + const Strings = getStrings(ctx.from?.language_code || 'en'); try { const response = await axios(Resources.randomPonyApi); let tags: string[] = []; @@ -24,12 +26,14 @@ export default (bot) => { ctx.replyWithPhoto(response.data.pony.representations.full, { caption: `${response.data.pony.sourceURL}\n\n${tags.length > 0 ? tags.join(', ') : ''}`, parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); } catch (error) { const message = Strings.ponyApi.apiErr.replace('{error}', error.message); ctx.reply(message, { parse_mode: 'Markdown', + // @ts-ignore reply_to_message_id: ctx.message.message_id }); return; diff --git a/src/commands/weather.ts b/src/commands/weather.ts index 716726c..6c1a529 100644 --- a/src/commands/weather.ts +++ b/src/commands/weather.ts @@ -21,10 +21,10 @@ const statusEmojis = { 43: '❄️', 44: 'n/a', 45: '🌧', 46: '🌨', 47: '🌩' }; -const getStatusEmoji = (statusCode) => statusEmojis[statusCode] || 'n/a'; +const getStatusEmoji = (statusCode: number) => statusEmojis[statusCode] || 'n/a'; -function getLocaleUnit(countryCode) { - const fahrenheitCountries = ['US', 'BS', 'BZ', 'KY', 'LR']; +function getLocaleUnit(countryCode: string) { + const fahrenheitCountries: string[] = ['US', 'BS', 'BZ', 'KY', 'LR']; if (fahrenheitCountries.includes(countryCode)) { return { temperatureUnit: 'F', speedUnit: 'mph', apiUnit: 'e' }; @@ -44,10 +44,18 @@ export default (bot) => { return; } - const location = userInput; - const apiKey = process.env.weatherKey; + const location: string = userInput; + const apiKey: string = process.env.weatherKey || ''; + + if (!apiKey || apiKey === "InsertYourWeatherDotComApiKeyHere") { + return ctx.reply(Strings.weatherStatus.apiKeyErr, { + parse_mode: "Markdown", + reply_to_message_id: ctx.message.message_id + }); + } try { + // TODO: this also needs to be sanitized and validated const locationResponse = await axios.get(`${Resources.weatherApi}/location/search`, { params: { apiKey: apiKey, diff --git a/src/locales/english.json b/src/locales/english.json index 773c490..f8bb0ec 100644 --- a/src/locales/english.json +++ b/src/locales/english.json @@ -49,7 +49,8 @@ "provideLocation": "*Please provide a location.*", "invalidLocation": "*Invalid location. Try again.*", "resultMsg": "*Weather in {addressFirst}:*\n\n*Status:* `{getStatusEmoji(iconCode)} {wxPhraseLong}`\n*Temperature:* `{temperature} °{temperatureUnit}`\n*Feels like:* `{temperatureFeelsLike} °{temperatureUnit2}`\n*Humidity:* `{relativeHumidity}%`\n*Wind speed:* `{windSpeed} {speedUnit}`", - "apiErr": "*An error occurred while retrieving the weather. Please try again later.*\n\n`{error}`" + "apiErr": "*An error occurred while retrieving the weather. Please try again later.*\n\n`{error}`", + "apiKeyErr": "*An API key was not set by the bot owner. Please try again later.*" }, "mainCommands": "Main commands", "mainCommandsDesc": "*Main commands*\n\n- /help: Show bot's help\n- /start: Start the bot\n- /privacy: Read the bot's Privacy Policy", diff --git a/src/locales/portuguese.json b/src/locales/portuguese.json index c7b1b4b..2e485f7 100644 --- a/src/locales/portuguese.json +++ b/src/locales/portuguese.json @@ -49,7 +49,8 @@ "provideLocation": "*Por favor, forneça uma localização.*", "invalidLocation": "*Localização inválida. Tente novamente.*", "resultMsg": "*Clima em {addressFirst}:*\n\n*Estado:* `{getStatusEmoji(iconCode)} {wxPhraseLong}`\n*Temperatura:* `{temperature} °{temperatureUnit}`\n*Sensação térmica:* `{temperatureFeelsLike} °{temperatureUnit2}`\n*Umidade:* `{relativeHumidity}%`\n*Velocidade do vento:* `{windSpeed} {speedUnit}`", - "apiErr": "*Ocorreu um erro ao obter o clima. Tente novamente mais tarde.*\n\n`{error}`" + "apiErr": "*Ocorreu um erro ao obter o clima. Tente novamente mais tarde.*\n\n`{error}`", + "apiKeyErr": "*Uma chave de API não foi definida pelo proprietário do bot. Tente novamente mais tarde.*" }, "mainCommands": "Comandos principais", "mainCommandsDesc": "*Comandos principais*\n\n- /help: Exibe a ajuda do bot\n- /start: Inicia o bot\n- /privacy: Leia a política de privacidade do bot", diff --git a/src/plugins/checklang.ts b/src/plugins/checklang.ts index a8d1b79..650747c 100644 --- a/src/plugins/checklang.ts +++ b/src/plugins/checklang.ts @@ -7,8 +7,8 @@ const languageFiles = { 'en-gb': '../locales/english.json' }; -function getStrings(languageCode) { - const filePath = languageFiles[languageCode] || languageFiles['en']; +function getStrings(languageCode: string) { + const filePath: string = languageFiles[languageCode] || languageFiles['en']; try { return require(filePath); } catch (error) {