Telegram-боты — дешевый и действенный способ генерации трафика. А если учесть, что Телега теперь выплачивает комиссию создателям контента, это даже можно считать способом заработка. Но чтобы трафик лился сам, нужен бот-парсер, который все сделает за вас. Одной из вариаций такого бота может стать бот для скачивания музыки.
«Но ведь музыка — это терабайты информации и бесчисленные сервера для их хранения», — скажете вы. И будете правы. Но разве кто-то говорил, что эту инфраструктуру нужно создавать или хотя бы поддерживать вам? С помощью нехитрого Telegram-бота можно просто скачивать музыку иКак все это провернуть, мы и расскажем сегодня.
Принцип работы бота для скачивания музыки из ВК
Алгоритмически это очень простой бот — это тот самый момент, когда интерфейс бота занимает больше строк кода, чем его функциональная часть. Но тут уж извините — все вопросы к Телеге с ее кнопками. Тем не менее со своей задачей он справляется, а большего нам и не надо. з VK и передавать юзеру в Telegram. Попутно предлагая ему подписаться на нужные вам каналы.
Впрочем, так как бот одной ногой в Telegram, а второй в ВК — у совсем далеких от темы людей могут возникнуть трудности. Но на деле все очень просто и сводится к следующему:
- Бот авторизуется в ВК и Telegram.
- Затем он прослушивает эфир, ожидая запросов от пользователя
- Как только юзер присылает сообщение, которое не является сервисным (/start, /help и т. д.), бот пересылает его в ВК, в «строку поиска по музыке». На самом деле он делает не это, но те, кто в теме, — и так в теме. В любом случае так будет проще представить принцип работы бота.
- Итак, сообщение от юзера «введено в поиск по музыке», на что ВК выдает соответствующие треки. Ну или не выдает, если нет совпадений — это бот тоже учитывает.
- Ответ от ВК «нарезается» на фрагменты по 10 треков (для удобства), и первые 10 присылаются юзеру в Телеге.
- Далее он либо указывает номер искомой песни, либо жмет «Вперед»/«Назад» — для перехода к следующей/предыдущей пачке песен, соответствующих его запросу.
- При вводе номера трека бот его считывает и проверяет, подписан ли пользователь на рекламируемый канал. Если нет — предлагает подписаться.
- Если юзер подписан, бот скачивает трек из ВК и загружает его в Телегу. После завершения загрузки в Telegram бот удаляет трек со своего сервера для экономии места.
Пошаговая инструкция, как сделать Telegram-бота для скачивания музыки из ВК
Само собой, сперва нам понадобится сервер. С этого начинается развертывание любого Telegram-бота. Какой именно сервер использовать, решайте сами. Лишь бы он поддерживал Python. Если вы делаете все это впервые, держите в помощь статью о том, как создать свой Python-сервер, — тестировать лучше на своем железе, а переносить уже после того, как освоитесь. После запуска сервера его нужно настроить, для этого в консоли вводим:
pip install telegram
А все — больше никаких сторонних библиотек. Взаимодействие с ВК будет на базовых для Python request’ах, так что далее только код. Впрочем, код кодом, но сначала получаем токены:
- Для получения токена для бота от Телеги пишем в ЛС к BotFather, выполняем его инструкции и сохраняем присвоенный токен.
- Для получения токена от ВК переходим на vkhost и следуем инструкции. Обратите внимание: токен дает полный доступ к вашей странице — так что не используйте личный аккаунт!
- Затем создаем файл bot.py и вставляем туда следующий код:
import os
import requestsfrom telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ApplicationBuilder, CallbackContext, CommandHandler, CallbackQueryHandler, MessageHandler, filters
class VKBot:
def __init__(self, token):
self.token = token
self.api_version = '5.131'
def search_audio(self, query, offset=0, count=10):
params = {
'access_token': self.token,
'v': self.api_version,
'q': query,
'count': count,
'offset': offset
}
response = requests.get('https://api.vk.com/method/audio.search', params=params)
if response.status_code == 200:
return response.json().get('response', {}).get('items', [])
else:
print(f"Ошибка при выполнении запроса: {response.status_code}")
return []
def get_audio_url(self, owner_id, audio_id):
params = {
'access_token': self.token,
'v': self.api_version,
'audios': f"{owner_id}_{audio_id}"
}
response = requests.get('https://api.vk.com/method/audio.getById', params=params)
if response.status_code == 200:
audio_url = response.json().get('response')[0].get('url')
return audio_url
else:
print(f"Ошибка при получении URL аудиозаписи: {response.status_code}")
return None
def download_audio(self, audio_url, save_path):
try:
response = requests.get(audio_url, stream=True)
if response.status_code == 200:
with open(save_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=1024):
f.write(chunk)
print(f"Аудиозапись успешно сохранена как '{save_path}'")
return save_path
else:
print(f"Ошибка при скачивании аудиозаписи: {response.status_code}")
return None
except Exception as e:
print(f"Произошла ошибка: {str(e)}")
return None
async def start(update: Update, context: CallbackContext) -> None:
await update.message.reply_text('Введите название трека для поиска:')
async def handle_message(update: Update, context: CallbackContext) -> None:
query = update.message.text
context.user_data['query'] = query
context.user_data['offset'] = 0
await show_results(update, context)
async def show_results(update: Update, context: CallbackContext) -> None:
query = context.user_data.get('query')
offset = context.user_data.get('offset', 0)
results = bot.search_audio(query, offset=offset, count=10)
if results:
keyboard = [[InlineKeyboardButton(f"{track['artist']} - {track['title']}", callback_data=f"track_{idx}")] for idx, track in enumerate(results)]
keyboard.append([InlineKeyboardButton('Предыдущая страница', callback_data='prev'), InlineKeyboardButton('Следующая страница', callback_data='next')])
keyboard.append([InlineKeyboardButton('Выйти', callback_data='quit')])
reply_markup = InlineKeyboardMarkup(keyboard)
if isinstance(update, Update):
await update.message.reply_text(f"Результаты {offset + 1} - {offset + len(results)}:", reply_markup=reply_markup)
else:
await update.edit_message_text(f"Результаты {offset + 1} - {offset + len(results)}:", reply_markup=reply_markup)
else:
await update.message.reply_text("Результаты не найдены.")
async def button(update: Update, context: CallbackContext) -> None:
query = update.callback_query
await query.answer()
data = query.data
if data == 'next':
context.user_data['offset'] += 10
await show_results(query, context)
elif data == 'prev':
if context.user_data['offset'] >= 10:
context.user_data['offset'] -= 10
await show_results(query, context)
elif data == 'quit':
await query.message.delete()
elif data.startswith('track_'):
idx = int(data.split('_')[1])
results = bot.search_audio(context.user_data['query'], offset=context.user_data['offset'], count=10)
audio = results[idx]
audio_url = bot.get_audio_url(audio['owner_id'], audio['id'])
if audio_url:
if await check_subscriptions(update, context):
save_path = f"{audio['artist']} - {audio['title']}.mp3"
file_path = bot.download_audio(audio_url, save_path)
if file_path:
with open(file_path, 'rb') as f:
await query.message.reply_audio(audio=f, title=audio['title'], performer=audio['artist'])
os.remove(file_path)
else:
await query.message.reply_text("Не удалось скачать аудиозапись")
else:
await query.message.reply_text("Пожалуйста, подпишитесь на все указанные каналы и нажмите 'Проверить подписку'.")
else:
await query.message.reply_text("Не удалось получить URL аудиозаписи")
elif data == 'check_subscription':
if await check_subscriptions(update, context):
await query.message.reply_text("Подписка подтверждена. Теперь вы можете получить аудиозапись.")
else:
await query.message.reply_text("Вы еще не подписались на все необходимые каналы.")
async def check_subscriptions(update: Update, context: CallbackContext) -> bool:
user_id = update.callback_query.from_user.id
ads_file = 'ads.txt'
if not os.path.exists(ads_file):
return True
with open(ads_file, 'r') as f:
channels = [line.strip() for line in f if line.strip()]
if not channels:
return True
not_subscribed_channels = []
for channel in channels:
try:
chat_member = await context.bot.get_chat_member(chat_id=channel, user_id=user_id)
if chat_member.status not in ['member', 'administrator', 'creator']:
not_subscribed_channels.append(channel)
except:
not_subscribed_channels.append(channel)
if not_subscribed_channels:
keyboard = [[InlineKeyboardButton('Проверить подписку', callback_data='check_subscription')]]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.callback_query.message.reply_text(
f"Пожалуйста, подпишитесь на следующие каналы и нажмите 'Проверить подписку':\n" + "\n".join(not_subscribed_channels),
reply_markup=reply_markup
)
return False
return True
if __name__ == '__main__':
vk_token = 'ВК ТОКЕН'
bot = VKBot(vk_token)
tg_token = 'ТГ ТОКЕН'
application = ApplicationBuilder().token(tg_token).build()
application.add_handler(CommandHandler('start', start))
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
application.add_handler(CallbackQueryHandler(button))
application.run_polling() - Сохраняем код в нашем файле, предварительно подставив нужные токены в соответствующие места.
- Создаем файл ads.txt и добавляем в него нужные нам каналы в формате @channel. Если не создавать файл — бот проигнорирует проверку подписки.
* НЕ РЕКОМЕНДУЕМ ВНОСИТЬ БОЛЕЕ 3 КАНАЛОВ — ЭТО СУЩЕСТВЕННО СНИЗИТ КОНВЕРСИЮ! - Осталось только запустить бот. Для этого вводим в консоль:
python bot.py - Ну и тестируем!
Демонстрация работы.
Подводя итоги
Несмотря на кажущиеся трудности, развернуть бот для генерации трафика с помощью парсинга музыки не так уж и сложно. И даже собственные data-hub’ы с терабайтами треков для этого не нужны. На этом все — подписывайтесь на нашу Телегу и получайте исходный код для арбитражных ботов первыми!