added voice chat

This commit is contained in:
KerradKerridi
2022-08-28 18:53:46 +03:00
parent bf99afa89b
commit 6da8d8211c
2 changed files with 268 additions and 78 deletions

140
db.py Normal file
View File

@@ -0,0 +1,140 @@
import sqlite3
import configparser
import os
import sys
config_path = os.path.join(sys.path[0], 'settings.ini')
config = configparser.ConfigParser()
config.read(config_path)
LOGS = config.getboolean('Settings', 'logs')
IMPORTANT_LOGS = config.get('Telegram', 'important_logs')
class BotDB:
def __init__(self, db_file):
self.conn = sqlite3.connect(db_file, check_same_thread=False)
self.cursor = self.conn.cursor()
def get_message_from_db(self, type: str, username):
"""Функция для запроса к базе данных и получения сообщений для бота. В аргументы передаются:
type - тип получаемой обратной связи, строковое значение, сохраненное в БД
username - имя пользователя
"""
# Подключаемся к базе
try:
cursor = self.conn.cursor()
cursor.execute(f"SELECT * FROM messages WHERE type=?", (type,))
# Забираем данные из таблицы, преобразуем в строку, заменяем поле username на имя пользователя,
# и вместо амберсанда подставляем перенос строки
if type == 'connect_with_admin' or type == 'del_message' or type == 'suggest_news' or type == 'start_message':
response_from_database = str(cursor.fetchone()[1]).replace('username', username).replace('&', '\n')
else:
response_from_database = str(cursor.fetchone()[1]).replace('&', '\n')
return response_from_database
except sqlite3.Error as error:
print(error)
def get_error_message_from_db(self, id: int):
"""Функция для запроса к базе данных и получения сообщений ошибки. В аргументы передаются:
id - идентификатор ошибки
"""
# Подключаемся к базе
try:
cursor = self.conn.cursor()
cursor.execute(f"SELECT * FROM error_messages WHERE id=?", (id,))
response_from_database = str(cursor.fetchone()[1])
return response_from_database
except sqlite3.Error as error:
print(error)
def add_new_user_in_db(self, user_id, first_name, full_name, username, is_bot, language_code, date_added, date_changed):
"""Добавляем юзера в базу"""
try:
self.cursor.execute("INSERT INTO 'our_users' ('user_id', 'first_name', 'full_name', 'username', 'is_bot', "
"'language_code', 'date_added', 'date_changed') VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
(user_id, first_name, full_name,
username,is_bot,language_code,date_added,date_changed))
return self.conn.commit()
except sqlite3.Error as error:
print(error)
def user_exists(self, user_id):
"""Проверяем, есть ли юзер в базе"""
try:
result = self.cursor.execute("SELECT `id` FROM `our_users` WHERE `user_id` = ?", (user_id,))
return bool(len(result.fetchall()))
except sqlite3.Error as error:
print(error)
def get_user_id(self, user_id):
"""Достаем id юзера в базе по его user_id"""
try:
result = self.cursor.execute("SELECT `id` FROM `our_users` WHERE `user_id` = ?", (user_id,))
return result.fetchone()[0]
except sqlite3.Error as error:
print(error)
def get_user_first_name(self, user_id):
try:
result = self.cursor.execute("SELECT `first_name` FROM `our_users` WHERE `user_id` = ?", (user_id,))
return result.fetchone()[0]
except sqlite3.Error as error:
print(error)
def change_name(self, user_id):
#TODO: реализовать функцию изменения имени пользователя по которому к нему обращается бот. ОБновляем поля first_name, date_changed
#result = self.cursor.execute("UPDATE 'our_users' SET (?) WHERE user_id = (?)", (new_user_name), )
pass
def add_audio_record(self, file_name, author_id, date_added, listen_count, file_id):
"""Добавляет информацию о войсе юзера в БД"""
try:
result = self.cursor.execute("INSERT INTO `audio_message_reference` (file_name, author_id, date_added, listen_count, file_id) VALUES (?, ?, ?, ?, ?)", (file_name, author_id, date_added, listen_count, file_id))
return self.conn.commit()
except sqlite3.Error as error:
print(error)
def get_last_user_audio_record(self, user_id):
"""Получает данные о количестве записей пользователя"""
try:
result = self.cursor.execute("SELECT `file_id` FROM `audio_message_reference` WHERE `author_id` = ?", (user_id,))
return bool(len(result.fetchall()))
except sqlite3.Error as error:
print(error)
def get_id_for_audio_record(self, user_id):
"""Получает ID аудио сообщения пользователя"""
try:
result = self.cursor.execute("SELECT `file_id` FROM `audio_message_reference` WHERE `author_id` = ? ORDER BY date_added DESC LIMIT 1",
(user_id,))
return result.fetchone()[0]
except sqlite3.Error as error:
print(error)
def get_path_for_audio_record(self, user_id):
"""Получает данные о названии файла"""
try:
result = self.cursor.execute("SELECT `file_name` FROM `audio_message_reference` WHERE `author_id` = ? ORDER BY date_added DESC LIMIT 1", (user_id,))
return result.fetchone()[0]
except sqlite3.Error as error:
print(error)
def get_random_audio(self):
"""Получает данные о войсе юзера из БД"""
try:
result = self.cursor.execute(
"SELECT `file_name` FROM `audio_message_reference` WHERE `author_id` = ? ORDER BY date_added DESC LIMIT 1",
(user_id,))
return result.fetchone()[0]
except sqlite3.Error as error:
print(error)
def close(self):
"""Закрываем соединение с БД"""
self.conn.close()

206
main.py
View File

@@ -1,12 +1,14 @@
import configparser
import itertools
import os
import sys
import sqlite3
from pathlib import Path
from time import sleep
from db import BotDB
import telebot
import random
from datetime import datetime
import time
from telebot import types
from telebot.apihelper import ApiTelegramException
@@ -18,6 +20,7 @@ config.read(config_path)
BOT_TOKEN = config.get('Telegram', 'BOT_TOKEN')
GROUP_FOR_POST = config.get('Telegram', 'group_for_posts')
GROUP_FOR_MESSAGE = config.get('Telegram', 'group_for_message')
GROUP_FOR_AUDIO = config.get('Telegram', 'group_for_audio')
MAIN_PUBLIC = config.get('Telegram', 'main_public')
GROUP_FOR_LOGS = config.get('Telegram', 'group_for_logs')
IMPORTANT_LOGS = config.get('Telegram', 'important_logs')
@@ -25,50 +28,9 @@ PREVIEW_LINK = config.getboolean('Telegram', 'PREVIEW_LINK')
#SETTINGS
LOGS = config.getboolean('Settings', 'logs')
#Инициализируем бота
#Инициализируем бота и базку
bot = telebot.TeleBot(BOT_TOKEN, parse_mode=None)
def select_message_from_db(type: str, username):
"""Функция для запроса к базе данных и получения сообщений для бота. В аргументы передаются:
type - тип получаемой обратной связи, строковое значение, сохраненное в БД
username - имя пользователя
"""
# Подключаемся к базе
conn = sqlite3.connect('tg-bot-database', check_same_thread=False)
try:
cursor = conn.cursor()
cursor.execute(f"SELECT * FROM messages WHERE type=?", (type,))
#Забираем данные из таблицы, преобразуем в строку, заменяем поле username на имя пользователя,
#и вместо амберсанда подставляем перенос строки
response_from_database = str(cursor.fetchone()[1]).replace('username', username).replace('&', '\n')
return response_from_database
except sqlite3.Error as error:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS,
text=f'Ошибка при работе с SQLite, {error}')
finally:
if conn:
conn.close()
def error_message_from_db(id: int):
"""Функция для запроса к базе данных и получения сообщений ошибки. В аргументы передаются:
id - идентификатор ошибки
"""
# Подключаемся к базе
conn = sqlite3.connect('tg-bot-database', check_same_thread=False)
try:
cursor = conn.cursor()
cursor.execute(f"SELECT * FROM error_messages WHERE id=?", (id,))
response_from_database = str(cursor.fetchone()[1])
return response_from_database
except sqlite3.Error as error:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS,
text=f'Ошибка при работе с SQLite, {error}')
finally:
if conn:
conn.close()
BotDB = BotDB('tg-bot-database')
def telegram_bot():
@bot.message_handler(commands=['start'])
@@ -88,26 +50,39 @@ def telegram_bot():
sleep(0.3)
except:
if LOGS:
bot.send_message(IMPORTANT_LOGS, error_message_from_db(7))
bot.send_message(IMPORTANT_LOGS, BotDB.get_error_message_from_db(7))
markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
item1 = types.KeyboardButton("Предложить свой пост")
item2 = types.KeyboardButton("Связаться с админами")
item3 = types.KeyboardButton("Удалить пост")
item4 = types.KeyboardButton("Войти в режим стендапа")
markup.add(item1, item2, item3)
markup.add(item1, item2, item3, item4)
try:
username = message.from_user.first_name
hello_message = select_message_from_db('start_message', username)
user_id = message.from_user.id
first_name = message.from_user.first_name
full_name = message.from_user.full_name
is_bot = message.from_user.is_bot
username = message.from_user.username
language_code = message.from_user.language_code
time_UTC = int(time.time())
date_added = datetime.fromtimestamp(time_UTC)
date_changed = datetime.fromtimestamp(time_UTC)
if BotDB.user_exists(user_id):
pass
else:
BotDB.add_new_user_in_db(user_id, first_name, full_name, username, is_bot, language_code, date_added, date_changed)
hello_message = BotDB.get_message_from_db('start_message', first_name)
bot.send_message(message.chat.id, hello_message, parse_mode='html', reply_markup=markup, disable_web_page_preview=not PREVIEW_LINK)
except:
if LOGS:
bot.send_message(IMPORTANT_LOGS, error_message_from_db(8))
bot.send_message(IMPORTANT_LOGS, BotDB.get_error_message_from_db(8))
bot.register_next_step_handler(message, go_send_messages)
@bot.message_handler(commands=['end_command'])
def after_post(message):
markup = types.ReplyKeyboardMarkup(row_width=1)
markup = types.ReplyKeyboardMarkup(row_width=2)
item1 = types.KeyboardButton("Предложить свой пост")
item2 = types.KeyboardButton("Связаться с админами")
item3 = types.KeyboardButton("Удалить пост")
@@ -124,16 +99,16 @@ def telegram_bot():
if message.text == 'Предложить свой пост':
try:
markup = types.ReplyKeyboardRemove()
username = message.from_user.first_name
suggest_news = select_message_from_db('suggest_news', username)
first_name = message.from_user.first_name
suggest_news = BotDB.get_message_from_db('suggest_news', first_name)
bot.send_message(message.chat.id, suggest_news, parse_mode='html')
sleep(0.3)
username = message.from_user.first_name
suggest_news_2 = select_message_from_db('suggest_news_2', username)
first_name = message.from_user.first_name
suggest_news_2 = BotDB.get_message_from_db('suggest_news_2', first_name)
msg = bot.send_message(message.chat.id, suggest_news_2,parse_mode='html', reply_markup=markup)
except:
if LOGS:
bot.send_message(IMPORTANT_LOGS, error_message_from_db(10))
bot.send_message(IMPORTANT_LOGS, BotDB.get_error_message_from_db(10))
#logging
if LOGS:
bot.forward_message(chat_id=GROUP_FOR_LOGS,
@@ -142,8 +117,8 @@ def telegram_bot():
bot.register_next_step_handler(msg, resend_message_in_group_for_post)
elif message.text == "Связаться с админами":
username = message.from_user.first_name
connect_with_admin = select_message_from_db('connect_with_admin', username)
first_name = message.from_user.first_name
connect_with_admin = BotDB.get_message_from_db('connect_with_admin', first_name)
msg = bot.send_message(message.chat.id, connect_with_admin, parse_mode="html")
#logging
if LOGS:
@@ -152,10 +127,26 @@ def telegram_bot():
message_id=message.message_id)
bot.register_next_step_handler(msg, resend_message_in_group_for_message)
elif message.text == "Войти в режим стендапа":
markup = types.ReplyKeyboardMarkup(row_width=1)
item1 = types.KeyboardButton("Высказаться")
item2 = types.KeyboardButton("Послушать")
markup.add(item1, item2)
first_name = message.from_user.first_name
message_for_standup = BotDB.get_message_from_db('message_for_standup', first_name)
msg = bot.send_message(message.chat.id, message_for_standup, parse_mode='html', reply_markup=markup, disable_web_page_preview=not PREVIEW_LINK)
#logging
if LOGS:
bot.forward_message(chat_id=GROUP_FOR_LOGS,
from_chat_id=message.chat_id,
message_id=message.message_id)
bot.register_next_step_handler(msg, standup)
elif message.text == "Удалить пост":
#TODO: требует автоматизации. На входе говорим пришли мне пост, на выходе получаем идентификатор поста, удаляем из ТГ. Насчет удаления из ВК надо подумать
username = message.from_user.first_name
del_message = select_message_from_db('del_message', username)
first_name = message.from_user.first_name
del_message = BotDB.get_message_from_db('del_message', first_name)
msg = bot.send_message(message.chat.id, del_message, parse_mode="html")
#logging
if LOGS:
@@ -172,39 +163,100 @@ def telegram_bot():
bot.send_sticker(message.chat.id, random_stick_bye)
except ApiTelegramException:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS, text=error_message_from_db(11))
bot.send_message(chat_id=IMPORTANT_LOGS, text=BotDB.get_error_message_from_db(11))
markup = types.ReplyKeyboardRemove()
try:
username = message.from_user.first_name
bye_message = select_message_from_db('bye_message', username)
first_name = message.from_user.first_name
bye_message = BotDB.get_message_from_db('bye_message', first_name)
bot.send_message(message.chat.id, bye_message,
parse_mode='html', reply_markup=markup, disable_web_page_preview=not PREVIEW_LINK)
except:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS, text=error_message_from_db(6))
bot.send_message(chat_id=IMPORTANT_LOGS, text=BotDB.get_error_message_from_db(6))
if LOGS:
#logging
bot.forward_message(chat_id=GROUP_FOR_LOGS,
from_chat_id=message.chat.id,
message_id=message.message_id)
else:
try:
username = message.from_user.first_name
user_error = select_message_from_db('user_error', username)
first_name = message.from_user.first_name
user_error = BotDB.get_message_from_db('user_error', first_name)
bot.send_message(message.chat.id, user_error, parse_mode='html', disable_web_page_preview=not PREVIEW_LINK)
except:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS, text=error_message_from_db(9))
bot.send_message(chat_id=IMPORTANT_LOGS, text=BotDB.get_error_message_from_db(9))
#logging
if LOGS:
bot.forward_message(chat_id=GROUP_FOR_LOGS,
from_chat_id=message.chat.id,
message_id=message.message_id)
after_post(message=message)
menu_standup(message=message)
def standup(message):
try:
if message.text == 'Высказаться' or message.text == 'Высказаться еще':
markup = types.ReplyKeyboardRemove()
msg = bot.send_message(chat_id=message.chat.id, text='Пришли мне свое голосовое сообщение', reply_markup=markup)
bot.register_next_step_handler(msg, save_voice_message)
elif message.text == 'Послушать':
#msg = bot.send_voice(chat_id=message.chat.id, open('voice_users/new_file.ogg', 'rb'))
msg = bot.send_message(chat_id=message.chat.id, text='Погоди, так еще не умею')
bot.register_next_step_handler(msg, menu_standup)
elif message.text == 'Вернуться в меню':
after_post(message=message)
except:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS, text=BotDB.get_error_message_from_db(4))
def menu_standup(message):
markup = types.ReplyKeyboardMarkup(row_width=2)
item1 = types.KeyboardButton("Высказаться еще")
item2 = types.KeyboardButton("Послушать")
item3 = types.KeyboardButton("Вернуться в меню")
markup.add(item1, item2, item3)
msg = bot.send_message(chat_id=message.chat.id,
text='Держи клавиатуру и выбери нужную кнопку внизу экрана!',
parse_mode='html', reply_markup=markup, disable_web_page_preview=not PREVIEW_LINK)
bot.register_next_step_handler(msg, standup)
def save_voice_message(message):
if message.content_type == 'voice':
#ret_msg = bot.send_voice(message.chat.id, open('voice_users/new_file.ogg', 'rb')) message_id, author_id, added_date
file_name = ''
file_id = 1
#Проверяем что запись о файле есть в базе данных
is_having_audio_from_user = BotDB.get_last_user_audio_record(user_id=message.from_user.id)
if is_having_audio_from_user is False:
#Если нет, то генерируем имя файла
file_name = f'message_from_{message.from_user.id}_number_{file_id}'
else:
#Иначе берем последнюю запись из БД, добавляем к ней 1, и создаем новую запись
file_name = BotDB.get_path_for_audio_record(user_id=message.from_user.id)
file_id = BotDB.get_id_for_audio_record(message.from_user.id) + 1
path = Path(f'voice_users/{file_name}.ogg')
if path.exists():
file_name = f'message_from_{message.from_user.id}_number_{file_id}'
else:
pass
#Собираем инфо о сообщении
author_id = message.from_user.id
time_UTC = int(time.time())
date_added = datetime.fromtimestamp(time_UTC)
#Сохраняем в базку
BotDB.add_audio_record(file_name, author_id, date_added, 0, file_id)
#Сохраняем файл на сервер
file_info = bot.get_file(message.voice.file_id)
downloaded_file = bot.download_file(file_info.file_path)
with open(f'voice_users/{file_name}.ogg', 'wb') as new_file:
new_file.write(downloaded_file)
bot.send_message(chat_id=message.chat.id, text='Окей, сохранил!')
menu_standup(message=message)
else:
msg = bot.send_message(chat_id=message.chat.id, text='Я тебя не понимаю, запиши голосовое')
bot.register_next_step_handler(msg, save_voice_message)
def resend_message_in_group_for_post(message):
markup = types.InlineKeyboardMarkup(row_width=1)
@@ -252,11 +304,11 @@ def telegram_bot():
except:
if LOGS:
username = message.from_user.first_name
error_message = str(error_message_from_db(5)).replace('username', username)
error_message = str(BotDB.get_error_message_from_db(5)).replace('username', username)
bot.send_message(chat_id=IMPORTANT_LOGS, text=error_message)
username = message.from_user.first_name
success_send_message = select_message_from_db('success_send_message', username)
success_send_message = BotDB.get_message_from_db('success_send_message', username)
bot.send_message(message.chat.id, success_send_message, parse_mode='html', disable_web_page_preview=not PREVIEW_LINK)
after_post(message=message)
@@ -268,11 +320,11 @@ def telegram_bot():
message_id=message.message_id
)
username = message.from_user.first_name
question = select_message_from_db('question', username)
question = BotDB.get_message_from_db('question', username)
bot.send_message(message.chat.id, question, parse_mode='html', disable_web_page_preview=not PREVIEW_LINK)
except:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS, text=error_message_from_db(4))
bot.send_message(chat_id=IMPORTANT_LOGS, text=BotDB.get_error_message_from_db(4))
after_post(message=message)
@@ -285,7 +337,7 @@ def telegram_bot():
bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
except:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS, text=error_message_from_db(3))
bot.send_message(chat_id=IMPORTANT_LOGS, text=BotDB.get_error_message_from_db(3))
elif call.data == 'post_post_post' and call.message.content_type == 'photo':
try:
bot.send_photo(
@@ -296,16 +348,14 @@ def telegram_bot():
bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
except:
if LOGS:
bot.send_message(chat_id=IMPORTANT_LOGS, text=error_message_from_db(2))
bot.send_message(chat_id=IMPORTANT_LOGS, text=BotDB.get_error_message_from_db(2))
elif call.data == 'decline':
try:
bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
except:
if LOGS:
logs(IMPORTANT_LOGS, error_message_from_db(1))
bot.send_message(IMPORTANT_LOGS, BotDB.get_error_message_from_db(1))
def logs(chat_name, text_error):
bot.send_message(chat_id=chat_name, text=text_error)
if __name__ == '__main__':
telegram_bot()