Merge branch 'main' into fix_ttk
This commit is contained in:
commit
32a389a301
11 changed files with 321 additions and 213 deletions
8
.dockerignore
Normal file
8
.dockerignore
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.env
|
||||||
|
config.env
|
||||||
|
*.md
|
||||||
|
!README.md
|
18
Dockerfile
Normal file
18
Dockerfile
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
FROM node:20-slim
|
||||||
|
|
||||||
|
# Install ffmpeg and other deps
|
||||||
|
RUN apt-get update && apt-get install -y ffmpeg && apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN chmod +x /usr/src/app/src/plugins/yt-dlp/yt-dlp
|
||||||
|
|
||||||
|
VOLUME /usr/src/app/config.env
|
||||||
|
|
||||||
|
CMD ["npm", "start"]
|
57
README.md
57
README.md
|
@ -9,10 +9,10 @@ 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)
|
- Node.js 20 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))
|
||||||
- Latest version of Node.js
|
|
||||||
- FFmpeg (only for the `/yt` command)
|
- FFmpeg (only for the `/yt` command)
|
||||||
|
- Docker and Docker Compose (only required for Docker setup)
|
||||||
|
|
||||||
## Run it yourself, develop or contribute with Kowalski
|
## Run it yourself, develop or contribute with Kowalski
|
||||||
|
|
||||||
|
@ -36,6 +36,47 @@ After editing the file, save all changes and run the bot with ``npm start``.
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> To deal with dependencies, just run ``npm install`` or ``npm i`` at any moment to install all of them.
|
> To deal with dependencies, just run ``npm install`` or ``npm i`` at any moment to install all of them.
|
||||||
|
|
||||||
|
## Running with Docker
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Please complete the above steps to prepare your local copy for building. You do not need to install FFmpeg on your host system.
|
||||||
|
|
||||||
|
You can also run Kowalski using Docker, which simplifies the setup process. Make sure you have Docker and Docker Compose installed.
|
||||||
|
|
||||||
|
### Using Docker Compose
|
||||||
|
|
||||||
|
1. **Make sure to setup your `config.env` file first!**
|
||||||
|
|
||||||
|
2. **Run the container**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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
|
||||||
|
|
||||||
|
If you prefer to use Docker directly, you can use these instructions instead.
|
||||||
|
|
||||||
|
1. **Make sure to setup your `config.env` file first!**
|
||||||
|
|
||||||
|
2. **Build the image**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t kowalski .
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Run the container**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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
|
||||||
|
|
||||||
- **botSource**: Put the link to your bot source code.
|
- **botSource**: Put the link to your bot source code.
|
||||||
|
@ -48,6 +89,18 @@ After editing the file, save all changes and run the bot with ``npm start``.
|
||||||
|
|
||||||
- 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 ``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
|
||||||
|
|
||||||
|
### YouTube Downloading
|
||||||
|
|
||||||
|
**Q:** I get a "Permission denied (EACCES)" error in the console when running the `/yt` command
|
||||||
|
|
||||||
|
**A:** Make sure `src/plugins/yt-dlp/yt-dlp` is executable. You can do this on Linux like so:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x src/plugins/yt-dlp/yt-dlp
|
||||||
|
```
|
||||||
|
|
||||||
## About/License
|
## About/License
|
||||||
|
|
||||||
BSD-3-Clause - 2024 Lucas Gabriel (lucmsilva).
|
BSD-3-Clause - 2024 Lucas Gabriel (lucmsilva).
|
||||||
|
|
9
docker-compose.yml
Normal file
9
docker-compose.yml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
services:
|
||||||
|
kowalski:
|
||||||
|
build: .
|
||||||
|
container_name: kowalski
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./config.env:/usr/src/app/config.env:ro
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
|
@ -6,6 +6,12 @@ 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');
|
||||||
|
|
||||||
|
// 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.')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
const bot = new Telegraf(process.env.botToken);
|
const bot = new Telegraf(process.env.botToken);
|
||||||
const maxRetries = process.env.maxRetries || 5;
|
const maxRetries = process.env.maxRetries || 5;
|
||||||
let restartCount = 0;
|
let restartCount = 0;
|
||||||
|
|
|
@ -62,7 +62,7 @@ async function handleAdminCommand(ctx, action, successMessage, errorMessage) {
|
||||||
reply_to_message_id: ctx.message.message_id
|
reply_to_message_id: ctx.message.message_id
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.reply(errorMessage.replace('{error}', error.message), {
|
ctx.reply(errorMessage.replace(/{error}/g, error.message), {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
reply_to_message_id: ctx.message.message_id
|
reply_to_message_id: ctx.message.message_id
|
||||||
});
|
});
|
||||||
|
@ -91,12 +91,12 @@ module.exports = (bot) => {
|
||||||
handleAdminCommand(ctx, async () => {
|
handleAdminCommand(ctx, async () => {
|
||||||
try {
|
try {
|
||||||
const commitHash = await getGitCommitHash();
|
const commitHash = await getGitCommitHash();
|
||||||
await ctx.reply(Strings.gitCurrentCommit.replace('{commitHash}', commitHash), {
|
await ctx.reply(Strings.gitCurrentCommit.replace(/{commitHash}/g, commitHash), {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
reply_to_message_id: ctx.message.message_id
|
reply_to_message_id: ctx.message.message_id
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.reply(Strings.gitErrRetrievingCommit.replace('{error}', error), {
|
ctx.reply(Strings.gitErrRetrievingCommit.replace(/{error}/g, error), {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
reply_to_message_id: ctx.message.message_id
|
reply_to_message_id: ctx.message.message_id
|
||||||
});
|
});
|
||||||
|
@ -109,12 +109,12 @@ module.exports = (bot) => {
|
||||||
handleAdminCommand(ctx, async () => {
|
handleAdminCommand(ctx, async () => {
|
||||||
try {
|
try {
|
||||||
const result = await updateBot();
|
const result = await updateBot();
|
||||||
await ctx.reply(Strings.botUpdated.replace('{result}', result), {
|
await ctx.reply(Strings.botUpdated.replace(/{result}/g, result), {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
reply_to_message_id: ctx.message.message_id
|
reply_to_message_id: ctx.message.message_id
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.reply(Strings.errorUpdatingBot.replace('{error}', error), {
|
ctx.reply(Strings.errorUpdatingBot.replace(/{error}/g, error), {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
reply_to_message_id: ctx.message.message_id
|
reply_to_message_id: ctx.message.message_id
|
||||||
});
|
});
|
||||||
|
@ -127,7 +127,7 @@ module.exports = (bot) => {
|
||||||
const botName = ctx.message.text.split(' ').slice(1).join(' ');
|
const botName = ctx.message.text.split(' ').slice(1).join(' ');
|
||||||
handleAdminCommand(ctx, async () => {
|
handleAdminCommand(ctx, async () => {
|
||||||
await ctx.telegram.setMyName(botName);
|
await ctx.telegram.setMyName(botName);
|
||||||
}, Strings.botNameChanged.replace('{botName}', botName), Strings.botNameErr.replace('{error}', error));
|
}, Strings.botNameChanged.replace(/{botName}/g, botName), Strings.botNameErr.replace(/{error}/g, error));
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.command('setbotdesc', spamwatchMiddleware, async (ctx) => {
|
bot.command('setbotdesc', spamwatchMiddleware, async (ctx) => {
|
||||||
|
@ -135,7 +135,7 @@ module.exports = (bot) => {
|
||||||
const botDesc = ctx.message.text.split(' ').slice(1).join(' ');
|
const botDesc = ctx.message.text.split(' ').slice(1).join(' ');
|
||||||
handleAdminCommand(ctx, async () => {
|
handleAdminCommand(ctx, async () => {
|
||||||
await ctx.telegram.setMyDescription(botDesc);
|
await ctx.telegram.setMyDescription(botDesc);
|
||||||
}, Strings.botDescChanged.replace('{botDesc}', botDesc), Strings.botDescErr.replace('{error}', error));
|
}, Strings.botDescChanged.replace(/{botDesc}/g, botDesc), Strings.botDescErr.replace(/{error}/g, error));
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.command('botkickme', spamwatchMiddleware, async (ctx) => {
|
bot.command('botkickme', spamwatchMiddleware, async (ctx) => {
|
||||||
|
@ -159,7 +159,7 @@ module.exports = (bot) => {
|
||||||
caption: botFile
|
caption: botFile
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.reply(Strings.unexpectedErr.replace('{error}', error.message), {
|
ctx.reply(Strings.unexpectedErr.replace(/{error}/g, error.message), {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
reply_to_message_id: ctx.message.message_id
|
reply_to_message_id: ctx.message.message_id
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,8 +6,8 @@ async function sendHelpMessage(ctx, isEditing) {
|
||||||
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 helpText = Strings.botHelp
|
const helpText = Strings.botHelp
|
||||||
.replace('{botName}', botInfo.first_name)
|
.replace(/{botName}/g, botInfo.first_name)
|
||||||
.replace("{sourceLink}", process.env.botSource);
|
.replace(/{sourceLink}/g, process.env.botSource);
|
||||||
const options = {
|
const options = {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
disable_web_page_preview: true,
|
disable_web_page_preview: true,
|
||||||
|
@ -35,7 +35,7 @@ module.exports = (bot) => {
|
||||||
|
|
||||||
bot.command("about", spamwatchMiddleware, async (ctx) => {
|
bot.command("about", spamwatchMiddleware, async (ctx) => {
|
||||||
const Strings = getStrings(ctx.from.language_code);
|
const Strings = getStrings(ctx.from.language_code);
|
||||||
const aboutMsg = Strings.botAbout.replace("{sourceLink}", `${process.env.botSource}`);
|
const aboutMsg = Strings.botAbout.replace(/{sourceLink}/g, `${process.env.botSource}`);
|
||||||
|
|
||||||
ctx.reply(aboutMsg, {
|
ctx.reply(aboutMsg, {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
|
|
|
@ -6,7 +6,7 @@ module.exports = (bot) => {
|
||||||
bot.start(spamwatchMiddleware, async (ctx) => {
|
bot.start(spamwatchMiddleware, async (ctx) => {
|
||||||
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}', botInfo.first_name);
|
const startMsg = Strings.botWelcome.replace(/{botName}/g, botInfo.first_name);
|
||||||
|
|
||||||
ctx.reply(startMsg, {
|
ctx.reply(startMsg, {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
|
|
|
@ -1,198 +1,212 @@
|
||||||
const { getStrings } = require('../plugins/checklang.js');
|
const { getStrings } = require('../plugins/checklang.js');
|
||||||
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
|
const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js');
|
||||||
const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch);
|
const spamwatchMiddleware = require('../plugins/lib-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');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const ytDlpPaths = {
|
const ytDlpPaths = {
|
||||||
linux: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp'),
|
linux: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp'),
|
||||||
win32: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp.exe'),
|
win32: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp.exe'),
|
||||||
darwin: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp_macos'),
|
darwin: path.resolve(__dirname, '../plugins/yt-dlp/yt-dlp_macos'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const getYtDlpPath = () => {
|
const getYtDlpPath = () => {
|
||||||
const platform = os.platform();
|
const platform = os.platform();
|
||||||
return ytDlpPaths[platform] || ytDlpPaths.linux;
|
return ytDlpPaths[platform] || ytDlpPaths.linux;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const ffmpegPaths = {
|
const ffmpegPaths = {
|
||||||
linux: '/usr/bin/ffmpeg',
|
linux: '/usr/bin/ffmpeg',
|
||||||
win32: path.resolve(__dirname, '../plugins/ffmpeg/bin/ffmpeg.exe'),
|
win32: path.resolve(__dirname, '../plugins/ffmpeg/bin/ffmpeg.exe'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFfmpegPath = () => {
|
const getFfmpegPath = () => {
|
||||||
const platform = os.platform();
|
const platform = os.platform();
|
||||||
return ffmpegPaths[platform] || ffmpegPaths.linux;
|
return ffmpegPaths[platform] || ffmpegPaths.linux;
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadFromYoutube = async (command, args) => {
|
const downloadFromYoutube = async (command, args) => {
|
||||||
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) {
|
||||||
reject({ error, stdout, stderr });
|
reject({ error, stdout, stderr });
|
||||||
} else {
|
} else {
|
||||||
resolve({ stdout, stderr });
|
resolve({ stdout, stderr });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getApproxSize = async (command, videoUrl) => {
|
const getApproxSize = async (command, videoUrl) => {
|
||||||
let args = [];
|
let args = [];
|
||||||
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 {
|
||||||
args = [videoUrl, '--compat-opt', 'manifest-filesize-approx', '-O', 'filesize_approx'];
|
args = [videoUrl, '--compat-opt', 'manifest-filesize-approx', '-O', 'filesize_approx'];
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const { stdout } = await downloadFromYoutube(command, args);
|
const { stdout } = await downloadFromYoutube(command, args);
|
||||||
const sizeInBytes = parseInt(stdout.trim(), 10);
|
const sizeInBytes = parseInt(stdout.trim(), 10);
|
||||||
if (!isNaN(sizeInBytes)) {
|
if (!isNaN(sizeInBytes)) {
|
||||||
return sizeInBytes / (1024 * 1024);
|
return sizeInBytes / (1024 * 1024);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = (bot) => {
|
module.exports = (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();
|
||||||
const userId = ctx.from.id;
|
const userId = ctx.from.id;
|
||||||
const videoUrl = ctx.message.text.split(' ').slice(1).join(' ');
|
const videoUrl = ctx.message.text.split(' ').slice(1).join(' ');
|
||||||
const mp4File = `tmp/${userId}.mp4`;
|
const mp4File = `tmp/${userId}.mp4`;
|
||||||
const tempMp4File = `tmp/${userId}.f137.mp4`;
|
const tempMp4File = `tmp/${userId}.f137.mp4`;
|
||||||
const tempWebmFile = `tmp/${userId}.f251.webm`;
|
const tempWebmFile = `tmp/${userId}.f251.webm`;
|
||||||
let cmdArgs = "";
|
let cmdArgs = "";
|
||||||
const dlpCommand = ytDlpPath;
|
const dlpCommand = ytDlpPath;
|
||||||
const ffmpegPath = getFfmpegPath();
|
const ffmpegPath = getFfmpegPath();
|
||||||
const ffmpegArgs = ['-i', tempMp4File, '-i', tempWebmFile, '-c:v copy -c:a copy -strict -2', mp4File];
|
const ffmpegArgs = ['-i', tempMp4File, '-i', tempWebmFile, '-c:v copy -c:a copy -strict -2', mp4File];
|
||||||
|
|
||||||
if (!videoUrl) {
|
if (!videoUrl) {
|
||||||
return ctx.reply(Strings.ytDownload.noLink, {
|
return ctx.reply(Strings.ytDownload.noLink, {
|
||||||
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
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fs.existsSync(path.resolve(__dirname, "../props/cookies.txt"))) {
|
if (fs.existsSync(path.resolve(__dirname, "../props/cookies.txt"))) {
|
||||||
cmdArgs = "--max-filesize 2G --no-playlist --cookies src/props/cookies.txt --merge-output-format mp4 -o";
|
cmdArgs = "--max-filesize 2G --no-playlist --cookies src/props/cookies.txt --merge-output-format mp4 -o";
|
||||||
} else {
|
} else {
|
||||||
cmdArgs = `--max-filesize 2G --no-playlist --merge-output-format mp4 -o`;
|
cmdArgs = `--max-filesize 2G --no-playlist --merge-output-format mp4 -o`;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const downloadingMessage = await ctx.reply(Strings.ytDownload.checkingSize, {
|
const downloadingMessage = await ctx.reply(Strings.ytDownload.checkingSize, {
|
||||||
parse_mode: 'Markdown',
|
parse_mode: 'Markdown',
|
||||||
reply_to_message_id: ctx.message.message_id,
|
reply_to_message_id: ctx.message.message_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (fs.existsSync(ytDlpPath)) {
|
if (fs.existsSync(ytDlpPath)) {
|
||||||
const approxSizeInMB = await Promise.race([
|
const approxSizeInMB = await Promise.race([
|
||||||
getApproxSize(ytDlpPath, videoUrl),
|
getApproxSize(ytDlpPath, videoUrl),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await ctx.telegram.editMessageText(
|
if (approxSizeInMB > 50) {
|
||||||
ctx.chat.id,
|
await ctx.telegram.editMessageText(
|
||||||
downloadingMessage.message_id,
|
ctx.chat.id,
|
||||||
null,
|
downloadingMessage.message_id,
|
||||||
Strings.ytDownload.downloadingVid, {
|
null,
|
||||||
parse_mode: 'Markdown',
|
Strings.ytDownload.uploadLimit, {
|
||||||
reply_to_message_id: ctx.message.message_id,
|
parse_mode: 'Markdown',
|
||||||
},
|
reply_to_message_id: ctx.message.message_id,
|
||||||
);
|
},
|
||||||
|
);
|
||||||
const dlpArgs = [videoUrl, ...cmdArgs.split(' '), mp4File];
|
|
||||||
await downloadFromYoutube(dlpCommand, dlpArgs);
|
return;
|
||||||
|
}
|
||||||
await ctx.telegram.editMessageText(
|
|
||||||
ctx.chat.id,
|
await ctx.telegram.editMessageText(
|
||||||
downloadingMessage.message_id,
|
ctx.chat.id,
|
||||||
null,
|
downloadingMessage.message_id,
|
||||||
Strings.ytDownload.uploadingVid, {
|
null,
|
||||||
parse_mode: 'Markdown',
|
Strings.ytDownload.downloadingVid, {
|
||||||
reply_to_message_id: ctx.message.message_id,
|
parse_mode: 'Markdown',
|
||||||
},
|
reply_to_message_id: ctx.message.message_id,
|
||||||
);
|
},
|
||||||
|
);
|
||||||
if (fs.existsSync(tempMp4File)) {
|
|
||||||
await downloadFromYoutube(ffmpegPath, ffmpegArgs);
|
const dlpArgs = [videoUrl, ...cmdArgs.split(' '), mp4File];
|
||||||
}
|
await downloadFromYoutube(dlpCommand, dlpArgs);
|
||||||
|
|
||||||
if (fs.existsSync(mp4File)) {
|
await ctx.telegram.editMessageText(
|
||||||
const message = Strings.ytDownload.msgDesc.replace("{userMention}", `[${ctx.from.first_name}](tg://user?id=${userId})`)
|
ctx.chat.id,
|
||||||
|
downloadingMessage.message_id,
|
||||||
try {
|
null,
|
||||||
await ctx.replyWithVideo({
|
Strings.ytDownload.uploadingVid, {
|
||||||
source: mp4File
|
parse_mode: 'Markdown',
|
||||||
}, {
|
reply_to_message_id: ctx.message.message_id,
|
||||||
caption: message,
|
},
|
||||||
parse_mode: 'Markdown',
|
);
|
||||||
reply_to_message_id: ctx.message.message_id,
|
|
||||||
});
|
if (fs.existsSync(tempMp4File)) {
|
||||||
|
await downloadFromYoutube(ffmpegPath, ffmpegArgs);
|
||||||
fs.unlinkSync(mp4File);
|
}
|
||||||
} catch (error) {
|
|
||||||
if (toString(error).includes("Request Entity Too Large")) {
|
if (fs.existsSync(mp4File)) {
|
||||||
await ctx.telegram.editMessageText(
|
const message = Strings.ytDownload.msgDesc.replace("{userMention}", `[${ctx.from.first_name}](tg://user?id=${userId})`)
|
||||||
ctx.chat.id,
|
|
||||||
downloadingMessage.message_id,
|
try {
|
||||||
null,
|
await ctx.replyWithVideo({
|
||||||
Strings.ytDownload.uploadLimit, {
|
source: mp4File
|
||||||
parse_mode: 'Markdown',
|
}, {
|
||||||
reply_to_message_id: ctx.message.message_id,
|
caption: message,
|
||||||
},
|
parse_mode: 'Markdown',
|
||||||
);
|
reply_to_message_id: ctx.message.message_id,
|
||||||
} else {
|
});
|
||||||
const errMsg = Strings.ytDownload.uploadErr.replace("{error}", error)
|
|
||||||
await ctx.telegram.editMessageText(
|
fs.unlinkSync(mp4File);
|
||||||
ctx.chat.id,
|
} catch (error) {
|
||||||
downloadingMessage.message_id,
|
if (error.response.description.includes("Request Entity Too Large")) {
|
||||||
null,
|
await ctx.telegram.editMessageText(
|
||||||
errMsg, {
|
ctx.chat.id,
|
||||||
parse_mode: 'Markdown',
|
downloadingMessage.message_id,
|
||||||
reply_to_message_id: ctx.message.message_id,
|
null,
|
||||||
},
|
Strings.ytDownload.uploadLimit, {
|
||||||
);
|
parse_mode: 'Markdown',
|
||||||
};
|
reply_to_message_id: ctx.message.message_id,
|
||||||
|
},
|
||||||
fs.unlinkSync(mp4File);
|
);
|
||||||
}
|
} else {
|
||||||
} else {
|
const errMsg = Strings.ytDownload.uploadErr.replace("{error}", error)
|
||||||
await ctx.reply(mp4File, {
|
await ctx.telegram.editMessageText(
|
||||||
parse_mode: 'Markdown',
|
ctx.chat.id,
|
||||||
reply_to_message_id: ctx.message.message_id,
|
downloadingMessage.message_id,
|
||||||
});
|
null,
|
||||||
}
|
errMsg, {
|
||||||
} else {
|
parse_mode: 'Markdown',
|
||||||
await ctx.telegram.editMessageText(
|
reply_to_message_id: ctx.message.message_id,
|
||||||
ctx.chat.id,
|
},
|
||||||
downloadingMessage.message_id,
|
);
|
||||||
null,
|
};
|
||||||
Strings.ytDownload.libNotFound, {
|
|
||||||
parse_mode: 'Markdown',
|
fs.unlinkSync(mp4File);
|
||||||
reply_to_message_id: ctx.message.message_id,
|
}
|
||||||
},
|
} else {
|
||||||
);
|
await ctx.reply(mp4File, {
|
||||||
}
|
parse_mode: 'Markdown',
|
||||||
} catch (error) {
|
reply_to_message_id: ctx.message.message_id,
|
||||||
const errMsg = Strings.ytDownload.uploadErr.replace("{error}", error)
|
});
|
||||||
await ctx.telegram.editMessageText(
|
}
|
||||||
ctx.chat.id,
|
} else {
|
||||||
downloadingMessage.message_id,
|
await ctx.telegram.editMessageText(
|
||||||
null,
|
ctx.chat.id,
|
||||||
errMsg, {
|
downloadingMessage.message_id,
|
||||||
parse_mode: 'Markdown',
|
null,
|
||||||
reply_to_message_id: ctx.message.message_id,
|
Strings.ytDownload.libNotFound, {
|
||||||
},
|
parse_mode: 'Markdown',
|
||||||
);
|
reply_to_message_id: ctx.message.message_id,
|
||||||
}
|
},
|
||||||
});
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const errMsg = Strings.ytDownload.uploadErr.replace("{error}", error)
|
||||||
|
await ctx.telegram.editMessageText(
|
||||||
|
ctx.chat.id,
|
||||||
|
downloadingMessage.message_id,
|
||||||
|
null,
|
||||||
|
errMsg, {
|
||||||
|
parse_mode: 'Markdown',
|
||||||
|
reply_to_message_id: ctx.message.message_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"botWelcome": "*Hello! I am {botName}!*\nI was made with love by some nerds who really love programming!\n\n*Before using, you need to read the privacy policy (/privacy) to 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](https://blog.lucmsilva.com/posts/lynx-privacy-policy) 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})",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"botWelcome": "*Olá! Eu sou o {botName}!*\n\n*Antes de usar, você precisa ler a política de privacidade (/privacy) para 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](https://blog.lucmsilva.com/posts/lynx-privacy-policy) 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})",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue