Исходный код тг‐бота - GeraDrobierro/MUSICFLOW GitHub Wiki

ИСХОДНЫЙ КОД

import telebot
from telebot import types
import sqlite3  # Импортирую библиотеку для работы с БД
import os  # импортирую библиотеку для работы с сервером

bot = telebot.TeleBot(token='_ВАШ_ТОКЕН_')
name = None  # переменная, в которой будут храниться значения с названием аудиофайла
artist = None  # переменная, в которой будут храниться значения с названием артиста
old_name = None

def main():
    @bot.message_handler(commands=['start'])  # декоратор, который получает значение ввиде команды \start
    def start(message):
        markup = types.ReplyKeyboardMarkup()  # создаю обьект на основе класса
        btn1 = types.KeyboardButton('/listen')  # основные кнопки бота
        btn2 = types.KeyboardButton('/add')
        btn3 = types.KeyboardButton('/view_all')
        btn4 = types.KeyboardButton('/options')
        markup.row(btn1, btn2, btn3, btn4)
        bot.send_message(message.chat.id, f'Привет, {message.from_user.first_name}, напиши /help', reply_markup=markup)
        # приветсвенное сообщение
    @bot.message_handler(commands=['help'])  # Создал декоратор, который принимает в себя команду /help
    def help_info(message):
        markup = types.ReplyKeyboardMarkup()
        btn1 = types.KeyboardButton('/listen')  # Это основные кнопки бота
        btn2 = types.KeyboardButton('/add')
        btn3 = types.KeyboardButton('/view_all')
        btn4 = types.KeyboardButton('/options')
        markup.row(btn1, btn2, btn3, btn4)
        file = open('help.txt', 'r') 
        # Создаю переменную file и присваиваю ей файлиовый обьект с режимом доступа только для чтения
        k = file.read()  # переменной k передаем метод считывания данных из файла
        bot.send_message(message.chat.id, f'{k}', reply_markup=markup)  
        # бот отправляет сообщение с текстом и выводит кнопки на экран 
        file.close()  # закрываю файл
       @bot.message_handler(['add'])
    def song_name(message):
        conn = sqlite3.connect('music.sql')  # создаю обьект на основе класса sqlite3, т.е. создаю БД
        cur = conn.cursor()  # Создаю курсор для работы с БД

        cur.execute('CREATE TABLE IF NOT EXISTS loadings '
                    '(id int auto_increment primary key, name varchar(50), artist varchar(50))')
        # создаю таблицу с атрибутами name, artist и первичным ключом id
        conn.commit()  # обращаюсь к БД с нашим запросом
        cur.close()  # закрываю курсор
        conn.close()  # закрываю БД

        bot.send_message(message.chat.id, 'Введи название песни')
        bot.register_next_step_handler(message, naming)  # перенаправляю бота выполнить следующую функцию

    def naming(message):  # функция для 'регистрации' имени трека
        global name  # обьявляю переменную name как глобальную

        bot.send_message(message.chat.id, 'отправь аудио')
        name = message.text  # бот регистрирует название с сообщения пользователя

        bot.register_next_step_handler(message, save_audio)

    @bot.message_handler(content_types=['audio'])  # декоратор, который приниимает как значение аудиофайл
    def save_audio(message):  # функция сохранения аудиофайла в БД
        try:
            global name  # обьявляю переменную name, artist как глобальную
            global artist

            artist = message.audio.performer
            # обращаюсь к методу обьекта message, в котором хранится инф. о исполнителе

            audio_file_id = message.audio.file_id  # переменная, в которой храниться id сообщения
            audio_file = bot.get_file(audio_file_id)  # переменная, которая представляет собой полученный файл
            audio_file_path = audio_file.file_path

            audio_name = f"/ВАШ_ПУТЬ_К_ПАПКЕ_/MUSIC/{name}.mp3"

            audio_data = bot.download_file(audio_file_path)

            with open(audio_name, 'wb') as file:  # Открытие файла для записи в двоичном режиме
                file.write(audio_data)  # Запись данных аудиофайла в файл

            conn = sqlite3.connect('music.sql')
            cur = conn.cursor()

            cur.execute('INSERT INTO loadings (name, artist) VALUES ("%s", "%s")' % (name, artist))
            # Выполнение SQL-запроса для добавления информации об аудиофайле в БД
            conn.commit()
            cur.close()
            conn.close()

            markup = types.InlineKeyboardMarkup()
            bot.delete_message(message.chat.id, message.message_id)  # Удаление сообщения с аудиофайлом
            markup.add(types.InlineKeyboardButton('Весь плейлист', callback_data='loadings'))
            # Добавление кнопки к клавиатуре и вызываю функцию loadings
            bot.send_message(message.chat.id, 'Трек добавлен', reply_markup=markup)
        except AttributeError:  # обработка исключения, если сообщение не является аудиофайлом
            bot.send_message(message.chat.id, 'Друг, похоже ты отправил мне не аудиофайл. Отправь мне аудио, пожалуйста')

    @bot.callback_query_handler(func=lambda callback: True)  # Декоратор для обработки callback-запросов
    def callback_message(callback):  # Функция, которая будет вызываться при callback-запросах

        conn = sqlite3.connect('music.sql')
        cur = conn.cursor()

        cur.execute('SELECT * FROM loadings')
        loadings = cur.fetchall()

        info = ''   # Переменная для хранения информации о треках
        for i in loadings:
            info += f'Название трека:{i[1]}, Исполнитель: {i[2]}\n'  # Формирование строки информации о треке
        cur.close()
        conn.close()
        bot.send_message(callback.message.chat.id, info)  # Отправка сообщения с информацией о треках в чат
    @bot.message_handler(commands=['view_all'])
    def view_all(message):  # функция для просморта всего плейлиста
        conn = sqlite3.connect('music.sql')
        cur = conn.cursor()

        cur.execute('SELECT * FROM loadings')
        loadings = cur.fetchall()

        info = ''
        for i in loadings:
            info += f'Название трека:{i[1]}, Исполнитель: {i[2]}\n'
        cur.close()
        conn.close()
        bot.send_message(message.chat.id, f'ВАШ ПЛЕЙЛИСТ: \n{info}')
     @bot.message_handler(commands=['listen'])
    def listen(message):
        try:
            conn = sqlite3.connect('music.sql')  # обращаюсь к БД
            cur = conn.cursor()

            cur.execute('SELECT * FROM loadings')
            loadings = cur.fetchall()

            info = ''
            for i in loadings:
                info += f'Название трека:{i[1]}, Исполнитель: {i[2]}\n'
            cur.close()
            conn.close()
            bot.send_message(message.chat.id, f'ВАШ ПЛЕЙЛИСТ: \n{info}')  # иформация о плейлисте
            bot.register_next_step_handler(message, music_player)  # перенаправляю бота на выполнение следующей функци

        except sqlite3.OperationalError:  # обработка оишбок, если пользователь еще не загрузил трек
            bot.send_message(message.chat.id, 'Ты пока не загрузил песни')

    def music_player(message):
        conn = sqlite3.connect('music.sql')
        cur = conn.cursor()

        cur.execute('SELECT * FROM loadings')  # Выполнение SQL-запроса для выборки всех записей из таблицы loadings
        loadings = cur.fetchall()  # Получение результатов запроса
        checkout = message.text  # Получение текста сообщения
        for i in loadings:
            if checkout in f'{i[1]}':  # Проверяю, содержится ли текст сообщения в названии трека
                file = open(f'/ПУТЬ_К_ПАПКЕ_/MUSIC/{checkout}.mp3', 'rb')  
                # Открываю файл трека в двоичном режиме
                bot.send_audio(message.chat.id, file, title=f'{checkout}')  
                # Отправляю аудиофайла в чат с указанием заголовка
                file.close()
            else:
                pass
        @bot.message_handler(commands=['options'])  # декоратор для обработки команды /options
    def song_name(message):
        markup = types.ReplyKeyboardMarkup()
        btn1 = types.KeyboardButton('/delete')
        btn2 = types.KeyboardButton('/edit')
        markup.row(btn1, btn2)
        bot.send_message(message.chat.id, 'Что вы хотите сделать ?', reply_markup=markup)
    @bot.message_handler(commands=['delete'])
    def preparation_for_delete(message):
        bot.register_next_step_handler(message, delete)  # Регистрирую следующего обработчика для данного сообщения
        bot.send_message(message.chat.id, 'Введи название песни')
        conn = sqlite3.connect('music.sql')
        cur = conn.cursor()

        cur.execute('SELECT * FROM loadings')  # Выполняю SQL-запроса для выборки всех записей из таблицы loadings
        loadings = cur.fetchall()
        info = ''
        for i in loadings:
            info += f'Название трека: {i[1]}, Исполнитель: {i[2]}\n'  # Формирую строки с информацией о треках
        bot.send_message(message.chat.id, info)   # Отправляю информации о всех треках в чат

    def delete(message):

        markup = types.ReplyKeyboardMarkup()
        btn1 = types.KeyboardButton('/listen')
        btn2 = types.KeyboardButton('/add')
        btn3 = types.KeyboardButton('/view_all')
        btn4 = types.KeyboardButton('/options')
        markup.row(btn1, btn2, btn3, btn4)

        checkout = message.text  # Получаю названия трека для удаления
        conn = sqlite3.connect('music.sql')
        cur = conn.cursor()

        cur.execute('DELETE FROM loadings WHERE name = ?', (checkout,))
        # Удаляю записи с указанным названием из базы данных
        conn.commit()  # Сохраняю изменений

        file_path = os.path.join(f'/ПУТЬ_К_ПАПКЕ_/MUSIC/{checkout}.mp3')  # Путь к файлу трека
        try:
            os.remove(file_path)   # Попытка удалить файл трека
            print(f"Файл {checkout} успешно удален с сервера")
            bot.send_message(message.chat.id, 'Запись успешно удалена')

        except OSError as e:  # обрабатываю ошибку, если трека для удаления нет
            print(f"Ошибка удаления файла на сервере: {e}")
            bot.send_message(message.chat.id, 'Такого трека нет в твоём плейлисте, друг')

        cur.execute('SELECT * FROM loadings')
        loadings = cur.fetchall()
        info = ''
        for i in loadings:
            info += f'Название трека: {i[1]}, Исполнитель: {i[2]}\n'
        cur.close()
        conn.close()

        bot.send_message(message.chat.id, info, reply_markup=markup)
    @bot.message_handler(commands=['edit'])
    def find_old_name(message):

        bot.send_message(message.chat.id, 'Введи старое название песни')  # Запрос на ввод старого названия песни
        conn = sqlite3.connect('music.sql')
        cur = conn.cursor()

        cur.execute('SELECT * FROM loadings')
        loadings = cur.fetchall()
        info = ''
        for i in loadings:
            info += f'Название трека: {i[1]}, Исполнитель: {i[2]}\n'
        bot.send_message(message.chat.id, info)
        bot.register_next_step_handler(message, new_name)  # Регистрируем следующего обработчика для нового названия

    def new_name(message):
        global old_name   # Объявляем глобальную переменную для старого названия

        old_name = message.text   # Получаем старое название песни
        bot.send_message(message.chat.id, 'Введи новое название песни')  # Запрос на ввод нового названия песни
        bot.register_next_step_handler(message, edit)  # Регистрация следующего обработчика для изменения

    def edit(message):
        global old_name  # Объявление глобальной переменной для старого названия

        markup = types.ReplyKeyboardMarkup()
        btn1 = types.KeyboardButton('/listen')
        btn2 = types.KeyboardButton('/add')
        btn3 = types.KeyboardButton('/view_all')
        btn4 = types.KeyboardButton('/options')
        markup.row(btn1, btn2, btn3, btn4)

        checkout = old_name  # Присваиваем переменной старое название
        the_new_name = message.text   # Полученаем новое название песни

        conn = sqlite3.connect('music.sql')
        cur = conn.cursor()

        cur.execute("UPDATE loadings SET name = ? WHERE name = ?", (the_new_name, checkout))  # Обновление названия в БД
        conn.commit()

        file_path = f'/ПУТЬ_К_ПАПКЕ_/MUSIC/{checkout}.mp3'   # Путь к старому файлу
        new_file_path = f'/ПУТЬ_К_ПАПКЕ_/MUSIC/{the_new_name}.mp3'  # Путь к новому файлу

        try:
            os.rename(file_path, new_file_path)  # Переименование файла на сервере
            print(f"Файл {checkout} успешно обновлен на сервере")
            bot.send_message(message.chat.id, 'Запись успешно обновлена')
        except OSError as e:  # обработка ошибок, если трека для редактирования нет
            print(f"Ошибка обновления файла на сервере: {e}")
            bot.send_message(message.chat.id, 'Похоже такого трека нету в твоём плейлисте, друг')

        cur.execute('SELECT * FROM loadings')
        loadings = cur.fetchall()
        info = ''
        for i in loadings:
            info += f'Название трека: {i[1]}, Исполнитель: {i[2]}\n'

        cur.close()
        conn.close()

        bot.send_message(message.chat.id, info, reply_markup=markup)
        @bot.message_handler()  # функция для обработки обычного текста
    def txt_random_validation(message):
        check = message.text
        if check != '/add' or '/start' or '/listen':  
            file = open('validation.txt', 'r')  # создаю файловый обьект для чтения
            k = file.read()
            bot.send_message(message.chat.id, f'{k}')  # отправляю информацию
            file.close()  # закрываю файл

if __name__ == '__main__':
    main()
    bot.polling()  # обращаюсь к методу обьекта bot, чтобы бот мог принимать сообщения и отправлять их