Merge branch 'main' into ai-features
This commit is contained in:
commit
995f61b0b9
10 changed files with 101 additions and 35 deletions
|
@ -1,5 +1,5 @@
|
|||
# links for source and privacy
|
||||
botPrivacy = "https://blog.lucmsilva.com/posts/lynx-privacy-policy"
|
||||
botPrivacy = "https://github.com/abocn/TelegramBot/blob/main/TERMS_OF_USE.md"
|
||||
botSource = "https://github.com/ABOCN/TelegramBot"
|
||||
|
||||
# insert token here
|
||||
|
|
18
TERMS_OF_USE.md
Normal file
18
TERMS_OF_USE.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Terms of Use
|
||||
|
||||
By using Kowalski ([@KowalskiNodeBot](https://t.me/KowalskiNodeBot), you agree to the terms outlined below. If you do not agree with any of these terms, please discontinue use of the bot immediately.
|
||||
|
||||
## 1. Blocklist System
|
||||
|
||||
We reserve the right to block users from accessing the bot based on their behavior. Users who generate inappropriate content or misuse the bot will be permanently blocked by user ID. Attempts to circumvent a block by using alternative or secondary accounts will also result in those accounts being blocked.
|
||||
|
||||
Additionally, Kowalski integrates with the SpamWatch API to automatically deny access to users banned by that system. If you are listed in SpamWatch, you will not be able to use the bot.
|
||||
|
||||
## 2. Source Code
|
||||
|
||||
The bot's source code is publicly available. You can review it at the Kowalski GitHub Repository:
|
||||
[https://github.com/abocn/TelegramBot](https://github.com/abocn/TelegramBot)
|
||||
|
||||
## 3. Changes to These Terms
|
||||
|
||||
We may modify or update these Terms of Use at any time, with or without prior notice. Continued use of the bot constitutes acceptance of the latest version of the terms.
|
|
@ -3,9 +3,9 @@
|
|||
"start": "nodemon src/bot.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dotenvx/dotenvx": "^1.42.2",
|
||||
"@types/bun": "^1.2.11",
|
||||
"axios": "^1.9.0",
|
||||
"@dotenvx/dotenvx": "^1.45.1",
|
||||
"@types/bun": "^1.2.17",
|
||||
"axios": "^1.10.0",
|
||||
"node-html-parser": "^7.0.1",
|
||||
"nodemon": "^3.1.10",
|
||||
"telegraf": "^4.16.3",
|
||||
|
|
|
@ -63,7 +63,7 @@ function getRandomInt(max: number) {
|
|||
export default (bot: Telegraf<Context>) => {
|
||||
bot.command('random', spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => {
|
||||
const Strings = getStrings(languageCode(ctx));
|
||||
const randomValue = getRandomInt(11);
|
||||
const randomValue = getRandomInt(10);
|
||||
const randomVStr = Strings.randomNum.replace('{number}', randomValue);
|
||||
|
||||
ctx.reply(
|
||||
|
|
|
@ -60,6 +60,13 @@ export default (bot: Telegraf<Context>) => {
|
|||
if (verifyInput(ctx, userInput, invalidCode, true)) {
|
||||
return;
|
||||
}
|
||||
if (userInput.length !== 3) {
|
||||
ctx.reply(Strings.httpCodes.invalidCode, {
|
||||
parse_mode: 'Markdown',
|
||||
...({ reply_to_message_id })
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const apiUrl = `${Resources.httpCatApi}${userInput}`;
|
||||
|
||||
|
|
|
@ -61,23 +61,27 @@ export default (bot: Telegraf<Context>) => {
|
|||
...({ reply_to_message_id })
|
||||
});
|
||||
}
|
||||
|
||||
const result = await downloadModule(moduleId);
|
||||
|
||||
if (result) {
|
||||
const { filePath, fileName } = result;
|
||||
|
||||
await ctx.replyWithDocument({ source: filePath }, {
|
||||
caption: fileName,
|
||||
...({ reply_to_message_id })
|
||||
});
|
||||
|
||||
fs.unlinkSync(filePath);
|
||||
} else {
|
||||
ctx.reply(Strings.maDownloadError, {
|
||||
parse_mode: "Markdown",
|
||||
...({ reply_to_message_id })
|
||||
});
|
||||
const numberRegex = /^\d+$/;
|
||||
const isNumber = numberRegex.test(moduleId);
|
||||
if (isNumber) {
|
||||
const result = await downloadModule(moduleId);
|
||||
if (result) {
|
||||
const { filePath, fileName } = result;
|
||||
const regexExtension = /\.\w+$/i;
|
||||
const hasExtension = regexExtension.test(fileName);
|
||||
if (hasExtension) {
|
||||
await ctx.replyWithDocument({ source: filePath }, {
|
||||
caption: fileName,
|
||||
...({ reply_to_message_id })
|
||||
});
|
||||
fs.unlinkSync(filePath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ctx.reply(Strings.maInvalidModule, {
|
||||
parse_mode: "Markdown",
|
||||
...({ reply_to_message_id })
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -14,6 +14,10 @@ export default (bot: Telegraf<Context>) => {
|
|||
bot.command(["rpony", "randompony", "mlpart"], spamwatchMiddleware, async (ctx: Context & { message: { text: string } }) => {
|
||||
const Strings = getStrings(languageCode(ctx));
|
||||
const reply_to_message_id = replyToMessageId(ctx);
|
||||
ctx.reply(Strings.ponyApi.searching, {
|
||||
parse_mode: 'Markdown',
|
||||
...({ reply_to_message_id })
|
||||
});
|
||||
try {
|
||||
const response = await axios(Resources.randomPonyApi);
|
||||
let tags: string[] = [];
|
||||
|
|
|
@ -63,13 +63,22 @@ const getApproxSize = async (command: string, videoUrl: string): Promise<number>
|
|||
}
|
||||
};
|
||||
|
||||
const isValidUrl = (url: string): boolean => {
|
||||
try {
|
||||
new URL(url);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export default (bot) => {
|
||||
bot.command(['yt', 'ytdl', 'sdl', 'video', 'dl'], spamwatchMiddleware, async (ctx) => {
|
||||
const Strings = getStrings(ctx.from.language_code);
|
||||
const ytDlpPath = getYtDlpPath();
|
||||
const userId: number = ctx.from.id;
|
||||
const videoUrl: string = ctx.message.text.split(' ').slice(1).join(' ');
|
||||
const videoUrlSafe: boolean = ytUrl.valid(videoUrl);
|
||||
const videoIsYoutube: boolean = ytUrl.valid(videoUrl);
|
||||
const randId: string = Math.random().toString(36).substring(2, 15);
|
||||
const mp4File: string = `tmp/${userId}-${randId}.mp4`;
|
||||
const tempMp4File: string = `tmp/${userId}-${randId}.f137.mp4`;
|
||||
|
@ -79,22 +88,30 @@ export default (bot) => {
|
|||
const ffmpegPath: string = getFfmpegPath();
|
||||
const ffmpegArgs: string[] = ['-i', tempMp4File, '-i', tempWebmFile, '-c:v copy -c:a copy -strict -2', mp4File];
|
||||
|
||||
console.log(`DOWNLOADING: ${videoUrl}\nSAFE: ${videoUrlSafe}\n`)
|
||||
|
||||
/*
|
||||
for now, no checking is done for the video url
|
||||
yt-dlp should handle the validation, though it supports too many sites to hard-code
|
||||
*/
|
||||
if (!videoUrl) {
|
||||
return ctx.reply(Strings.ytDownload.noLink, {
|
||||
parse_mode: "Markdown",
|
||||
disable_web_page_preview: true,
|
||||
reply_to_message_id: ctx.message.message_id
|
||||
});
|
||||
} else if (!videoUrlSafe) {
|
||||
return ctx.reply(Strings.ytDownload.notYtLink, {
|
||||
}
|
||||
|
||||
// make sure its a valid url
|
||||
if (!isValidUrl(videoUrl)) {
|
||||
console.log("[!] Invalid URL:", videoUrl)
|
||||
return ctx.reply(Strings.ytDownload.noLink, {
|
||||
parse_mode: "Markdown",
|
||||
disable_web_page_preview: true,
|
||||
reply_to_message_id: ctx.message.message_id
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`\nDownload Request:\nURL: ${videoUrl}\nYOUTUBE: ${videoIsYoutube}\n`)
|
||||
|
||||
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";
|
||||
} else {
|
||||
|
@ -113,6 +130,7 @@ export default (bot) => {
|
|||
]);
|
||||
|
||||
if (approxSizeInMB > 50) {
|
||||
console.log("[!] Video size exceeds 50MB:", approxSizeInMB)
|
||||
await ctx.telegram.editMessageText(
|
||||
ctx.chat.id,
|
||||
downloadingMessage.message_id,
|
||||
|
@ -126,6 +144,7 @@ export default (bot) => {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log("[i] Downloading video...")
|
||||
await ctx.telegram.editMessageText(
|
||||
ctx.chat.id,
|
||||
downloadingMessage.message_id,
|
||||
|
@ -139,6 +158,7 @@ export default (bot) => {
|
|||
const dlpArgs = [videoUrl, ...cmdArgs.split(' '), mp4File];
|
||||
await downloadFromYoutube(dlpCommand, dlpArgs);
|
||||
|
||||
console.log("[i] Uploading video...")
|
||||
await ctx.telegram.editMessageText(
|
||||
ctx.chat.id,
|
||||
downloadingMessage.message_id,
|
||||
|
@ -209,14 +229,25 @@ export default (bot) => {
|
|||
},
|
||||
);
|
||||
}
|
||||
console.log("[i] Request completed\n")
|
||||
} catch (error) {
|
||||
const errMsg = Strings.ytDownload.uploadErr.replace("{error}", error)
|
||||
let errMsg = Strings.ytDownload.uploadErr
|
||||
|
||||
if (error.stderr.includes("--cookies-from-browser")) {
|
||||
console.log("[!] Ratelimited by video provider:", error.stderr)
|
||||
errMsg = Strings.ytDownload.botDetection
|
||||
if (error.stderr.includes("youtube")) {
|
||||
errMsg = Strings.ytDownload.botDetection.replace("video provider", "YouTube")
|
||||
}
|
||||
} else {
|
||||
console.log("[!]", error.stderr)
|
||||
}
|
||||
|
||||
// will no longer edit the message as the message context is not outside the try block
|
||||
await ctx.reply(errMsg, {
|
||||
parse_mode: 'Markdown',
|
||||
reply_to_message_id: ctx.message.message_id,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
|
@ -75,11 +75,11 @@
|
|||
"uploadingVid": "⬆️ *Uploading video...*",
|
||||
"msgDesc": "{userMention}*, there is your downloaded video.*",
|
||||
"downloadErr": "*Error during YT video download:*\n\n`{err}`",
|
||||
"uploadErr": "Error uploading file. Please try again later.\n\n{error}",
|
||||
"uploadErr": "Error uploading file. Please try again later.",
|
||||
"uploadLimit": "*This video exceeds the 50 MB upload limit imposed by Telegram on our bot. Please try another video. We're doing our best to increase this limit.*",
|
||||
"sizeLimitWarn": "*This video had its quality reduced because it exceeded the 50MB limit for uploads imposed by Telegram.*",
|
||||
"noLink": "Please provide a link to a video to download.",
|
||||
"notYtLink": "Please provide a valid YouTube link to download."
|
||||
"botDetection": "My server is being rate limited by the video provider! Please try again later, or ask the bot owner to add their cookies/account."
|
||||
},
|
||||
"botUpdated": "Bot updated with success.\n\n```{result}```",
|
||||
"errorUpdatingBot": "Error updating bot\n\n{error}",
|
||||
|
@ -106,6 +106,7 @@
|
|||
"noEpisodeFound": "No episode found.",
|
||||
"noComicName": "Please provide the comic's name.",
|
||||
"noComicFound": "No comic found.",
|
||||
"searching": "Searching for a character…",
|
||||
"apiErr": "An error occurred while fetching data from the API.\n\n`{error}`"
|
||||
},
|
||||
"codenameCheck": {
|
||||
|
|
|
@ -75,11 +75,11 @@
|
|||
"uploadingVid": "*Enviando vídeo...*",
|
||||
"msgDesc": "{userMention}*, aqui está o seu vídeo baixado.*",
|
||||
"downloadErr": "*Erro durante o download do vídeo do YT:*\n\n`{err}`",
|
||||
"uploadErr": "Erro ao enviar o arquivo. Tente novamente mais tarde.\n\n{error}",
|
||||
"uploadErr": "Erro ao enviar o arquivo. Tente novamente mais tarde.",
|
||||
"uploadLimit": "*Este vídeo excede o limite de carregamento de 50 MB imposto pelo Telegram ao nosso bot. Por favor, tente outro vídeo. Estamos fazendo o possível para aumentar esse limite.*",
|
||||
"sizeLimitWarn": "*Esse vídeo teve a qualidade reduzida por estar excedendo o limite de 50MB para uploads imposto pelo Telegram.*",
|
||||
"noLink": "*Por favor, forneça um link de um vídeo para download.*",
|
||||
"notYtLink": "*Forneça um link válido do YouTube para fazer o download.*"
|
||||
"botDetection": "Meu servidor está com a taxa limitada pelo provedor de vídeo! Tente novamente mais tarde ou peça ao proprietário do bot para adicionar seus cookies/conta."
|
||||
},
|
||||
"botUpdated": "Bot atualizado com sucesso.\n\n```{result}```",
|
||||
"errorUpdatingBot": "Erro ao atualizar o bot\n\n{error}",
|
||||
|
@ -106,6 +106,7 @@
|
|||
"noEpisodeFound": "Nenhum episódio encontrado.",
|
||||
"noComicName": "Por favor, forneça o nome da comic.",
|
||||
"noComicFound": "Nenhuma comic foi encontrada.",
|
||||
"searching": "Procurando por um personagem…",
|
||||
"apiErr": "Ocorreu um erro ao buscar dados da API.\n\n`{error}`"
|
||||
},
|
||||
"codenameCheck": {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue