Я создал Telegram-бота (FYTT), который ищет Telegram-каналы всех ваших подписок на YouTube

Я создал Telegram-бота (FYTT), который ищет Telegram-каналы всех ваших подписок на YouTube

Идея создания бота пришла после замедления YouTube в России. Многие блогеры стали активно призывать подписчиков переходить в Telegram, чтобы не потерять связь с аудиторией. Я решил сделать удобный инструмент для быстрого поиска Telegram-каналов любимых авторов.

Что я использовал?

Поскольку опыта в разработке у меня было мало, я выбрал следующий стек технологий:

Node.js с библиотекой telegraf.js для работы с Telegram API

MongoDB и mongoose для работы с базой данных

Express.js для создания веб-сервера

Google API для работы с YouTube

Lemnos API для получения дополнительной информации о каналах

Реализация

1. Основные команды бота

Начнем с главной команды /start, которая инициализирует работу с ботом:

bot.start(async (ctx) => { const chatId = ctx.chat.id; let chat = await Analytics.findOne({ chatId: chatId }) // Создаем новую запись пользователя, если его нет в базе if (chat === null) { try { let username = ctx.message.chat.username let newChat = new Analytics({ chatId: ctx.message.chat.id, username: username, awatingChannels: true, status: "member", count: 0 }) await newChat.save() } catch { // Если username недоступен, используем first_name let newChat = new Analytics({ chatId: ctx.message.chat.id, username: ctx.message.chat.first_name, awatingChannels: true, status: "member", count: 0 }) await newChat.save() } } else { chat.awatingChannels = true await chat.save() }

// Отправляем приветственное сообщение с кнопками await setBotCommands() ctx.replyWithHTML( 'Приветствуем вас в нашем сервисе поиска Telegram-каналов ютуберов!\n' + 'Бот безопасен, так как представляет собой открытый исходный код, ' + 'который может посмотреть каждый желающий. (/faq или пишите @vitosperansky)\n\n' + 'Поддержать проект: https://www.donationalerts.com/r/vitosperansky\n\n' + 'Выберите опцию:', Markup.inlineKeyboard([ [Markup.button.callback('Найти YouTube-каналы в Telegram', 'find_channels')], [Markup.button.callback('Связать YouTube-канал с Telegram-каналом', 'link_channel')] ]), { disable_web_page_preview: true } ); });

2. Авторизация через Google

Для работы с YouTube API необходима авторизация через Google. Вот как реализована генерация URL для авторизации:

async function generateAuthUrl(chatId) { const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH)); const { client_id, client_secret } = credentials.web; const oAuth2Client = new OAuth2Client( client_id, client_secret, REDIRECT_URL ); const authUrl = oAuth2Client.generateAuthUrl({ access_type: 'online', scope: SCOPES, state: chatId.toString() }); return authUrl; }

Когда пользователь нажимает на кнопку поиска каналов, запускается следующий обработчик:

const find_channels = async (ctx) => { const chatId = ctx.chat.id; const authUrl = await generateAuthUrl(chatId, ctx);

ctx.replyWithMarkdown( '*Нажмите кнопку ниже для авторизации на Youtube и получения списка ваших подписок:*\n\n' + '❗Авторизация нужна только для получения списка ваших подписок ' + '(запрашиваются права youtube.readonly - только чтения, подробнее /faq)❗\n\n' + '_Процесс займет время: ~50 секунд. (в зависимости от количества ваших подписок)_', { reply_markup: { inline_keyboard: [ [{ text: 'Авторизоваться и найти подписки', url: authUrl }] ] } } ); };

// Обработчики команды поиска каналов bot.action('find_channels', async (ctx) => { ctx.answerCbQuery(); await find_channels(ctx) })

bot.command('find_channels', async (ctx) => { await find_channels(ctx) })

3. Дополнительные команды

Бот также имеет несколько дополнительных команд для удобства использования:

// Команда FAQ bot.command('faq', async (ctx) => { ctx.replyWithMarkdown(` **Ответы на вопросы о проекте:**

Какова цель проекта? — Максимально упростить поиск Телеграмм каналов ваших любимых авторов.

У меня не украдут Google Аккаунт? — Нет, бот имеет открытый исходный код, который может посмотреть каждый желающий на Github - https://github.com/VitoSperansky/FromYoutubeToTelegram.

