Перейти к содержимому

Как подключить sqlite к python telegram bot

  • автор:

#4 – SQLite3. Подключение к базе данных

#4 – SQLite3. Подключение к базе данных

За урок вы выполните подключение базы данных к вашему Телеграм Боту. Вы подключите БД SQLite3, но в будущем по схожему принципу сможете подключать любые другие БД.

Видеоурок

База данных SQLite3 была выбрана в качестве примера по причине ее простоты настройки и использования. В точно таком же формате вы в будущем можете подключиться к любой другой базе данных, что поддерживается языком Python. Это могут быть: MySQL, PostgreSQL, MongoDB и многие другие.

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

В ходе урока был показан общий принцип работы с базами данных. В будущем вы можете использовать любую другую БД на свое усмотрение.

Весь код будет доступен после подписки на проект!

Как вывести определенную запись в sqlite согласно условиям python + Telegram bot

У меня есть телеграм бот. Заранее скажу, что те кто используют моего бота есть в моей базе данных! У меня в боте есть кнопка «Оформить заказ✅» я пытаюсь сделать так, чтобы тот кто нажимал на эту кнопку проверился есть ли он(Его id) в БД и если есть то вывести запись где есть его id (Соответственно у меня кроме id в записи выйдет информация о nickname Имя, Фамилия, телефон и username) Но когда я пытаюсь вывести эту информацию(запись) используя fetchone() то выводится только первая запись по умолчанию и она не реагирует на то, что, кто нажал на кнопку «Оформить заказ✅». А я хотел бы чтобы она выводила запись согласно id человека нажавшего на кнопку «Оформить заказ✅» то есть, если его id есть в БД то вывести запись(id username имя телефон и тп) где есть его id.

@bot.message_handler(content_types=['text']) def handler(message): with sq.connect("bot5.db") as con: cur = con.cursor() chat_id = message.chat.id if message.text == "Оформить заказ✅": exists = cur.execute("SELECT 1 FROM info1 WHERE [chat_id]).fetchone() if exists == True: print("DA") cur.execute(""" SELECT * FROM info1 WHERE chat_id """) data2 = cur.fetchone() print(data2) chat_id = message.chat.id bot.send_message(chat_id, '\n'.join(map(str, data2))) 

Фото с моей базы данных Фото с моей базы данных P.S Смог сделать так, думаю проблема в том что я не могу правильно сделать так чтобы выводилась запись(информация) именно того кто нажал на кнопку «Оформить заказ✅» Несмотря на то что, кто нажимает на эту кнопку выводится только первая запись в базе данных! введите сюда описание изображения

Отслеживать

задан 17 окт 2021 в 14:31

25 7 7 бронзовых знаков

прочитайте sqlite3 для совершенных новичков

17 окт 2021 в 16:41

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Вот оно современное поколение бот-девелоперов. Эх.

chat_id = call.message.chat.id if message.text == "Оформить заказ✅": cur.execute(f'SELECT * FROM info1 WHERE ') exists = cur.fetchall() if exists == True: print(exists)

Отслеживать

ответ дан 17 окт 2021 в 16:37

316 1 1 серебряный знак 7 7 бронзовых знаков

Прокачиваем телеграм-бота: пишем полноценный бэкенд

Сегодня мы продолжим этот проект и добавим возможности нашему бэкенду для телеграм-бота. Если хотите разобраться в теме телеграм-ботов с самого начала, почитайте эти статьи:

Логика проекта

Мы сделаем простого бота для приёма отчётов — что сделано за день или над чем идёт работа:

  1. Сообщение может написать боту кто угодно. Бот запомнит, кто ему написал.
  2. Бот будет работать только с текстовыми сообщениями. Стикеры и файлы не подойдут.
  3. Чтобы никто не спамил, бот обрезает сообщение до 500 символов и записывает их в свою базу данных.
  4. База данных будет настоящая — SQLite, с которой Python работает без дополнительных настроек.
  5. У бота будут две команды — посмотреть все отчёты за вчера и за сегодня. По этим командам бот присылает отчёты.
  6. Другие команды бот игнорирует, удалить отчёт нельзя, бот помнит всё.

Это простая, но рабочая логика бэкенда — с ним бот уже может приносить пользу и быть рабочим инструментом.

Что понадобится

Для скрипта нам понадобится Python — половина современного бэкенда пишется именно на нём.

Также мы будем использовать базу данных SQLite — она простая, быстрая и работает практически везде. Прочитайте о ней: SQLite — самая простая база данных, которая работает везде

Код обработки команд для бота мы возьмём из наших прошлых статей про Телеграм и адаптируем под новый проект:

Исходный код прошлого проекта

# подключаем модуль для Телеграма import telebot # указываем токен для доступа к боту bot = telebot.TeleBot(123456789:AAAAA12345678abcdef12345678abcdef') # приветственный текст start_txt = 'Привет! Это журнал «Код». \n\nТеперь у бота появился бэкенд.' # обрабатываем старт бота @bot.message_handler(commands=['start']) def start(message): # выводим приветственное сообщение bot.send_message(message.from_user.id, start_txt, parse_mode='Markdown') # запускаем бота if __name__ == '__main__': while True: # в бесконечном цикле постоянно опрашиваем бота — есть ли новые сообщения try: bot.polling(none_stop=True, interval=0) # если возникла ошибка — сообщаем про исключение и продолжаем работу except Exception as e: print('❌❌❌❌❌ Сработало исключение! ❌❌❌❌❌')

Подключаем базу данных

Мы будем хранить все отчёты пользователей в базе данных — это позволит нам хранить почти неограниченное количество отчётов и быстро находить среди них нужные. Для этого сначала подключим библиотеку sqlite3:

# модуль для работы с базой данных
import sqlite3 as sl

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

# подключаемся к файлу с базой данных
con = sl.connect(‘reports.db’)

А вот тут есть тонкий момент: если это наш первый запуск программы, то после подключения скрипт получит пустую базу, без таблиц и внутренней структуры. Если мы попробуем туда что-то записать, то получим ошибку. Чтобы такого не было, сразу сделаем проверку, есть ли в базе нужная нам таблица. Если есть — всё хорошо, продолжаем работу, а если нет — просто создадим её и тоже продолжим работу.

Обратите внимание на структуру таблицы: чтобы каждая запись имела свой уникальный ключ, мы используем для этого комбинацию даты и времени. Дело в том, что время в Python можно получить с точностью до миллисекунды — этого достаточно для того, чтобы у каждого сообщения было своё уникальное время.

Ещё нам нужно хранить дату, чтобы выбирать по ней отчёты за вчера и за сегодня — сделаем это в поле date. В остальные поля будем записывать id и ник пользователя в Телеграме и сам текст сообщения.

# открываем файл with con: # получаем количество таблиц с нужным нам именем data = con.execute("select count(*) from sqlite_master where type='table' and name='reports'") for row in data: # если таких таблиц нет if row[0] == 0: # создаём таблицу для отчётов with con: con.execute(""" CREATE TABLE reports ( datetime VARCHAR(40) PRIMARY KEY, date VARCHAR(20), id VARCHAR(200), name VARCHAR(200), text VARCHAR(500) ); """)

Запоминаем отчёт пользователя

Когда база готова, мы можем принимать и сохранять все сообщения пользователей. Так как нам нужно каждой записи в таблице дать свой уникальный идентификатор, используем для этого комбинацию даты и времени. Для этого сначала подключим стандартные библиотеки:

# модуль работы со временем
from datetime import datetime, timezone, timedelta

Так как мы считаем каждое сообщение пользователя отчётом о работе, мы будем обрабатывать и запоминать каждое текстовое сообщение в чате. При этом мы принудительно обрежем сообщение и оставим только первые 500 символов, чтобы ограничить возможный спам. Как только скрипт получит любой текст, он занесёт его в базу и отправит пользователю сообщение с подтверждением.

# обрабатываем входящий отчёт пользователя @bot.message_handler(content_types=['text']) def func(message): # подключаемся к базе con = sl.connect('reports.db') # подготавливаем запрос sql = 'INSERT INTO reports (datetime, date, id, name, text) values(?, ?, ?, ?, ?)' # получаем дату и время now = datetime.now(timezone.utc) # и просто дату date = now.date() # формируем данные для запроса data = [ (str(now), str(date), str(message.from_user.id), str(message.from_user.username), str(message.text[:500])) ] # добавляем с помощью запроса данные with con: con.executemany(sql, data) # отправляем пользователю сообщение о том, что отчёт принят bot.send_message(message.from_user.id, 'Принято, спасибо!', parse_mode='Markdown')

Проверим, как работает код: отправим боту любое сообщение и посмотрим, получим ли мы что-то в ответ:

Прокачиваем телеграм-бота: пишем полноценный бэкенд

Выводим отчёты за сегодня

В реальном проекте мы бы отдельно прописали ID пользователя, который может запрашивать отчёты, чтобы этой командой мог пользоваться только один человек, например руководитель отдела. Сейчас для наглядности мы сделаем проще: сделаем команду /now доступной для всех. Когда бот её получит, он отправит в ответ все отчёты за сегодня.

Логика поиска и выводов отчёта будет такая:

  1. Подключаемся к базе.
  2. Получаем текущую дату и ищем в базе все записи с этой датой.
  3. Перебираем результаты и формируем из них сообщение с отчётами.
  4. Отправляем общий отчёт пользователю.

При этом нам ещё нужно предусмотреть ситуацию, когда отчётов сегодня не было. Если этого не сделать, скрипт попытается отправить пустое сообщение и выдаст ошибку. В этом случае нам нужно дополнительно проверить, пустая у нас строка с отчётом или нет. Если пустая — записать в неё текст о том, что за сегодня отчётов не было.

# обрабатываем команду /now @bot.message_handler(commands=['now']) def start(message): # подключаемся к базе con = sl.connect('reports.db') # получаем сегодняшнюю дату now = datetime.now(timezone.utc) date = now.date() # пустая строка для будущих отчётов s = '' # работаем с базой with con: # выполняем запрос к базе data = con.execute('SELECT * FROM reports WHERE date = :Date;',) # перебираем все результаты for row in data: # формируем строку в общем отчёте s = s + '*' + row[3] + '*' + ' → ' + row[4] + '\n\n' # если отчётов не было за сегодня if s == '': # формируем новое сообщение s = 'За сегодня ещё нет записей' # отправляем общий отчёт обратно в телеграм bot.send_message(message.from_user.id, s, parse_mode='Markdown')

Перезапускаем скрипт и просим бота показать нам сегодняшние отчёты:

Прокачиваем телеграм-бота: пишем полноценный бэкенд

Выводим вчерашние отчёты

Здесь всё то же самое, кроме даты и текста при отсутствии отчётов. С текстом всё просто, а со вчерашней — не совсем. Дело в том, что если штатными средствами получить текущую дату и просто отнять от неё единицу, то скрипт выдаст ошибку. Всё из-за того, что дата — это не целое число, а отдельный объект, из которого нельзя просто вычитать числа.

Чтобы получить вчерашнюю дату, используют функцию timedelta() — она считает разницу между текущей датой и указанным в ней количеством дней и эту разницу хранит как раз в виде объекта, который можно вычитать из даты.

# обрабатываем команду /yesterday @bot.message_handler(commands=['yesterday']) def start(message): # подключаемся к базе con = sl.connect('reports.db') # получаем вчерашнюю дату yesterday = datetime.today() - timedelta(days=1) y_date = yesterday.date() # пустая строка для будущих отчётов s = '' # работаем с базой with con: # выполняем запрос data = con.execute('SELECT * FROM reports WHERE date = :Date;',) # смотрим на результат for row in data: # если результат пустой — ничего не делаем if row[0] == 0: pass # если вчера были какие-то отчёты else: # добавляем их в общий список отчётов s = s + '*' + row[3] + '*' + ' → ' + row[4] + '\n\n' # если отчётов не было за вчера if s == '': # формируем новое сообщение s = 'За вчерашний день нет записей' # отправляем пользователю это новое сообщение bot.send_message(message.from_user.id, s, parse_mode='Markdown')

Так как мы только начали работать с ботом, вчерашних сообщений в нём ещё нет, поэтому в ответ на эту команду бот выдаст заготовленный текст:

Прокачиваем телеграм-бота: пишем полноценный бэкенд

Результат

Смотрите, что мы сегодня сделали:

  1. Подключили бэкенд в виде скрипта к фронтенду — телеграм-боту.
  2. После этого бот смог обрабатывать наши сообщения и команды — запоминать отчёты и отправлять их, когда нужно.
  3. Мы не трогали фронт, зато все наши изменения в бэкенде приводили к тому, что бот получал новые функции одну за другой.

Так и работает бэкенд: он почти не влияет на интерфейс, зато от него может полностью зависеть логика проекта. Если хотите делать крутой бэкенд и разбираться в этом — приходите в Практикум на курсы бэкенда, там научат всему, что потребуется.

Что нужно доделать в следующий раз

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

  1. Если отчётов за день станет слишком много, возможно, бот не сможет отправить их в одном сообщении или не сможет отправить в принципе. Нужно добавить проверку на максимальное количество символов, и, если что, — делить одно сообщение на несколько.
  2. Код вывода сообщений за вчера и за сегодня — одинаковый за исключением нескольких строк. Нужно вынести общую часть в отдельную функцию, чтобы не плодить спагетти-код.

Попробуйте сделать это сами или дождитесь следующей статьи с продолжением, где мы исправим обе эти проблемы.

Готовый код

# подключаем модуль для Телеграма import telebot # модуль работы со временем from datetime import datetime, timezone, timedelta # модуль для работы с базой данных import sqlite3 as sl # указываем токен для доступа к боту bot = telebot.TeleBot('6285051364:AAGG2iZ77NIeWj0YjqIs791qxPhvcS3Yu0s') # приветственный текст start_txt = 'Привет! Это журнал «Код». \n\nТеперь у бота появился бэкенд.' # подключаемся к файлу с базой данных con = sl.connect('reports.db') # открываем файл with con: # получаем количество таблиц с нужным нам именем data = con.execute("select count(*) from sqlite_master where type='table' and name='reports'") for row in data: # если таких таблиц нет if row[0] == 0: # создаём таблицу для отчётов with con: con.execute(""" CREATE TABLE reports ( datetime VARCHAR(40) PRIMARY KEY, date VARCHAR(20), id VARCHAR(200), name VARCHAR(200), text VARCHAR(500) ); """) # обрабатываем старт бота @bot.message_handler(commands=['start']) def start(message): # выводим приветственное сообщение bot.send_message(message.from_user.id, start_txt, parse_mode='Markdown') # обрабатываем команду /now @bot.message_handler(commands=['now']) def start(message): # подключаемся к базе con = sl.connect('reports.db') # получаем сегодняшнюю дату now = datetime.now(timezone.utc) date = now.date() # пустая строка для будущих отчётов s = '' # работаем с базой with con: # выполняем запрос к базе data = con.execute('SELECT * FROM reports WHERE date = :Date;',) # перебираем все результаты for row in data: # формируем строку в общем отчёте s = s + '*' + row[3] + '*' + ' → ' + row[4] + '\n\n' # если отчётов не было за сегодня if s == '': # формируем новое сообщение s = 'За сегодня ещё нет записей' # отправляем общий отчёт обратно в телеграм bot.send_message(message.from_user.id, s, parse_mode='Markdown') # обрабатываем команду /yesterday @bot.message_handler(commands=['yesterday']) def start(message): # подключаемся к базе con = sl.connect('reports.db') # получаем вчерашнюю дату yesterday = datetime.today() - timedelta(days=1) y_date = yesterday.date() # пустая строка для будущих отчётов s = '' # работаем с базой with con: # выполняем запрос data = con.execute('SELECT * FROM reports WHERE date = :Date;',) # смотрим на результат for row in data: # если результат пустой — ничего не делаем if row[0] == 0: pass # если вчера были какие-то отчёты else: # добавляем их в общий список отчётов s = s + '*' + row[3] + '*' + ' → ' + row[4] + '\n\n' # если отчётов не было за вчера if s == '': # формируем новое сообщение s = 'За вчерашний день нет записей' # отправляем пользователю это новое сообщение bot.send_message(message.from_user.id, s, parse_mode='Markdown') # обрабатываем входящий отчёт пользователя @bot.message_handler(content_types=['text']) def func(message): # подключаемся к базе con = sl.connect('reports.db') # подготавливаем запрос sql = 'INSERT INTO reports (datetime, date, id, name, text) values(?, ?, ?, ?, ?)' # получаем дату и время now = datetime.now(timezone.utc) # и просто дату date = now.date() # формируем данные для запроса data = [ (str(now), str(date), str(message.from_user.id), str(message.from_user.username), str(message.text[:500])) ] # добавляем с помощью запроса данные with con: con.executemany(sql, data) # отправляем пользователю сообщение о том, что отчёт принят bot.send_message(message.from_user.id, 'Принято, спасибо!', parse_mode='Markdown') # запускаем бота if __name__ == '__main__': while True: # в бесконечном цикле постоянно опрашиваем бота — есть ли новые сообщения try: bot.polling(none_stop=True, interval=0) # если возникла ошибка — сообщаем про исключение и продолжаем работу except Exception as e: print('❌❌❌❌❌ Сработало исключение! ❌❌❌❌❌')

Что дальше

Теперь у нас есть полноценный бэкенд для телеграм-бота, который умеет принимать и отправлять отчёты. Но сила бэкенда в том, что его можно обернуть в любой интерфейс, в том числе и в веб-страницу. В следующий раз сделаем именно это: сделаем сайт, на котором будут отображаться все отчёты, которые прислали этому телеграм-боту. Получается, что бэкенд будет один, а фронтенда — два. Магия.

Python Telegram Bot. Как правильно изменить данные в БД Sqlite3?

user = message.from_user.id
sql
val = («balance + 15», user)
c.execute(sql, val)
conn.commit()
При работе в balance он просто записывает значение «balance + 15», вместо прибавления 15 к имеющимся числу

Пробовал делать «небезопасным» методом:

c.execute(«UPDATE main SET balance = balance + 15
WHERE user_id = id_пользователя «)
conn.commit()

В этом случае баланс записывается правильно, но работает только если руками указать id конкретного пользователя

Помогите. люди добрые

  • Вопрос задан более трёх лет назад
  • 798 просмотров

3 комментария

Средний 3 комментария

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *