Почему не получается отправить фото альбомом в библиотеке telebot через file_id и функцию InputMediaPhoto?

Я перепробовал очень много способов, как отправлять альбомы с помощью file_id

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

Если кто-то знает как сделать так, чтобы они записывались в 1 массив и выводились методом send_media_group молю о помощи и прикладываю часть кода снизу.

Правка: таблица содержит данные file_id, по типу

таблица photo

@bot.channel_post_handler(content_types=['photo', 'text']) #хендлер на отправку фотографий
def channelphoto(idphoto):
    file_id = idphoto.photo[-1].file_id #file_id из фотографий
    medcaption = idphoto.caption #нереализованная подпись для альбомов

    data = sqlite3.connect('photo.txt')
    cur = data.cursor()
    cur.execute(" INSERT INTO photo (fileid) VALUES ('%s')" % (file_id)) #запись всех вводимых file_id до начала их использования
    cur.execute("DELETE FROM photo WHERE rowid NOT IN(SELECT MIN(rowid) FROM photo GROUP BY fileid)")
    data.commit()
    cur.close()
    data.close()

    data = sqlite3.connect('photo.txt')
    cur = data.cursor()
    cur.execute('SELECT * FROM photo')  
    photo = cur.fetchall()

    media_album = []
    score = 0
    for el1 in photo:
        if file_id == el1[1]:
            media_album.append(telebot.types.InputMediaPhoto(file_id)) #моя задумка с использованием базы данных
            print(el1[1]) #это я пытался смотреть, что оно выводит и как именно
    
    cur.close()
    data.close()


    data = sqlite3.connect('text.txt')
    cur = data.cursor()
    cur.execute('SELECT * FROM users')  
    users = cur.fetchall()

    info = 0
    for el in users:
        info = el[1]
        bot.send_media_group(info, media_album)#вывод фоток альбомом, который увы не работает. info - переменная со всеми id пользователей

    cur.close()
    data.close()

Ответы (1 шт):

Автор решения: krabnerab

Когда ты получаешь сообщение с несколькими фото/видео, у этого сообщения есть media_group_id, это идентификатор для всей группы

В этом коде ты сохраняешь file_id и при попытке собрать альбом ты сравниваешь file_id самим с собой и получаешь просто массив одного элемента.

Тебе нужно сохранять media_group_idи file_id в связке и делать что-то типа

cur.execute('SELECT file_id FROM photos WHERE media_group_id = ?', (media_group_id,))

таблица albums

CREATE TABLE IF NOT EXISTS albums (
    media_group_id TEXT PRIMARY KEY,
    caption TEXT,
    created_at REAL
)

таблица photos

CREATE TABLE IF NOT EXISTS photos (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    media_group_id TEXT,
    file_id TEXT,
    FOREIGN KEY(media_group_id) REFERENCES albums(media_group_id)
);
#функция для очистки старых альбомов
def cleanup_old_albums():
    while True:
        time.sleep(60)  #раз в минуту
        conn = sqlite3.connect('albums.db')
        cur = conn.cursor()
        now = time.time()
        cur.execute("DELETE FROM albums WHERE created_at < ?", (now - 10,))  #удаляем старше 10 сек
        conn.commit()
        conn.close()

#запускаем фоновую очистку
threading.Thread(target=cleanup_old_albums, daemon=True).start()

@bot.channel_post_handler(content_types=['photo'])
def handle_channel_post(message):
    file_id = message.photo[-1].file_id
    caption = message.caption if message.caption else None
    media_group_id = getattr(message, 'media_group_id', None)

    conn = sqlite3.connect('albums.db')
    cur = conn.cursor()

    if media_group_id:
        now = time.time()

        cur.execute('''
            INSERT OR IGNORE INTO albums (media_group_id, caption, created_at)
            VALUES (?, ?, ?)
        ''', (media_group_id, caption, now))

        cur.execute('''
            INSERT INTO photos (media_group_id, file_id)
            VALUES (?, ?)
        ''', (media_group_id, file_id))

        conn.commit()
        conn.close()

        #задержка нужна потому что в там какие-то интервалы с отправкой альбома, не сильно углублялся, но по идее этого должно хватить, тк максимум 10 фотографий в альбоме
        threading.Timer(1.2, send_album_if_ready, args=(media_group_id,)).start()

    else:
        #это если одно фото
        conn.close()
        send_album_to_users([file_id], caption)


def send_album_if_ready(media_group_id):
    conn = sqlite3.connect('albums.db')
    cur = conn.cursor()

    cur.execute('SELECT file_id FROM photos WHERE media_group_id = ?', (media_group_id,))
    photos = cur.fetchall()

    cur.execute('SELECT caption FROM albums WHERE media_group_id = ?', (media_group_id,))
    row = cur.fetchone()
    caption = row[0] if row else None

    conn.close()

    if photos:
        file_ids = [p[0] for p in photos]
        send_album_to_users(file_ids, caption)

        #удаляем альбом из бд после отправки
        conn = sqlite3.connect('albums.db')
        cur = conn.cursor()
        cur.execute('DELETE FROM albums WHERE media_group_id = ?', (media_group_id,))
        conn.commit()
        conn.close()


def send_album_to_users(file_ids, caption=None):
    if not file_ids:
        return

    #формируем медиа-группу
    media = []
    for i, fid in enumerate(file_ids):
        if i == 0 and caption:
            media.append(telebot.types.InputMediaPhoto(fid, caption=caption))
        else:
            media.append(telebot.types.InputMediaPhoto(fid))

    #получаем пользователей из бд
    try:
        conn_users = sqlite3.connect('text.txt')
        cur_users = conn_users.cursor()
        cur_users.execute('SELECT user_id FROM users')
        users = cur_users.fetchall()
        conn_users.close()

        for (user_id,) in users:
            try:
                bot.send_media_group(user_id, media)
            except Exception as e:
                print(f"Ошибка отправки альбому {user_id}: {e}")
    except Exception as e:
        print(f"Ошибка при получении пользователей: {e}")
→ Ссылка