diff --git a/bot_modules/access.py b/bot_modules/access.py new file mode 100644 index 0000000..fb4e7e8 --- /dev/null +++ b/bot_modules/access.py @@ -0,0 +1,49 @@ +# -*- coding: utf8 -*- +# Общественное достояние 2023, Алексей Безбородов (Alexei Bezborodov) + +# Профиль пользователя + +from bot_sys import bot_bd, log, config, keyboard +from bot_modules import start +from aiogram import Bot, types + +import sqlite3 + +from aiogram.dispatcher import Dispatcher + +bot = Bot(token=config.GetTelegramBotApiToken(), parse_mode=types.ParseMode.HTML) + +# --------------------------------------------------------- +# БД +init_bd_cmds = [] + +# --------------------------------------------------------- +# Сообщения + +# --------------------------------------------------------- +# Работа с кнопками + +# --------------------------------------------------------- +# Обработка сообщений + +# --------------------------------------------------------- +# Работа с базой данных + + +# --------------------------------------------------------- +# API + +def GetUserAccess(a_UserID): + return None + +# Инициализация БД +def GetInitBDCommands(): + return init_bd_cmds + +# Доступные кнопки +def GetButtonNames(a_UserAccess): + return [] + +# Обработка кнопок +def RegisterHandlers(dp : Dispatcher): + return diff --git a/bot_modules/groups.py b/bot_modules/groups.py new file mode 100644 index 0000000..aff760d --- /dev/null +++ b/bot_modules/groups.py @@ -0,0 +1,193 @@ +# -*- coding: utf8 -*- +# Общественное достояние 2023, Алексей Безбородов (Alexei Bezborodov) + +# Группы пользователей + +from bot_sys import bot_bd, log, config, keyboard +from bot_modules import start, access +from aiogram import Bot, types +from aiogram.dispatcher import FSMContext +from aiogram.dispatcher.filters.state import State, StatesGroup + +import sqlite3 + +from aiogram.dispatcher import Dispatcher + +bot = Bot(token=config.GetTelegramBotApiToken(), parse_mode=types.ParseMode.HTML) + +class FSMRequestToBD(StatesGroup): + sqlRequest = State() + +# --------------------------------------------------------- +# БД +init_bd_cmds = ["""CREATE TABLE IF NOT EXISTS user_groups( + group_id INTEGER PRIMARY KEY NOT NULL, + groupName TEXT, + UNIQUE(group_id) +);""", +"""CREATE TABLE IF NOT EXISTS user_in_groups( + user_id INTEGER, + group_id INTEGER, + UNIQUE(user_id, group_id) +);""", +] + +# --------------------------------------------------------- +# Сообщения + +group_start_message = ''' +Группы пользователей находятся в стадии разработки + +Пока можете воспользоваться хардкорным способом через запросы к БД +''' + +request_start_message = ''' +**Задайте запрос к БД** + +Можете воспользоваться следующими шаблонами: +1. `SELECT * FROM users` - Все пользователи +2. `SELECT group_id, groupName FROM user_groups` - Все группы пользоватлей +3. `INSERT INTO user_groups(groupName) VALUES('GROUPNAME')` - добавление группы с именем GROUPNAME +4. `SELECT group_id FROM user_in_groups WHERE user_id = USERID`- Все ID групп в которых состоит пользователь с USERID +5. `SELECT groupName FROM user_groups WHERE group_id=(SELECT groupid FROM user_in_groups WHERE user_id = USERID)` - Все имена групп пользователя с USERID +6. `INSERT INTO user_in_groups(user_id, group_id) VALUES(USERID, GROUPID)` - добавление пользователя USERID в группу с GROUPID +''' + +request_cancel_message = ''' +Запрос к БД отменён +''' + +user_group_button_name = "📰 Группы пользователей" +sql_request_button_name = "📰 Запрос к БД" +canсel_button_name = "📰 Отменить" + +# --------------------------------------------------------- +# Работа с кнопками + +def GetEditGroupKeyboardButtons(a_UserAccess): + cur_buttons = [sql_request_button_name] + mods = [start] + return keyboard.MakeKeyboard(keyboard.GetButtons(mods, a_UserAccess) + cur_buttons) + +def GetCancelKeyboardButtons(a_UserAccess): + return keyboard.MakeKeyboard([canсel_button_name]) + +# --------------------------------------------------------- +# Обработка сообщений + +# Приветствие +async def GroupStart(a_Message): + user_id = str(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) + await bot.send_message(user_id, group_start_message, reply_markup = GetEditGroupKeyboardButtons(user_access)) + +async def RequestToBDCancel(a_Message : types.message, state : FSMContext): + user_access = access.GetUserAccess(a_Message.from_user.id) + await state.finish() + await a_Message.answer(request_cancel_message, reply_markup = GetEditGroupKeyboardButtons(user_access)) + +async def RequestToBDStart(a_Message : types.message): + user_access = access.GetUserAccess(a_Message.from_user.id) + await FSMRequestToBD.sqlRequest.set() + await a_Message.answer(request_start_message, reply_markup = GetCancelKeyboardButtons(user_access), parse_mode='Markdown') + +async def RequestToBD(a_Message : types.message, state : FSMContext): + user_access = access.GetUserAccess(a_Message.from_user.id) + result = '' + async with state.proxy() as prjData: + sql_request = a_Message.text + log.Success(f'Сделан запрос [{sql_request}] пользователем {a_Message.from_user.id}.') + result = SQLRequestToBD(sql_request) + log.Success(f'Результат запроса [{sql_request}] от пользователя {a_Message.from_user.id} следующий [{result}].') + await state.finish() + await a_Message.answer(str(result), reply_markup = GetEditGroupKeyboardButtons(user_access)) + +# --------------------------------------------------------- +# Работа с базой данных групп + +def SQLRequestToBD(a_Request : str): + db = sqlite3.connect(bot_bd.GetBDFileName()) + cursor = db.cursor() + cursor.execute(a_Request) + result = cursor.fetchall() + db.commit() + cursor.close() + db.close() + return result + +def GetGroupIDForUser(a_UserID): + db = sqlite3.connect(bot_bd.GetBDFileName()) + cursor = db.cursor() + groups = cursor.execute('SELECT group_id FROM user_in_groups WHERE user_id = ?', (a_UserID)).fetchall() + cursor.close() + db.close() + return groups + +def GetGroupNamesForUser(a_UserID): + db = sqlite3.connect(bot_bd.GetBDFileName()) + cursor = db.cursor() + groups = cursor.execute('SELECT groupName FROM user_groups WHERE group_id=(SELECT group_id FROM user_in_groups WHERE user_id = ?)', (a_UserID)).fetchall() + cursor.close() + db.close() + print(groups) + return groups + +def GetGroupList(): + db = sqlite3.connect(bot_bd.GetBDFileName()) + cursor = db.cursor() + groups = cursor.execute('SELECT * FROM user_groups').fetchall() + cursor.close() + db.close() + return groups + +def GetGroup(a_GroupID): + db = sqlite3.connect(bot_bd.GetBDFileName()) + cursor = db.cursor() + group = cursor.execute('SELECT * FROM user_groups WHERE groupID = ?', ([a_GroupID])).fetchall() + cursor.close() + db.close() + return group + +def AddGroup(a_Name): + db = sqlite3.connect(bot_bd.GetBDFileName()) + cursor = db.cursor() + cursor.execute('INSERT INTO user_groups(groupName) VALUES(?)', (a_prjName)) + db.commit() + cursor.close() + db.close() + return + +def EditGroup(a_GroupID, a_Name): + db = sqlite3.connect(bot_bd.GetBDFileName()) + cursor = db.cursor() + cursor.execute('UPDATE user_groups SET groupName = ? WHERE groupID = ?', (a_prjPhoto, a_Name)) + db.commit() + cursor.close() + db.close() + return + +def DelGroup(a_GroupID): + db = sqlite3.connect(bot_bd.GetBDFileName()) + cursor = db.cursor() + cursor.execute('DELETE FROM user_groups WHERE groupID = ?', ([a_GroupID])) + db.commit() + db.close() + return + +# --------------------------------------------------------- +# API + +# Инициализация БД +def GetInitBDCommands(): + return init_bd_cmds + +# Доступные кнопки +def GetButtonNames(a_UserAccess): + return [user_group_button_name] + +# Обработка кнопок +def RegisterHandlers(dp : Dispatcher): + dp.register_message_handler(GroupStart, text = user_group_button_name) + dp.register_message_handler(RequestToBDStart, text = sql_request_button_name) + dp.register_message_handler(RequestToBDCancel, text = canсel_button_name, state = FSMRequestToBD.sqlRequest) + dp.register_message_handler(RequestToBD, state = FSMRequestToBD.sqlRequest) diff --git a/bot_modules/profile.py b/bot_modules/profile.py index f28f970..62306f1 100644 --- a/bot_modules/profile.py +++ b/bot_modules/profile.py @@ -15,11 +15,11 @@ bot = Bot(token=config.GetTelegramBotApiToken(), parse_mode=types.ParseMode.HTML # --------------------------------------------------------- # БД -init_bd_cmd = """CREATE TABLE IF NOT EXISTS users( +init_bd_cmds = ["""CREATE TABLE IF NOT EXISTS users( user_id INTEGER, userName TEXT, UNIQUE(user_id) -);""" +);"""] # --------------------------------------------------------- # Сообщения @@ -80,7 +80,7 @@ def GetUserInfo(a_UserID): # Инициализация БД def GetInitBDCommands(): - return [init_bd_cmd] + return init_bd_cmds # Доступные кнопки def GetButtonNames(a_UserAccess): diff --git a/bot_modules/projects.py b/bot_modules/projects.py index f1ecda8..0b5ffae 100644 --- a/bot_modules/projects.py +++ b/bot_modules/projects.py @@ -4,7 +4,7 @@ # Проекты from bot_sys import bot_bd, log, config, keyboard -from bot_modules import start +from bot_modules import start, access from aiogram import Bot, types from aiogram.dispatcher import FSMContext from aiogram.dispatcher.filters.state import State, StatesGroup @@ -26,12 +26,12 @@ class FSMEditProject(StatesGroup): # --------------------------------------------------------- # БД -init_bd_cmd = '''CREATE TABLE IF NOT EXISTS projects( +init_bd_cmds = ['''CREATE TABLE IF NOT EXISTS projects( projectPhoto TEXT, projectName TEXT, projectDesc TEXT, projectID INTEGER PRIMARY KEY -)''' +)'''] # --------------------------------------------------------- # Сообщения @@ -157,15 +157,12 @@ def GetProjectsListKeyboardButtons(a_UserAccess, a_Prefix): projects_button_list += [keyboard.Button(str(t[1]), t[3])] return keyboard.MakeInlineKeyboard(projects_button_list, a_Prefix) -def GetUserAccess(a_UserID): - return None - # --------------------------------------------------------- # Обработка сообщений # Отображение всех проектов async def ProjectsOpen(a_Message : types.message): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) await bot.send_message(a_Message.from_user.id, base_project_message, reply_markup = GetEditProjectKeyboardButtons(user_access)) await bot.send_message(a_Message.from_user.id, select_project_message, reply_markup = GetProjectsListKeyboardButtons(user_access, select_project_callback_prefix)) @@ -181,7 +178,7 @@ def GetProjectData(a_ProjectID): async def ShowProject(a_CallbackQuery : types.CallbackQuery): project_id = str(a_CallbackQuery.data).replace(select_project_callback_prefix, '') - user_access = GetUserAccess(a_CallbackQuery.from_user.id) + user_access = access.GetUserAccess(a_CallbackQuery.from_user.id) msg, photo_id, name, desc = GetProjectData(project_id) if msg != '': await bot.send_message(a_CallbackQuery.from_user.id, msg, reply_markup = GetEditProjectKeyboardButtons(user_access)) @@ -196,17 +193,17 @@ async def ShowProject(a_CallbackQuery : types.CallbackQuery): # Создание нового проекта async def ProjectCreateCancel(a_Message : types.message, state : FSMContext): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) await state.finish() await a_Message.answer(project_cancel_create_message, reply_markup = GetEditProjectKeyboardButtons(user_access)) async def ProjectCreate(a_Message : types.message): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) await FSMCreateProject.prjPhoto.set() await a_Message.answer(project_create_message_1, reply_markup = GetSkipAndCancelKeyboardButtons(user_access)) async def PhotoLoad(a_Message : types.message, state : FSMContext, a_FileID): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) async with state.proxy() as prjData: prjData['photo'] = a_FileID await FSMCreateProject.next() @@ -219,14 +216,14 @@ async def ProjectPhotoSkip(a_Message : types.message, state : FSMContext): await PhotoLoad(a_Message, state, 0) async def ProjectNameLoad(a_Message : types.message, state : FSMContext): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) async with state.proxy() as prjData: prjData['name'] = a_Message.text await FSMCreateProject.next() await a_Message.answer(project_create_message_3, reply_markup = GetCancelKeyboardButtons(user_access)) async def ProjectDescLoad(a_Message : types.message, state : FSMContext): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) async with state.proxy() as prjData: prjData['desc'] = a_Message.text prjPhoto = prjData['photo'] @@ -240,16 +237,16 @@ async def ProjectDescLoad(a_Message : types.message, state : FSMContext): # Редактирование проекта async def ProjectSelectForEdit(a_Message : types.message): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) await bot.send_message(a_Message.from_user.id, project_select_to_edit_message, reply_markup = GetProjectsListKeyboardButtons(user_access, select_to_edit_project_callback_prefix)) async def ProjectEditCancel(a_Message : types.message, state : FSMContext): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) await state.finish() await a_Message.answer(project_cancel_edit_message, reply_markup = GetEditProjectKeyboardButtons(user_access)) async def ProjectEdit(a_CallbackQuery : types.CallbackQuery, state : FSMContext): - user_access = GetUserAccess(a_CallbackQuery.from_user.id) + user_access = access.GetUserAccess(a_CallbackQuery.from_user.id) await FSMEditProject.prjID.set() prjID = str(a_CallbackQuery.data).replace(select_to_edit_project_callback_prefix, '') async with state.proxy() as prjData: @@ -258,7 +255,7 @@ async def ProjectEdit(a_CallbackQuery : types.CallbackQuery, state : FSMContext) await bot.send_message(a_CallbackQuery.from_user.id, project_edit_message_1, reply_markup = GetSkipAndCancelKeyboardButtons(user_access)) async def PhotoEditLoad(a_Message : types.message, state : FSMContext, a_FileID): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) project_id = 0 async with state.proxy() as prjData: prjData['photo'] = a_FileID @@ -284,7 +281,7 @@ async def ProjectEditPhotoSkip(a_Message : types.message, state : FSMContext): await PhotoEditLoad(a_Message, state, photo_id) async def EditNameSkip(a_Message : types.message, state : FSMContext, a_Name): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) async with state.proxy() as prjData: prjData['name'] = a_Name await FSMEditProject.next() @@ -294,7 +291,7 @@ async def ProjectEditNameLoad(a_Message : types.message, state : FSMContext): await EditNameSkip(a_Message, state, a_Message.text) async def ProjectEditDescLoad(a_Message : types.message, state : FSMContext): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) async with state.proxy() as prjData: prjData['desc'] = a_Message.text project_id = prjData['prjID'] @@ -309,11 +306,11 @@ async def ProjectEditDescLoad(a_Message : types.message, state : FSMContext): # Удаление проекта async def ProjectDelete(a_Message : types.message): - user_access = GetUserAccess(a_Message.from_user.id) + user_access = access.GetUserAccess(a_Message.from_user.id) await bot.send_message(a_Message.from_user.id, project_select_to_delete_message, reply_markup = GetProjectsListKeyboardButtons(user_access, delete_project_callback_prefix)) async def prjDelete(a_CallbackQuery : types.CallbackQuery): - user_access = GetUserAccess(a_CallbackQuery.from_user.id) + user_access = access.GetUserAccess(a_CallbackQuery.from_user.id) projectID = str(a_CallbackQuery.data).replace(delete_project_callback_prefix, '') DelProject(projectID) log.Success(f'Проект №{projectID} был удалён пользователем {a_CallbackQuery.from_user.id}.') @@ -369,7 +366,7 @@ def DelProject(a_ProjectID): # Инициализация БД def GetInitBDCommands(): - return [init_bd_cmd] + return init_bd_cmds # Доступные кнопки def GetButtonNames(a_UserAccess): diff --git a/bot_modules/start.py b/bot_modules/start.py index 034a238..7b33dda 100644 --- a/bot_modules/start.py +++ b/bot_modules/start.py @@ -4,7 +4,7 @@ # Стартовое меню from bot_sys import log, config, keyboard -from bot_modules import profile, projects +from bot_modules import profile, projects, groups from aiogram.dispatcher import Dispatcher @@ -23,7 +23,7 @@ start_menu_button_name = "☰ Главное меню" # Работа с кнопками def GetStartKeyboardButtons(a_UserAccess): - mods = [profile, projects] + mods = [profile, projects, groups] return keyboard.MakeKeyboardForMods(mods, a_UserAccess) # --------------------------------------------------------- diff --git a/main.py b/main.py index 3ce0964..2ea23a3 100644 --- a/main.py +++ b/main.py @@ -10,13 +10,13 @@ from aiogram.dispatcher import Dispatcher from aiogram.contrib.fsm_storage.memory import MemoryStorage import sqlite3 from bot_sys import config, log, bot_bd, user_access -from bot_modules import profile, start, projects +from bot_modules import profile, start, projects, groups storage = MemoryStorage() bot = Bot(token=config.GetTelegramBotApiToken(), parse_mode = types.ParseMode.HTML) dp = Dispatcher(bot, storage = storage) -mods = [profile, start, projects] +mods = [profile, start, projects, groups] init_bd_cmd = [] for m in mods: