Merge branch 'main' into main

This commit is contained in:
Lucas Gabriel 2025-04-15 19:40:34 -03:00 committed by GitHub
commit f6886ae504
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 80 additions and 72 deletions

4
.gitmodules vendored
View file

@ -1,3 +1,3 @@
[submodule "src/plugins/lib-spamwatch"] [submodule "src/spamwatch"]
path = src/plugins/lib-spamwatch path = src/spamwatch
url = https://github.com/ABOCN/TelegramBot-SpamWatch url = https://github.com/ABOCN/TelegramBot-SpamWatch

View file

@ -1,7 +1,7 @@
FROM node:20-slim FROM node:20-slim
# Install ffmpeg and other deps # Install ffmpeg and other deps
RUN apt-get update && apt-get install -y ffmpeg && apt-get clean && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get install -y ffmpeg git && apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /usr/src/app WORKDIR /usr/src/app

View file

@ -1,6 +1,7 @@
BSD 3-Clause License BSD 3-Clause License
Copyright (c) 2024, Lucas Gabriel Copyright (c) 2024-2025, Lucas Gabriel <lucmsilva651@gmail.com>,
ABOCN <abocn@protonmail.me> and all contributors
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:

View file

@ -1,7 +1,9 @@
# Kowalski (Node.js Telegram Bot) # Kowalski (Node.js Telegram Bot)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)
![GitHub License](https://img.shields.io/github/license/ABOCN/TelegramBot) [![GitHub License](https://img.shields.io/github/license/ABOCN/TelegramBot)](https://github.com/abocn/TelegramBot/blob/main/LICENSE)
[![CodeQL](https://github.com/abocn/TelegramBot/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/abocn/TelegramBot/actions/workflows/github-code-scanning/codeql)
[![Dependabot Updates](https://github.com/abocn/TelegramBot/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/abocn/TelegramBot/actions/workflows/dependabot/dependabot-updates)
Kowalski is a a simple Telegram bot made in Node.js. Kowalski is a a simple Telegram bot made in Node.js.
@ -9,24 +11,20 @@ Kowalski is a a simple Telegram bot made in Node.js.
## Self-host requirements ## Self-host requirements
- Node.js 20 or newer (you can also use [Bun](https://bun.sh)) > [!IMPORTANT]
> You will only need all of them if you are not running it dockerized. Read ["Running with Docker"](#running-with-docker) for more information.
- Node.js 23 or newer (you can also use [Bun](https://bun.sh))
- A Telegram bot (create one at [@BotFather](https://t.me/botfather)) - A Telegram bot (create one at [@BotFather](https://t.me/botfather))
- FFmpeg (only for the `/yt` command) - FFmpeg (only for the `/yt` command)
- Docker and Docker Compose (only required for Docker setup) - Docker and Docker Compose (only required for Docker setup)
## Run it yourself, develop or contribute with Kowalski ## Running locally (non-Docker setup)
First, clone the repo with Git: First, clone the repo with Git:
```bash ```bash
git clone https://github.com/ABOCN/TelegramBot git clone --recurse-submodules https://github.com/ABOCN/TelegramBot
```
And now, init the submodules with these commands (this is very important):
```bash
cd TelegramBot
git submodule update --init --recursive
``` ```
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 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).
@ -41,6 +39,9 @@ After editing the file, save all changes and run the bot with ``npm start``.
> [!IMPORTANT] > [!IMPORTANT]
> Please complete the above steps to prepare your local copy for building. You do not need to install FFmpeg on your host system. > Please complete the above steps to prepare your local copy for building. You do not need to install FFmpeg on your host system.
> [!NOTE]
> Using the `-d` flag when running causes Kowalski to run in the background. If you're just playing around or testing, you may not want to use this flag.
You can also run Kowalski using Docker, which simplifies the setup process. Make sure you have Docker and Docker Compose installed. You can also run Kowalski using Docker, which simplifies the setup process. Make sure you have Docker and Docker Compose installed.
### Using Docker Compose ### Using Docker Compose
@ -53,9 +54,6 @@ You can also run Kowalski using Docker, which simplifies the setup process. Make
docker compose up -d docker compose up -d
``` ```
> [!NOTE]
> The `-d` flag causes Kowalski to run in the background. If you're just playing around, you may not want to use this flag.
### Using Docker Run ### Using Docker Run
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.
@ -74,21 +72,18 @@ If you prefer to use Docker directly, you can use these instructions instead.
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)/config.env:/usr/src/app/config.env:ro kowalski
``` ```
> [!NOTE]
> The `-d` flag causes Kowalski to run in the background. If you're just playing around, you may not want to use this flag.
## config.env Functions ## config.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!
- **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.
- **maxRetries**: Maximum number of retries for a failing command on Kowalski. Default is 5. If the limit is hit, the bot will crash past this number.
- **botToken**: Put your bot token that you created at [@BotFather](https://t.me/botfather). - **botToken**: Put your bot token that you created at [@BotFather](https://t.me/botfather).
- **botAdmins**: Put the ID of the people responsible for managing the bot. They can use some administrative + exclusive commands on any group. - **botAdmins**: Put the ID of the people responsible for managing the bot. They can use some administrative + exclusive commands on any group.
- **lastKey**: Last.fm API key, for use on `lastfm.js` functions, like see who is listening to what song and etc. - **lastKey**: Last.fm API key, for use on `lastfm.js` functions, like see who is listening to what song and etc.
- **weatherKey**: Weather.com API key, used for the `/weather` command. - **weatherKey**: Weather.com API key, used for the `/weather` command.
## Note
- 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!
## Troubleshooting ## Troubleshooting
### YouTube Downloading ### YouTube Downloading

View file

@ -1,5 +1,12 @@
botSource = "https://github.com/change-this/to-your-repo/" # links for source and privacy
botToken = "InsertYourBotTokenHere" botPrivacy = "https://blog.lucmsilva.com/posts/lynx-privacy-policy"
botAdmins = 0000000000, 00000000, 00000000 botSource = "https://github.com/ABOCN/TelegramBot"
# insert token here
botToken = ""
# misc (botAdmins isnt a array here!)
maxRetries = 9999
botAdmins = 00000000, 00000000, 00000000
lastKey = "InsertYourLastFmApiKeyHere" lastKey = "InsertYourLastFmApiKeyHere"
weatherKey = "InsertYourWeatherDotComApiKeyHere" weatherKey = "InsertYourWeatherDotComApiKeyHere"

View file

@ -1,7 +1,7 @@
const { Telegraf } = require('telegraf'); const { Telegraf } = require('telegraf');
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const { isOnSpamWatch } = require('./plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('./spamwatch/spamwatch.js');
require('@dotenvx/dotenvx').config({ path: "config.env" }); require('@dotenvx/dotenvx').config({ path: "config.env" });
require('./plugins/ytdlp-wrapper.js'); require('./plugins/ytdlp-wrapper.js');
// require('./plugins/termlogger.js'); // require('./plugins/termlogger.js');

View file

@ -1,7 +1,7 @@
const Resources = require('../props/resources.json'); const Resources = require('../props/resources.json');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require("axios"); const axios = require("axios");
module.exports = (bot) => { module.exports = (bot) => {

View file

@ -1,7 +1,7 @@
const Resources = require('../props/resources.json'); const Resources = require('../props/resources.json');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require('axios'); const axios = require('axios');
const { verifyInput } = require('../plugins/verifyInput.js'); const { verifyInput } = require('../plugins/verifyInput.js');

View file

@ -1,6 +1,6 @@
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const os = require('os'); const os = require('os');
const { exec } = require('child_process'); const { exec } = require('child_process');
const { error } = require('console'); const { error } = require('console');

View file

@ -1,7 +1,7 @@
const Resources = require('../props/resources.json'); const Resources = require('../props/resources.json');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(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);

View file

@ -4,8 +4,8 @@
// 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('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require('axios'); const axios = require('axios');
const { parse } = require('node-html-parser'); const { parse } = require('node-html-parser');
@ -193,14 +193,18 @@ function extractMetaData(meta, key) {
return line ? line.split('"')[1] : ""; return line ? line.split('"')[1] : "";
} }
function getUsername(ctx){
let userName = String(ctx.from.first_name);
if(userName.includes("<") && userName.includes(">")) {
userName = userName.replaceAll("<", "").replaceAll(">", "");
}
return userName;
}
module.exports = (bot) => { module.exports = (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;
let userName = String(ctx.from.first_name); const userName = getUsername(ctx);
if(userName.includes("<") && userName.includes(">")) {
userName = userName.replaceAll("<", "").replaceAll(">", "");
}
const phone = ctx.message.text.split(" ").slice(1).join(" "); const phone = ctx.message.text.split(" ").slice(1).join(" ");
if (!phone) { if (!phone) {
@ -228,7 +232,7 @@ module.exports = (bot) => {
bot.action(/details:(.+):(.+)/, async (ctx) => { bot.action(/details:(.+):(.+)/, async (ctx) => {
const url = ctx.match[1]; const url = ctx.match[1];
const userId = parseInt(ctx.match[2]); const userId = parseInt(ctx.match[2]);
const userName = ctx.from.first_name; const userName = getUsername(ctx);
const callbackQueryUserId = ctx.update.callback_query.from.id; const callbackQueryUserId = ctx.update.callback_query.from.id;

View file

@ -1,6 +1,6 @@
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
async function sendHelpMessage(ctx, isEditing) { async function sendHelpMessage(ctx, isEditing) {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);

View file

@ -1,7 +1,7 @@
const Resources = require('../props/resources.json'); const Resources = require('../props/resources.json');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require('axios'); const axios = require('axios');
const { verifyInput } = require('../plugins/verifyInput.js'); const { verifyInput } = require('../plugins/verifyInput.js');

View file

@ -1,6 +1,6 @@
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
async function getUserInfo(ctx) { async function getUserInfo(ctx) {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);

View file

@ -2,8 +2,8 @@ const Resources = require('../props/resources.json');
const fs = require('fs'); const fs = require('fs');
const axios = require('axios'); const axios = require('axios');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const scrobbler_url = Resources.lastFmApi; const scrobbler_url = Resources.lastFmApi;
const api_key = process.env.lastKey; const api_key = process.env.lastKey;

View file

@ -1,6 +1,6 @@
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
module.exports = (bot) => { module.exports = (bot) => {
bot.start(spamwatchMiddleware, async (ctx) => { bot.start(spamwatchMiddleware, async (ctx) => {
@ -16,8 +16,9 @@ module.exports = (bot) => {
bot.command('privacy', spamwatchMiddleware, async (ctx) => { bot.command('privacy', spamwatchMiddleware, async (ctx) => {
const Strings = getStrings(ctx.from.language_code); const Strings = getStrings(ctx.from.language_code);
ctx.reply( const message = Strings.botPrivacy.replace("{botPrivacy}", process.env.botPrivacy);
Strings.botPrivacy, {
ctx.reply(message, {
parse_mode: 'Markdown', parse_mode: 'Markdown',
disable_web_page_preview: true, disable_web_page_preview: true,
reply_to_message_id: ctx.message.message_id reply_to_message_id: ctx.message.message_id

View file

@ -3,8 +3,8 @@ const axios = require('axios');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
async function downloadModule(moduleId) { async function downloadModule(moduleId) {
try { try {

View file

@ -1,7 +1,7 @@
const Resources = require('../props/resources.json'); const Resources = require('../props/resources.json');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require("axios"); const axios = require("axios");
const { verifyInput } = require('../plugins/verifyInput.js'); const { verifyInput } = require('../plugins/verifyInput.js');

View file

@ -1,7 +1,7 @@
// const Resources = require('../props/resources.json'); // const Resources = require('../props/resources.json');
// const { getStrings } = require('../plugins/checklang.js'); // const { getStrings } = require('../plugins/checklang.js');
// const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); // const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
// const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); // const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
// const escape = require('markdown-escape'); // const escape = require('markdown-escape');
// const axios = require('axios'); // const axios = require('axios');

View file

@ -1,7 +1,7 @@
const Resources = require('../props/resources.json'); const Resources = require('../props/resources.json');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const axios = require("axios"); const axios = require("axios");
module.exports = (bot) => { module.exports = (bot) => {

View file

@ -5,9 +5,9 @@
const Resources = require('../props/resources.json'); const Resources = require('../props/resources.json');
const axios = require('axios'); const axios = require('axios');
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const { verifyInput } = require('../plugins/verifyInput.js'); const { verifyInput } = require('../plugins/verifyInput.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
const statusEmojis = { const statusEmojis = {
0: '⛈', 1: '⛈', 2: '⛈', 3: '⛈', 4: '⛈', 5: '🌨', 6: '🌨', 7: '🌨', 0: '⛈', 1: '⛈', 2: '⛈', 3: '⛈', 4: '⛈', 5: '🌨', 6: '🌨', 7: '🌨',

View file

@ -1,6 +1,6 @@
const { getStrings } = require('../plugins/checklang.js'); const { getStrings } = require('../plugins/checklang.js');
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const { isOnSpamWatch } = require('../spamwatch/spamwatch.js');
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); const spamwatchMiddleware = require('../spamwatch/Middleware.js')(isOnSpamWatch);
const { execFile } = require('child_process'); const { execFile } = require('child_process');
const os = require('os'); const os = require('os');
const fs = require('fs'); const fs = require('fs');

View file

@ -1,7 +1,7 @@
{ {
"botWelcome": "*Hello! I'm {botName}!*\nI was made with love by some nerds who really love programming!\n\n*By using {botName}, you affirm that you have read to and agree with the privacy policy (/privacy). This helps you understand where your data goes when using this bot.*\n\nAlso, you can use /help to see the bot commands!", "botWelcome": "*Hello! I'm {botName}!*\nI was made with love by some nerds who really love programming!\n\n*By using {botName}, you affirm that you have read to and agree with the privacy policy (/privacy). This helps you understand where your data goes when using this bot.*\n\nAlso, you can use /help to see the bot commands!",
"botHelp": "*Hey, I'm {botName}, a simple bot made entirely from scratch in Telegraf and Node.js by some nerds who really love programming.*\n\nClick on the buttons below to see which commands you can use!\n", "botHelp": "*Hey, I'm {botName}, a simple bot made entirely from scratch in Telegraf and Node.js by some nerds who really love programming.*\n\nClick on the buttons below to see which commands you can use!\n",
"botPrivacy": "Check out [this link](https://blog.lucmsilva.com/posts/lynx-privacy-policy) to read the bot's privacy policy.", "botPrivacy": "Check out [this link]({botPrivacy}) to read the bot's privacy policy.",
"botAbout": "*About the bot*\n\nThe bot base was originally created by [Lucas Gabriel (lucmsilva)](https://github.com/lucmsilva651), now maintained by several people.\n\nThe bot's purpose is to bring fun to your groups here on Telegram in a relaxed and simple way. The bot also features some very useful commands, which you can see using the help command (/help).\n\nSpecial thanks to @givfnz2 for his many contributions to the bot!\n\nSee the source code: [Click here to go to GitHub]({sourceLink})", "botAbout": "*About the bot*\n\nThe bot base was originally created by [Lucas Gabriel (lucmsilva)](https://github.com/lucmsilva651), now maintained by several people.\n\nThe bot's purpose is to bring fun to your groups here on Telegram in a relaxed and simple way. The bot also features some very useful commands, which you can see using the help command (/help).\n\nSpecial thanks to @givfnz2 for his many contributions to the bot!\n\nSee the source code: [Click here to go to GitHub]({sourceLink})",
"aboutBot": "About the bot", "aboutBot": "About the bot",
"varStrings": { "varStrings": {

View file

@ -1,7 +1,7 @@
{ {
"botWelcome": "*Olá! Eu sou o {botName}!*\n\n*Ao usar o {botName}, você afirma que leu e concorda com a política de privacidade (/privacy). Isso ajuda você a entender onde seus dados vão ao usar este bot.*\n\nAlém disso, você pode usar /help para ver os meus comandos!", "botWelcome": "*Olá! Eu sou o {botName}!*\n\n*Ao usar o {botName}, você afirma que leu e concorda com a política de privacidade (/privacy). Isso ajuda você a entender onde seus dados vão ao usar este bot.*\n\nAlém disso, você pode usar /help para ver os meus comandos!",
"botHelp": "*Oi, eu sou o {botName}, um bot simples feito do zero em Telegraf e Node.js por uns nerds que gostam de programação.*\n\nVeja o código fonte: [Clique aqui para ir ao GitHub]({sourceLink})\n\nClique nos botões abaixo para ver quais comandos você pode usar!\n", "botHelp": "*Oi, eu sou o {botName}, um bot simples feito do zero em Telegraf e Node.js por uns nerds que gostam de programação.*\n\nVeja o código fonte: [Clique aqui para ir ao GitHub]({sourceLink})\n\nClique nos botões abaixo para ver quais comandos você pode usar!\n",
"botPrivacy": "Acesse [este link](https://blog.lucmsilva.com/posts/lynx-privacy-policy) para ler a política de privacidade do bot.", "botPrivacy": "Acesse [este link]({botPrivacy}) para ler a política de privacidade do bot.",
"botAbout": "*Sobre o bot*\n\nA base deste bot foi feita originalmente por [Lucas Gabriel (lucmsilva)](https://github.com/lucmsilva651), agora sendo mantido por várias pessoas.\n\nA intenção do bot é trazer diversão para os seus grupos aqui no Telegram de uma maneira bem descontraida e simples. O bot também conta com alguns comandos bem úteis, que você consegue ver com o comando de ajuda (/help).\n\nAgradecimento especial ao @givfnz2 pelas suas várias contribuições ao bot!\n\nVeja o código fonte: [Clique aqui para ir ao GitHub]({sourceLink})", "botAbout": "*Sobre o bot*\n\nA base deste bot foi feita originalmente por [Lucas Gabriel (lucmsilva)](https://github.com/lucmsilva651), agora sendo mantido por várias pessoas.\n\nA intenção do bot é trazer diversão para os seus grupos aqui no Telegram de uma maneira bem descontraida e simples. O bot também conta com alguns comandos bem úteis, que você consegue ver com o comando de ajuda (/help).\n\nAgradecimento especial ao @givfnz2 pelas suas várias contribuições ao bot!\n\nVeja o código fonte: [Clique aqui para ir ao GitHub]({sourceLink})",
"aboutBot": "Sobre o bot", "aboutBot": "Sobre o bot",
"varStrings": { "varStrings": {

@ -1 +0,0 @@
Subproject commit 8d35b7ec4cffb48df8d1f59485b32e2484ae64e7

1
src/spamwatch Submodule

@ -0,0 +1 @@
Subproject commit b71b3b9eab0f172c038674fc6739fce9199ad3e0