Как работает бот? — Бот просит вас авторизоваться в свой Google аккаунт, чтобы получить список ваших подписок на YouTube. Затем система обращается к своей базе данных, где хранятся соответствия YouTube-каналов и их Телеграмм-каналов. Если бот находит соответствия в базе данных, он записывает их в список найденных каналов. Если YouTube-каналы, на которые вы подписаны, отсутствуют в нашей базе данных, бот отправляет запрос в YouTube на получение ссылок социальных сетей, привязанных к каналу. Среди этих ссылок бот ищет ссылку на Телеграмм. Найдя новую ссылку на Телеграмм-канал, бот добавляет её в базу данных. В итоге, пользователь получает список YouTube-каналов с их Телеграмм-каналами.

Остались вопросы? - Пишите @vitosperansky `); });

// Команда для рассылки сообщений (только для администратора) bot.command('send', async (ctx) => { if (ctx.message.chat.id == MODERATOR_CHAT_ID) { let chatId = ctx.message.text.replace('/send ', '').replace(/ [\s\S]+/, ''); let text = ctx.message.text.replace('/send ', '').replace(`${chatId} `, '').toString();

if(chatId === 'all') { let Users = await Analytics.find() let goodSend = []; let badSend = []; ctx.reply("Рассылка началась.") for (let i = 0; i < Users.length; i++) { try { await bot.telegram.sendMessage(Users[i].chatId, text, { parse_mode: "HTML" }); goodSend.push(Users[i]); } catch (error) { badSend.push(Users[i]); } } ctx.reply(`Рассылка завершена\n\nУспешно отправлено: ${goodSend.length} сообщений.\n` + `Не получилось отправить: ${badSend.length} сообщений.`) } else { try { await bot.telegram.sendMessage(chatId, text, { parse_mode: "HTML" }); ctx.reply(`Сообщение успешно отправлено пользователю. \n\nChatId: ${chatId}\nТекст: ${text}`) } catch { ctx.reply("Ошибка при отправке сообщения.") } } } else { ctx.reply("Вы не админ!") } });

Проблемы и их решения

1. Проблема дублирования запросов

При авторизации в Google-аккаунте возникла проблема с дублированием запросов, если у пользователя несколько аккаунтов. Для решения этой проблемы я использовал флаг awaitingChannels в базе данных, который позволяет отслеживать состояние запроса и избегать дублирования.

2. Ограничение длины сообщений

В первых версиях бот пытался отправить все найденные каналы одним сообщением, но столкнулся с ограничением Telegram на длину сообщения. Решение было простым - разбить информацию на несколько сообщений. (присылать txt файлом к примеру не совсем верно, ведь тогда теряется легкость в переходе на телеграм канал).

3. Сайт

Сайт работает на порту 3000 (fytt.tech:3000), что не совсем стандартно для веб-приложений. Это связано с тем, что порты ниже 1024 по умолчанию закрыты для установки серверов из соображений безопасности. В идеале следовало бы настроить переадресацию с порта 443 (стандартный HTTPS порт) с помощью инструмента вроде ngrok, но поскольку сайт служит в основном для верификации Google, эта задача была отложена.

Процесс верификации Google

Получение доступа к YouTube API потребовало пройти верификацию Google. Процесс включал несколько этапов:

Создание логотипа: Первая версия логотипа была отклонена из-за слишком явного использования элементов YouTube и Telegram. Пришлось создать более оригинальный дизайн.

1 версия - отклонена (кто-то увидел тут силуэт лица человека xD)

2 версия — принято (на фоне текст fromyoutubetotelegram)

Разработка сайта: Потребовалось создать сайт с политикой конфиденциальности и пользовательским соглашением. При этом возникли следующие требования:

Необходимость владения доменом

Настройка SSL-сертификатов через certbot

Корректная политика конфиденциальности

Демонстрация работы: Создание демо-видео для показа функционала бота. (пришлось им видео записать под смешную музыку)

Продвижение проекта

Потом я решил продвинуть бота и записал два смешных shorts:

https://youtu.be/N0IGLuufSCE — text to speech (elevenlabs)

https://youtu.be/MlXEUIDBhE0 — Speech to speech моей записи на ии оригинального голоса Рика из Рика и Морти (сделал на этом сайте).

Полезные ссылки

Бот: https://t.me/FYTTproject_bot

Исходный код: https://github.com/VitoSperansky/FromYoutubeToTelegram

Сайт: fytt.tech:3000

Контакты для связи: https://t.me/vitosperansky

Планы на будущее

Улучшение алгоритма поиска каналов

Оптимизация работы с базой данных

Добавление новых функций по запросам пользователей

Настройка правильной маршрутизации портов на сервере

Заключение

Проект показал, что даже с минимальным опытом разработки можно создать полезный инструмент, который решает реальную проблему пользователей. Открытый исходный код и прозрачность работы позволили завоевать доверие пользователей, а интеграция с популярными платформами обеспечила удобство использования.

Начать дискуссию