From d9c7d0f8f6a25cefb0e6ec8e37e9c33b5efebec4 Mon Sep 17 00:00:00 2001 From: ilyak Date: Mon, 1 Jan 2024 19:48:39 +0500 Subject: [PATCH 01/14] 1 --- bot.py | 10 +++---- data/sql_database.py | 58 ++++++++++++++++++++++++++++++------ handlers/user_handlers.py | 62 ++++++++++++++++++++++++--------------- keyboards/keyboards.py | 1 + lexicon/lexicon.py | 1 + services/services.py | 10 ++++++- 6 files changed, 104 insertions(+), 38 deletions(-) diff --git a/bot.py b/bot.py index 274f858..cb4c4ff 100644 --- a/bot.py +++ b/bot.py @@ -4,11 +4,12 @@ from aiogram import Bot, Dispatcher from config.config import Config, load_config from handlers import user_handlers -from data.sql_database import LobbyDatabase +from data.sql_database import LobbyDatabase, UsersWithoutLobbiesDatabase from services.set_menu import set_main_menu logger = logging.getLogger(__name__) -lobby_database = LobbyDatabase('test3') +lobby_database = LobbyDatabase('test6') +users_without_lobbies_database = UsersWithoutLobbiesDatabase('test5') config: Config = load_config() bot = Bot(token=config.tg_bot.token, parse_mode='HTML') @@ -16,11 +17,10 @@ async def main(): lobby_database.create_table() - for i in range(1, 5): + users_without_lobbies_database.create_table() + for i in range(-1, 5): lobby_database.reset_lobby(i) lobby_database.default_lobby(i) - lobby_database.reset_lobby(-1) - lobby_database.default_lobby(-1) logging.basicConfig(level=logging.INFO, format='%(filename)s:%(lineno)d #%(levelname)-8s ' '[%(asctime)s] - %(name)s - %(message)s') diff --git a/data/sql_database.py b/data/sql_database.py index 2563d9a..767e819 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -1,6 +1,6 @@ import sqlite3 -conn = sqlite3.connect('test.py') +conn = sqlite3.connect('test1.py') class LobbyDatabase: @@ -10,7 +10,7 @@ def __init__(self, name): def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} - (id INT PRIMARY KEY, + (lobby_id INT PRIMARY KEY, people TEXT);""") conn.commit() cur.close() @@ -18,7 +18,7 @@ def create_table(self): def default_lobby(self, lobby_id: int): cur = conn.cursor() - cur.execute(f"""INSERT OR IGNORE INTO {self.name} (id, people) + cur.execute(f"""INSERT OR IGNORE INTO {self.name} (lobby_id, people) VALUES ({lobby_id}, ''); """) conn.commit() @@ -27,37 +27,77 @@ def default_lobby(self, lobby_id: int): def enter_lobby(self, lobby_id: int, user_chat_id: str): cur = conn.cursor() cur.execute(f"""SELECT people FROM {self.name} - WHERE id={lobby_id}; + WHERE lobby_id={lobby_id}; """) s = cur.fetchone()[0].split() s.append(user_chat_id) - cur.execute(f"""UPDATE {self.name} SET people='{' '.join(s)}' WHERE id={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET people='{' '.join(s)}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() def exit_lobby(self, lobby_id: int, user_chat_id: str): cur = conn.cursor() cur.execute(f"""SELECT people FROM {self.name} - WHERE id={lobby_id}; + WHERE lobby_id={lobby_id}; """) s = cur.fetchone()[0].split() s.remove(user_chat_id) - cur.execute(f"""UPDATE {self.name} SET people='{' '.join(s)}' WHERE id={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET people='{' '.join(s)}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() def reset_lobby(self, lobby_id: int): cur = conn.cursor() - cur.execute(f"""UPDATE {self.name} SET people='' WHERE id={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET people='' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() def get_lobby_stat(self, lobby_id: int): cur = conn.cursor() cur.execute(f"""SELECT people FROM {self.name} - WHERE id={lobby_id}; + WHERE lobby_id={lobby_id}; """) s = cur.fetchone()[0].split() conn.commit() cur.close() return s + + +class UsersWithoutLobbiesDatabase: + def __init__(self, name): + self.name = name + + def create_table(self): + cur = conn.cursor() + cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} + (chat_id INT PRIMARY KEY, + message_id INT);""") + conn.commit() + cur.close() + print('[INFO] TABLE CREATED SUCCESSFULLY') + + def insert_users_message_id(self, chat_id, message_id): + cur = conn.cursor() + cur.execute(f"""INSERT OR IGNORE INTO {self.name} (chat_id, message_id) + VALUES ({chat_id}, {message_id}); + """) + conn.commit() + cur.close() + + def update_users_message_id(self, chat_id, message_id): + cur = conn.cursor() + cur.execute(f"""UPDATE {self.name} SET message_id='{message_id}' WHERE chat_id={chat_id};""") + conn.commit() + cur.close() + + def get_statistic_of_users(self): + cur = conn.cursor() + cur.execute(f"""SELECT chat_id, message_id FROM {self.name}""") + stat = cur.fetchall() + conn.commit() + cur.close() + return stat + + def delete_chat_id(self, chat_id): + cur = conn.cursor() + cur.execute(f"""DELETE FROM {self.name} WHERE chat_id={chat_id};""") diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index b8834f3..ece99e5 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -3,28 +3,34 @@ from aiogram.types import Message, CallbackQuery from bot import bot -from data.sql_database import LobbyDatabase +from data.sql_database import LobbyDatabase, UsersWithoutLobbiesDatabase from keyboards.keyboards import keyboard_builder, create_inline_kb, LobbyCallbackFactory from aiogram.fsm.context import FSMContext from aiogram.fsm.state import default_state -from services.services import FSMLobbyClass, create_lobbies_page +from services.services import FSMLobbyClass, create_lobbies_page, send_messages_to_users router = Router() -lobby_database = LobbyDatabase('test3') +lobby_database = LobbyDatabase('test6') +users_without_lobbies_database = UsersWithoutLobbiesDatabase('test5') -# @router.message(Command(commands='start')) -# async def start(message: Message): +@router.message(Command(commands='start')) +async def start(message: Message, + state: FSMContext): + await message.answer(text='Это тренировочный бот для игры в ... с другими людьми.\nДля начала выберите лобби,' + ' использовав команду /lobbies') + users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, message_id=message.message_id) + await state.set_state(default_state) @router.message(Command(commands='lobbies'), StateFilter(default_state)) -async def test2(message: Message, - state: FSMContext): +async def lobbies(message: Message, + state: FSMContext): lobby_pages = create_lobbies_page() keyboards = create_inline_kb(2, dct=lobby_pages) - await message.answer(text='Список доступных лобби', reply_markup=keyboards) + bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboards) await state.set_state(FSMLobbyClass.select_lobby) - lobby_database.enter_lobby(lobby_id=-1, user_chat_id=str(message.chat.id)) + users_without_lobbies_database.update_users_message_id(chat_id=message.chat.id, message_id=bot_message.message_id) @router.callback_query(LobbyCallbackFactory.filter(), StateFilter(FSMLobbyClass.select_lobby)) @@ -35,33 +41,33 @@ async def lobby_page(callback: CallbackQuery, if len(lobby_stat) < 4: await state.set_state(FSMLobbyClass.in_lobby) lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id)) - lobby_database.exit_lobby(lobby_id=-1, user_chat_id=str(callback.message.chat.id)) - people_without_lobby = lobby_database.get_lobby_stat(-1) + users_without_lobbies_database.delete_chat_id(chat_id=callback.message.chat.id) + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() lobby_pages = create_lobbies_page() - for i in people_without_lobby: - await bot.edit_message_text(chat_id=int(i), text='Список доступных лобби', reply_markup=lobby_pages) + keyboard = create_inline_kb(width=2, dct=lobby_pages) + for chat_id, message_id in people_without_lobby: + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) await state.update_data(lobby=callback_data.lobby_id) - for i in lobby_stat: - await bot.send_message(chat_id=int(i), text=f'{callback.from_user.full_name} зашел в лобби') + await send_messages_to_users(bot=bot, message=f'{callback.from_user.full_name} зашел в лобби', users=lobby_stat) await callback.message.delete() await callback.message.answer(text=f'Вы вошли в лобби №{callback_data.lobby_id}! Любое ваше сообщение будет ' - f'отправлено участникам лобби!', - reply_markup=keyboard_builder(buttons=['Выйти'], - width=1)) + f'отправлено участникам лобби!\n' + f'Для выхода нажмите /exit') else: await callback.answer('Лобби заполнено') -@router.message(F.text == 'Выйти', StateFilter(FSMLobbyClass.in_lobby)) +@router.message(Command(commands='exit'), StateFilter(FSMLobbyClass.in_lobby)) async def exit_command(message: Message, state: FSMContext): await state.set_state(FSMLobbyClass.select_lobby) data = await state.get_data() lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id)) - lobby_database.enter_lobby(lobby_id=-1, user_chat_id=str(message.chat.id)) lobby_pages = create_lobbies_page() - keyboards = create_inline_kb(2, dct=lobby_pages) - await message.answer(text='Список доступных лобби', reply_markup=keyboards) + keyboards = create_inline_kb(width=2, dct=lobby_pages) + bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboards) + users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, message_id=bot_message.message_id) @router.message(StateFilter(FSMLobbyClass.in_lobby)) @@ -71,4 +77,14 @@ async def others(message: Message, people = lobby_database.get_lobby_stat(data['lobby']) for i in people: if int(i) != message.chat.id: - await bot.send_message(chat_id=int(i), text=message.text) \ No newline at end of file + await bot.send_message(chat_id=int(i), text=message.text) + + +# @router.message(Command(commands='test')) +# async def test(message: Message): +# people_without_lobby = users_without_lobbies_database.get_statistic_of_users() +# lobby_pages = create_lobbies_page() +# keyboard = create_inline_kb(2, dct=lobby_pages) +# for chat_id, message_id in people_without_lobby: +# await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, +# reply_markup=keyboard) diff --git a/keyboards/keyboards.py b/keyboards/keyboards.py index d942f0f..0b236b1 100644 --- a/keyboards/keyboards.py +++ b/keyboards/keyboards.py @@ -4,6 +4,7 @@ from aiogram.filters.callback_data import CallbackData from aiogram.types import KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton from aiogram.utils.keyboard import ReplyKeyboardBuilder, InlineKeyboardBuilder +from lexicon.lexicon import keyboard_lexicon def keyboard_builder(buttons: list, diff --git a/lexicon/lexicon.py b/lexicon/lexicon.py index f2cf915..beeb3d5 100644 --- a/lexicon/lexicon.py +++ b/lexicon/lexicon.py @@ -3,3 +3,4 @@ '/lobbies': 'Все лобби' } +keyboard_lexicon = {} diff --git a/services/services.py b/services/services.py index 68e27e1..b3c6a5d 100644 --- a/services/services.py +++ b/services/services.py @@ -1,9 +1,10 @@ +from aiogram import Bot from aiogram.fsm.state import State, StatesGroup from data.sql_database import LobbyDatabase from keyboards.keyboards import LobbyCallbackFactory -lobby_database = LobbyDatabase('test3') +lobby_database = LobbyDatabase('test6') class FSMLobbyClass(StatesGroup): @@ -14,3 +15,10 @@ class FSMLobbyClass(StatesGroup): def create_lobbies_page(): return {LobbyCallbackFactory(lobby_id=i).pack(): f'Лобби №{i} {len(lobby_database.get_lobby_stat(i))}/4' for i in range(1, 5)} + + +async def send_messages_to_users(bot: Bot, message: str, users: list): + for i in users: + await bot.send_message(chat_id=int(i), text=message) + + From 9237c3d6eaa2c2d5213eacb563c2177f887826ce Mon Sep 17 00:00:00 2001 From: ilyak Date: Tue, 2 Jan 2024 00:36:48 +0500 Subject: [PATCH 02/14] 1 --- data/sql_database.py | 40 ++++++++++---------- handlers/user_handlers.py | 80 +++++++++++++++++++++++++++------------ services/services.py | 8 +++- 3 files changed, 82 insertions(+), 46 deletions(-) diff --git a/data/sql_database.py b/data/sql_database.py index 767e819..029ceb0 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -10,53 +10,53 @@ def __init__(self, name): def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} - (lobby_id INT PRIMARY KEY, - people TEXT);""") + (lobby_id INT PRIMARY KEY, + users TEXT); + """) conn.commit() cur.close() print('[INFO] TABLE CREATED SUCCESSFULLY') def default_lobby(self, lobby_id: int): cur = conn.cursor() - cur.execute(f"""INSERT OR IGNORE INTO {self.name} (lobby_id, people) + cur.execute(f"""INSERT OR IGNORE INTO {self.name} (lobby_id, users) VALUES ({lobby_id}, ''); """) conn.commit() cur.close() - def enter_lobby(self, lobby_id: int, user_chat_id: str): + def enter_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): cur = conn.cursor() - cur.execute(f"""SELECT people FROM {self.name} + cur.execute(f"""SELECT users FROM {self.name} WHERE lobby_id={lobby_id}; """) - s = cur.fetchone()[0].split() - s.append(user_chat_id) - cur.execute(f"""UPDATE {self.name} SET people='{' '.join(s)}' WHERE lobby_id={lobby_id};""") + pairs = cur.fetchone()[0].split() + pairs.append(f"""{user_chat_id}-{user_name}""") + cur.execute(f"""UPDATE {self.name} SET users='{' '.join(pairs)}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() - def exit_lobby(self, lobby_id: int, user_chat_id: str): + def exit_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): cur = conn.cursor() - cur.execute(f"""SELECT people FROM {self.name} + cur.execute(f"""SELECT users FROM {self.name} WHERE lobby_id={lobby_id}; """) - s = cur.fetchone()[0].split() - s.remove(user_chat_id) - cur.execute(f"""UPDATE {self.name} SET people='{' '.join(s)}' WHERE lobby_id={lobby_id};""") + pairs = cur.fetchone()[0].split() + pairs.remove(f"""{user_chat_id}-{user_name}""") + cur.execute(f"""UPDATE {self.name} SET users='{' '.join(pairs)}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() def reset_lobby(self, lobby_id: int): cur = conn.cursor() - cur.execute(f"""UPDATE {self.name} SET people='' WHERE lobby_id={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET users='' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() def get_lobby_stat(self, lobby_id: int): cur = conn.cursor() - cur.execute(f"""SELECT people FROM {self.name} - WHERE lobby_id={lobby_id}; - """) + cur.execute(f"""SELECT users FROM {self.name} + WHERE lobby_id={lobby_id};""") s = cur.fetchone()[0].split() conn.commit() cur.close() @@ -70,8 +70,8 @@ def __init__(self, name): def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} - (chat_id INT PRIMARY KEY, - message_id INT);""") + (chat_id INT PRIMARY KEY, + message_id INT);""") conn.commit() cur.close() print('[INFO] TABLE CREATED SUCCESSFULLY') @@ -101,3 +101,5 @@ def get_statistic_of_users(self): def delete_chat_id(self, chat_id): cur = conn.cursor() cur.execute(f"""DELETE FROM {self.name} WHERE chat_id={chat_id};""") + conn.commit() + cur.close() \ No newline at end of file diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index ece99e5..6414aa1 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -1,13 +1,14 @@ -from aiogram import Router, F +from aiogram import Router +from aiogram.exceptions import TelegramBadRequest from aiogram.filters import Command, StateFilter from aiogram.types import Message, CallbackQuery from bot import bot from data.sql_database import LobbyDatabase, UsersWithoutLobbiesDatabase -from keyboards.keyboards import keyboard_builder, create_inline_kb, LobbyCallbackFactory +from keyboards.keyboards import create_inline_kb, LobbyCallbackFactory from aiogram.fsm.context import FSMContext from aiogram.fsm.state import default_state -from services.services import FSMLobbyClass, create_lobbies_page, send_messages_to_users +from services.services import FSMLobbyClass, create_lobbies_page, send_messages_to_users, get_lobby_members router = Router() lobby_database = LobbyDatabase('test6') @@ -40,20 +41,27 @@ async def lobby_page(callback: CallbackQuery, lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) if len(lobby_stat) < 4: await state.set_state(FSMLobbyClass.in_lobby) - lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id)) + lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id), + user_name=callback.from_user.full_name) users_without_lobbies_database.delete_chat_id(chat_id=callback.message.chat.id) people_without_lobby = users_without_lobbies_database.get_statistic_of_users() lobby_pages = create_lobbies_page() keyboard = create_inline_kb(width=2, dct=lobby_pages) for chat_id, message_id in people_without_lobby: - await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, - reply_markup=keyboard) + try: + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) + except TelegramBadRequest: + pass await state.update_data(lobby=callback_data.lobby_id) await send_messages_to_users(bot=bot, message=f'{callback.from_user.full_name} зашел в лобби', users=lobby_stat) await callback.message.delete() - await callback.message.answer(text=f'Вы вошли в лобби №{callback_data.lobby_id}! Любое ваше сообщение будет ' - f'отправлено участникам лобби!\n' - f'Для выхода нажмите /exit') + lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) + await callback.message.answer(text=f'Вы вошли в лобби №{callback_data.lobby_id}!\n\n' + f'Участники:\n' + f'{get_lobby_members(lobby_stat)}\n\n' + f'Информация о лобби - /info\n' + f'Выйти - /exit') else: await callback.answer('Лобби заполнено') @@ -61,30 +69,52 @@ async def lobby_page(callback: CallbackQuery, @router.message(Command(commands='exit'), StateFilter(FSMLobbyClass.in_lobby)) async def exit_command(message: Message, state: FSMContext): - await state.set_state(FSMLobbyClass.select_lobby) data = await state.get_data() - lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id)) + await state.clear() + lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), + user_name=message.from_user.full_name) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + await send_messages_to_users(bot=bot, message=f'{message.from_user.full_name} Вышел из лобби', users=lobby_stat) lobby_pages = create_lobbies_page() - keyboards = create_inline_kb(width=2, dct=lobby_pages) - bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboards) + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + keyboard = create_inline_kb(width=2, dct=lobby_pages) + for chat_id, message_id in people_without_lobby: + try: + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) + except TelegramBadRequest: + pass + await state.set_state(FSMLobbyClass.select_lobby) + bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboard) users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, message_id=bot_message.message_id) +@router.message(Command(commands='info'), StateFilter(FSMLobbyClass.in_lobby)) +async def info_command(message: Message, + state: FSMContext): + data = await state.get_data() + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + await message.answer(text=f'Лобби №{data["lobby"]}\n\n' + f'Участники:\n' + f'{get_lobby_members(lobby_stat)}\n\n' + f'Выйти - /exit') + + @router.message(StateFilter(FSMLobbyClass.in_lobby)) async def others(message: Message, state: FSMContext): data = await state.get_data() people = lobby_database.get_lobby_stat(data['lobby']) for i in people: - if int(i) != message.chat.id: - await bot.send_message(chat_id=int(i), text=message.text) - - -# @router.message(Command(commands='test')) -# async def test(message: Message): -# people_without_lobby = users_without_lobbies_database.get_statistic_of_users() -# lobby_pages = create_lobbies_page() -# keyboard = create_inline_kb(2, dct=lobby_pages) -# for chat_id, message_id in people_without_lobby: -# await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, -# reply_markup=keyboard) + if int(i.split('-')[0]) != message.chat.id: + await bot.send_message(chat_id=int(i), text=f"""{message.from_user.full_name}: {message.text}""") + + +@router.message(Command(commands='test')) +async def test(message: Message): + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + lobby_pages = create_lobbies_page() + keyboard = create_inline_kb(2, dct=lobby_pages) + for chat_id, message_id in people_without_lobby: + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) diff --git a/services/services.py b/services/services.py index b3c6a5d..9796d14 100644 --- a/services/services.py +++ b/services/services.py @@ -14,11 +14,15 @@ class FSMLobbyClass(StatesGroup): def create_lobbies_page(): - return {LobbyCallbackFactory(lobby_id=i).pack(): f'Лобби №{i} {len(lobby_database.get_lobby_stat(i))}/4' for i in range(1, 5)} + return {LobbyCallbackFactory(lobby_id=i).pack(): f'Лобби №{i} {len(lobby_database.get_lobby_stat(i))}/4' + for i in range(1, 5)} async def send_messages_to_users(bot: Bot, message: str, users: list): for i in users: - await bot.send_message(chat_id=int(i), text=message) + await bot.send_message(chat_id=int(i.split('-')[0]), text=message) +def get_lobby_members(pairs: list): + members = list(map(lambda x: x.split('-')[1], pairs)) + return '\n'.join(members) From 8ac285dee13d9a147025e804924e9b1f217f4329 Mon Sep 17 00:00:00 2001 From: ilyak Date: Tue, 2 Jan 2024 16:31:59 +0500 Subject: [PATCH 03/14] 1 --- bot.py | 8 +-- data/sql_database.py | 30 +++++------ handlers/user_handlers.py | 104 +++++++++++++++++++++++--------------- lexicon/lexicon.py | 4 +- 4 files changed, 82 insertions(+), 64 deletions(-) diff --git a/bot.py b/bot.py index cb4c4ff..6eb44f5 100644 --- a/bot.py +++ b/bot.py @@ -16,11 +16,11 @@ async def main(): - lobby_database.create_table() - users_without_lobbies_database.create_table() + await lobby_database.create_table() + await users_without_lobbies_database.create_table() for i in range(-1, 5): - lobby_database.reset_lobby(i) - lobby_database.default_lobby(i) + await lobby_database.reset_lobby(i) + await lobby_database.default_lobby(i) logging.basicConfig(level=logging.INFO, format='%(filename)s:%(lineno)d #%(levelname)-8s ' '[%(asctime)s] - %(name)s - %(message)s') diff --git a/data/sql_database.py b/data/sql_database.py index 029ceb0..7baa252 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -7,7 +7,7 @@ class LobbyDatabase: def __init__(self, name): self.name = name - def create_table(self): + async def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} (lobby_id INT PRIMARY KEY, @@ -17,7 +17,7 @@ def create_table(self): cur.close() print('[INFO] TABLE CREATED SUCCESSFULLY') - def default_lobby(self, lobby_id: int): + async def default_lobby(self, lobby_id: int): cur = conn.cursor() cur.execute(f"""INSERT OR IGNORE INTO {self.name} (lobby_id, users) VALUES ({lobby_id}, ''); @@ -25,7 +25,7 @@ def default_lobby(self, lobby_id: int): conn.commit() cur.close() - def enter_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): + async def enter_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} WHERE lobby_id={lobby_id}; @@ -36,7 +36,7 @@ def enter_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): conn.commit() cur.close() - def exit_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): + async def exit_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} WHERE lobby_id={lobby_id}; @@ -47,7 +47,7 @@ def exit_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): conn.commit() cur.close() - def reset_lobby(self, lobby_id: int): + async def reset_lobby(self, lobby_id: int): cur = conn.cursor() cur.execute(f"""UPDATE {self.name} SET users='' WHERE lobby_id={lobby_id};""") conn.commit() @@ -67,7 +67,7 @@ class UsersWithoutLobbiesDatabase: def __init__(self, name): self.name = name - def create_table(self): + async def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} (chat_id INT PRIMARY KEY, @@ -76,20 +76,16 @@ def create_table(self): cur.close() print('[INFO] TABLE CREATED SUCCESSFULLY') - def insert_users_message_id(self, chat_id, message_id): + async def insert_users_message_id(self, chat_id, message_id): cur = conn.cursor() - cur.execute(f"""INSERT OR IGNORE INTO {self.name} (chat_id, message_id) - VALUES ({chat_id}, {message_id}); + cur.execute(f"""INSERT INTO {self.name} (chat_id, message_id) + VALUES ({chat_id}, {message_id}) + ON CONFLICT(chat_id) + DO UPDATE SET message_id={message_id}; """) conn.commit() cur.close() - def update_users_message_id(self, chat_id, message_id): - cur = conn.cursor() - cur.execute(f"""UPDATE {self.name} SET message_id='{message_id}' WHERE chat_id={chat_id};""") - conn.commit() - cur.close() - def get_statistic_of_users(self): cur = conn.cursor() cur.execute(f"""SELECT chat_id, message_id FROM {self.name}""") @@ -98,8 +94,8 @@ def get_statistic_of_users(self): cur.close() return stat - def delete_chat_id(self, chat_id): + async def delete_chat_id(self, chat_id): cur = conn.cursor() cur.execute(f"""DELETE FROM {self.name} WHERE chat_id={chat_id};""") conn.commit() - cur.close() \ No newline at end of file + cur.close() diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index 6414aa1..bb4626e 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -1,7 +1,7 @@ from aiogram import Router from aiogram.exceptions import TelegramBadRequest from aiogram.filters import Command, StateFilter -from aiogram.types import Message, CallbackQuery +from aiogram.types import Message, CallbackQuery, ReplyKeyboardRemove from bot import bot from data.sql_database import LobbyDatabase, UsersWithoutLobbiesDatabase @@ -18,35 +18,72 @@ @router.message(Command(commands='start')) async def start(message: Message, state: FSMContext): + data = await state.get_data() + if data.get('lobby'): + await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), + user_name=message.from_user.full_name) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + await send_messages_to_users(bot=bot, message=f'{message.from_user.full_name} Вышел из лобби', users=lobby_stat) + lobby_pages = create_lobbies_page() + keyboard = create_inline_kb(width=2, dct=lobby_pages) + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + for chat_id, message_id in people_without_lobby: + try: + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) + except TelegramBadRequest: + pass + await state.set_state(default_state) await message.answer(text='Это тренировочный бот для игры в ... с другими людьми.\nДля начала выберите лобби,' ' использовав команду /lobbies') - users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, message_id=message.message_id) - await state.set_state(default_state) -@router.message(Command(commands='lobbies'), StateFilter(default_state)) +@router.message(Command(commands='lobbies')) async def lobbies(message: Message, state: FSMContext): lobby_pages = create_lobbies_page() keyboards = create_inline_kb(2, dct=lobby_pages) bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboards) await state.set_state(FSMLobbyClass.select_lobby) - users_without_lobbies_database.update_users_message_id(chat_id=message.chat.id, message_id=bot_message.message_id) + await users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, + message_id=bot_message.message_id) + data = await state.get_data() + if data.get('lobby'): + await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), + user_name=message.from_user.full_name) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + await send_messages_to_users(bot=bot, message=f'{message.from_user.full_name} Вышел из лобби', users=lobby_stat) + lobby_pages = create_lobbies_page() + keyboard = create_inline_kb(width=2, dct=lobby_pages) + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + for chat_id, message_id in people_without_lobby: + try: + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) + except TelegramBadRequest: + pass @router.callback_query(LobbyCallbackFactory.filter(), StateFilter(FSMLobbyClass.select_lobby)) async def lobby_page(callback: CallbackQuery, callback_data: LobbyCallbackFactory, state: FSMContext): - lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) - if len(lobby_stat) < 4: + lobby_stat_1 = lobby_database.get_lobby_stat(callback_data.lobby_id) + if len(lobby_stat_1) < 4: await state.set_state(FSMLobbyClass.in_lobby) - lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id), - user_name=callback.from_user.full_name) - users_without_lobbies_database.delete_chat_id(chat_id=callback.message.chat.id) - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + await lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id), + user_name=callback.from_user.full_name) lobby_pages = create_lobbies_page() keyboard = create_inline_kb(width=2, dct=lobby_pages) + lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) + await callback.message.edit_text(text=f'Вы вошли в лобби №{callback_data.lobby_id}!\n\n' + f'Участники:\n' + f'{get_lobby_members(lobby_stat)}\n\n' + f'Информация о лобби - /info\n' + f'Выйти - /exit', + reply_markup=None) + await users_without_lobbies_database.delete_chat_id(chat_id=callback.message.chat.id) + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() for chat_id, message_id in people_without_lobby: try: await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, @@ -54,14 +91,7 @@ async def lobby_page(callback: CallbackQuery, except TelegramBadRequest: pass await state.update_data(lobby=callback_data.lobby_id) - await send_messages_to_users(bot=bot, message=f'{callback.from_user.full_name} зашел в лобби', users=lobby_stat) - await callback.message.delete() - lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) - await callback.message.answer(text=f'Вы вошли в лобби №{callback_data.lobby_id}!\n\n' - f'Участники:\n' - f'{get_lobby_members(lobby_stat)}\n\n' - f'Информация о лобби - /info\n' - f'Выйти - /exit') + await send_messages_to_users(bot=bot, message=f'{callback.from_user.full_name} зашел в лобби', users=lobby_stat_1) else: await callback.answer('Лобби заполнено') @@ -70,23 +100,23 @@ async def lobby_page(callback: CallbackQuery, async def exit_command(message: Message, state: FSMContext): data = await state.get_data() - await state.clear() - lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), - user_name=message.from_user.full_name) - lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - await send_messages_to_users(bot=bot, message=f'{message.from_user.full_name} Вышел из лобби', users=lobby_stat) + await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), + user_name=message.from_user.full_name) lobby_pages = create_lobbies_page() - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() keyboard = create_inline_kb(width=2, dct=lobby_pages) + bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboard) + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + await state.clear() + await state.set_state(FSMLobbyClass.select_lobby) + await users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, message_id=bot_message.message_id) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) for chat_id, message_id in people_without_lobby: try: await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: pass - await state.set_state(FSMLobbyClass.select_lobby) - bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboard) - users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, message_id=bot_message.message_id) + await send_messages_to_users(bot=bot, message=f'{message.from_user.full_name} Вышел из лобби', users=lobby_stat) @router.message(Command(commands='info'), StateFilter(FSMLobbyClass.in_lobby)) @@ -101,20 +131,10 @@ async def info_command(message: Message, @router.message(StateFilter(FSMLobbyClass.in_lobby)) -async def others(message: Message, - state: FSMContext): +async def ready_command_others(message: Message, + state: FSMContext): data = await state.get_data() - people = lobby_database.get_lobby_stat(data['lobby']) + people = await lobby_database.get_lobby_stat(data['lobby']) for i in people: if int(i.split('-')[0]) != message.chat.id: - await bot.send_message(chat_id=int(i), text=f"""{message.from_user.full_name}: {message.text}""") - - -@router.message(Command(commands='test')) -async def test(message: Message): - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() - lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(2, dct=lobby_pages) - for chat_id, message_id in people_without_lobby: - await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, - reply_markup=keyboard) + await bot.send_message(chat_id=int(i.split('-')[0]), text=f"""{message.from_user.full_name}: {message.text}""") diff --git a/lexicon/lexicon.py b/lexicon/lexicon.py index beeb3d5..db6734f 100644 --- a/lexicon/lexicon.py +++ b/lexicon/lexicon.py @@ -1,6 +1,8 @@ lexicon_commands: dict[str, str] = { '/start': 'Запуск или обновление', - '/lobbies': 'Все лобби' + '/lobbies': 'Все лобби', + '/info': 'Информация о лобби', + '/exit': 'Выйти из лобби' } keyboard_lexicon = {} From 03817e40af9c335b921e86186344f558a4251984 Mon Sep 17 00:00:00 2001 From: ilyak Date: Wed, 3 Jan 2024 01:09:48 +0500 Subject: [PATCH 04/14] 1 --- bot.py | 9 ++-- data/sql_database.py | 42 ++++++++++----- handlers/user_handlers.py | 109 +++++++++++++++++++++++++++++--------- lexicon/lexicon.py | 2 +- services/services.py | 13 ++++- 5 files changed, 131 insertions(+), 44 deletions(-) diff --git a/bot.py b/bot.py index 6eb44f5..622c052 100644 --- a/bot.py +++ b/bot.py @@ -18,9 +18,12 @@ async def main(): await lobby_database.create_table() await users_without_lobbies_database.create_table() - for i in range(-1, 5): - await lobby_database.reset_lobby(i) - await lobby_database.default_lobby(i) + lobbies_id = lobby_database.get_all_lobby_stat() + users_without_lobby = users_without_lobbies_database.get_statistic_of_users() + for i in lobbies_id: + await lobby_database.reset_lobby(lobby_id=i[0]) + for i in users_without_lobby: + await users_without_lobbies_database.delete_chat_id(i[0]) logging.basicConfig(level=logging.INFO, format='%(filename)s:%(lineno)d #%(levelname)-8s ' '[%(asctime)s] - %(name)s - %(message)s') diff --git a/data/sql_database.py b/data/sql_database.py index 7baa252..f459e4a 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -17,51 +17,65 @@ async def create_table(self): cur.close() print('[INFO] TABLE CREATED SUCCESSFULLY') - async def default_lobby(self, lobby_id: int): - cur = conn.cursor() - cur.execute(f"""INSERT OR IGNORE INTO {self.name} (lobby_id, users) - VALUES ({lobby_id}, ''); - """) - conn.commit() - cur.close() - async def enter_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} - WHERE lobby_id={lobby_id}; + WHERE rowid={lobby_id}; """) pairs = cur.fetchone()[0].split() pairs.append(f"""{user_chat_id}-{user_name}""") - cur.execute(f"""UPDATE {self.name} SET users='{' '.join(pairs)}' WHERE lobby_id={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET users='{' '.join(pairs)}' WHERE rowid={lobby_id};""") conn.commit() cur.close() async def exit_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} - WHERE lobby_id={lobby_id}; + WHERE rowid={lobby_id}; """) pairs = cur.fetchone()[0].split() pairs.remove(f"""{user_chat_id}-{user_name}""") - cur.execute(f"""UPDATE {self.name} SET users='{' '.join(pairs)}' WHERE lobby_id={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET users='{' '.join(pairs)}' WHERE rowid={lobby_id};""") conn.commit() cur.close() async def reset_lobby(self, lobby_id: int): cur = conn.cursor() - cur.execute(f"""UPDATE {self.name} SET users='' WHERE lobby_id={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET users='' WHERE rowid={lobby_id};""") conn.commit() cur.close() def get_lobby_stat(self, lobby_id: int): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} - WHERE lobby_id={lobby_id};""") + WHERE rowid={lobby_id};""") s = cur.fetchone()[0].split() conn.commit() cur.close() return s + def create_new_lobby(self, user_chat_id: str, user_name: str): + cur = conn.cursor() + cur.execute(f"""INSERT INTO {self.name} VALUES (NULL, '{user_chat_id}-{user_name}')""") + cur.execute(f"""SELECT rowid FROM {self.name} + WHERE users='{user_chat_id}-{user_name}';""") + lobby_id = cur.fetchone()[0] + conn.commit() + cur.close() + return lobby_id + + def get_all_lobby_stat(self): + cur = conn.cursor() + cur.execute(f"""SELECT rowid, users FROM {self.name}""") + all_lobby_stat = cur.fetchall() + return all_lobby_stat + + def delete_lobby(self, lobby_id: int): + cur = conn.cursor() + cur.execute(f"""DELETE FROM {self.name} WHERE rowid={lobby_id};""") + conn.commit() + cur.close() + class UsersWithoutLobbiesDatabase: def __init__(self, name): diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index bb4626e..a496615 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -1,8 +1,8 @@ -from aiogram import Router +from aiogram import Router, F from aiogram.exceptions import TelegramBadRequest from aiogram.filters import Command, StateFilter -from aiogram.types import Message, CallbackQuery, ReplyKeyboardRemove - +from aiogram.types import Message, CallbackQuery +import locale from bot import bot from data.sql_database import LobbyDatabase, UsersWithoutLobbiesDatabase from keyboards.keyboards import create_inline_kb, LobbyCallbackFactory @@ -13,6 +13,7 @@ router = Router() lobby_database = LobbyDatabase('test6') users_without_lobbies_database = UsersWithoutLobbiesDatabase('test5') +locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8') @router.message(Command(commands='start')) @@ -20,10 +21,20 @@ async def start(message: Message, state: FSMContext): data = await state.get_data() if data.get('lobby'): + await state.update_data(lobby=None) await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), user_name=message.from_user.full_name) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - await send_messages_to_users(bot=bot, message=f'{message.from_user.full_name} Вышел из лобби', users=lobby_stat) + if not len(lobby_stat): + lobby_database.delete_lobby(data['lobby']) + else: + await send_messages_to_users(bot=bot, + message=f'{message.from_user.full_name} вышел из лобби\n\n' + f'Текущие участники:\n' + f'{get_lobby_members(lobby_stat)}\n\n' + f'Информация о лобби - /info\n' + f'Выйти - /exit', + users=lobby_stat) lobby_pages = create_lobbies_page() keyboard = create_inline_kb(width=2, dct=lobby_pages) people_without_lobby = users_without_lobbies_database.get_statistic_of_users() @@ -38,30 +49,40 @@ async def start(message: Message, ' использовав команду /lobbies') -@router.message(Command(commands='lobbies')) +@router.message(Command(commands='lobbies'), ~StateFilter(FSMLobbyClass.select_lobby)) async def lobbies(message: Message, state: FSMContext): - lobby_pages = create_lobbies_page() - keyboards = create_inline_kb(2, dct=lobby_pages) - bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboards) await state.set_state(FSMLobbyClass.select_lobby) - await users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, - message_id=bot_message.message_id) data = await state.get_data() + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() if data.get('lobby'): + await state.update_data(lobby=None) await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), user_name=message.from_user.full_name) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - await send_messages_to_users(bot=bot, message=f'{message.from_user.full_name} Вышел из лобби', users=lobby_stat) + if not len(lobby_stat): + lobby_database.delete_lobby(data['lobby']) + else: + await send_messages_to_users(bot=bot, + message=f'{message.from_user.full_name} вышел из лобби\n\n' + f'Текущие участники:\n' + f'{get_lobby_members(lobby_stat)}\n\n' + f'Информация о лобби - /info\n' + f'Выйти - /exit', + users=lobby_stat) lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(width=2, dct=lobby_pages) - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') for chat_id, message_id in people_without_lobby: try: await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: pass + lobby_pages = create_lobbies_page() + keyboards = create_inline_kb(2, dct=lobby_pages, last_btn='create_new_lobby') + bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboards) + await users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, + message_id=bot_message.message_id) @router.callback_query(LobbyCallbackFactory.filter(), StateFilter(FSMLobbyClass.select_lobby)) @@ -76,7 +97,7 @@ async def lobby_page(callback: CallbackQuery, lobby_pages = create_lobbies_page() keyboard = create_inline_kb(width=2, dct=lobby_pages) lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) - await callback.message.edit_text(text=f'Вы вошли в лобби №{callback_data.lobby_id}!\n\n' + await callback.message.edit_text(text=f'Вы вошли в лобби!\n\n' f'Участники:\n' f'{get_lobby_members(lobby_stat)}\n\n' f'Информация о лобби - /info\n' @@ -91,7 +112,13 @@ async def lobby_page(callback: CallbackQuery, except TelegramBadRequest: pass await state.update_data(lobby=callback_data.lobby_id) - await send_messages_to_users(bot=bot, message=f'{callback.from_user.full_name} зашел в лобби', users=lobby_stat_1) + await send_messages_to_users(bot=bot, + message=f'{callback.from_user.full_name} зашел в лобби\n\n' + f'Текущие участники:\n' + f'{get_lobby_members(lobby_stat)}\n\n' + f'Информация о лобби - /info\n' + f'Выйти - /exit', + users=lobby_stat_1) else: await callback.answer('Лобби заполнено') @@ -100,23 +127,34 @@ async def lobby_page(callback: CallbackQuery, async def exit_command(message: Message, state: FSMContext): data = await state.get_data() + print(data) await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), user_name=message.from_user.full_name) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + if not len(lobby_stat): + lobby_database.delete_lobby(data['lobby']) + else: + await send_messages_to_users(bot=bot, + message=f'{message.from_user.full_name} вышел из лобби\n\n' + f'Текущие участники:\n' + f'{get_lobby_members(lobby_stat)}\n\n' + f'Информация о лобби - /info\n' + f'Выйти - /exit', + users=lobby_stat) lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(width=2, dct=lobby_pages) + keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboard) people_without_lobby = users_without_lobbies_database.get_statistic_of_users() - await state.clear() + await state.update_data(lobby=None) await state.set_state(FSMLobbyClass.select_lobby) - await users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, message_id=bot_message.message_id) - lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + await users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, + message_id=bot_message.message_id) for chat_id, message_id in people_without_lobby: try: await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: pass - await send_messages_to_users(bot=bot, message=f'{message.from_user.full_name} Вышел из лобби', users=lobby_stat) @router.message(Command(commands='info'), StateFilter(FSMLobbyClass.in_lobby)) @@ -124,8 +162,7 @@ async def info_command(message: Message, state: FSMContext): data = await state.get_data() lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - await message.answer(text=f'Лобби №{data["lobby"]}\n\n' - f'Участники:\n' + await message.answer(text=f'Участники:\n' f'{get_lobby_members(lobby_stat)}\n\n' f'Выйти - /exit') @@ -134,7 +171,31 @@ async def info_command(message: Message, async def ready_command_others(message: Message, state: FSMContext): data = await state.get_data() - people = await lobby_database.get_lobby_stat(data['lobby']) + people = lobby_database.get_lobby_stat(data['lobby']) for i in people: if int(i.split('-')[0]) != message.chat.id: - await bot.send_message(chat_id=int(i.split('-')[0]), text=f"""{message.from_user.full_name}: {message.text}""") + await bot.send_message(chat_id=int(i.split('-')[0]), + text=f"""{message.from_user.full_name}: {message.text}""") + + +@router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) +async def create_new_lobby(callback: CallbackQuery, + state: FSMContext): + lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id), + user_name=callback.from_user.full_name) + await state.set_state(FSMLobbyClass.in_lobby) + await state.update_data(lobby=lobby_id) + await callback.message.edit_text(text='Вы создали новое лобби!\n\n' + 'Информация о лобби - /info\n' + 'Выйти - /exit') + await users_without_lobbies_database.delete_chat_id(chat_id=callback.message.chat.id) + people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + if people_without_lobby: + lobby_pages = create_lobbies_page() + keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') + for chat_id, message_id in people_without_lobby: + try: + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) + except TelegramBadRequest: + pass diff --git a/lexicon/lexicon.py b/lexicon/lexicon.py index db6734f..dfe3d55 100644 --- a/lexicon/lexicon.py +++ b/lexicon/lexicon.py @@ -5,4 +5,4 @@ '/exit': 'Выйти из лобби' } -keyboard_lexicon = {} +keyboard_lexicon = {'create_new_lobby': 'Новое лобби'} diff --git a/services/services.py b/services/services.py index 9796d14..740531e 100644 --- a/services/services.py +++ b/services/services.py @@ -13,9 +13,18 @@ class FSMLobbyClass(StatesGroup): lobby = State() +def create_lobby_short_name(users): + names = list(map(lambda x: x.split('-')[1], users)) + lobby_short_name = ', '.join(names) + lobby_short_name.strip(', ') + return lobby_short_name[:10]+'...' if len(lobby_short_name) < 10 else lobby_short_name + + def create_lobbies_page(): - return {LobbyCallbackFactory(lobby_id=i).pack(): f'Лобби №{i} {len(lobby_database.get_lobby_stat(i))}/4' - for i in range(1, 5)} + all_lobby_stat = lobby_database.get_all_lobby_stat() + return {LobbyCallbackFactory(lobby_id=lobby[0]).pack(): + f"""{create_lobby_short_name(lobby[1].split())} {len(lobby[1].split())}/4""" + for lobby in all_lobby_stat if lobby[1]} async def send_messages_to_users(bot: Bot, message: str, users: list): From fedefabe619b566f052e31320b5f0b2a08c96118 Mon Sep 17 00:00:00 2001 From: ilyak Date: Thu, 4 Jan 2024 02:45:09 +0500 Subject: [PATCH 05/14] 1 --- bot.py | 2 +- data/sql_database.py | 13 +++--- handlers/user_handlers.py | 98 ++++++++++++++++++++++++++++++++------- lexicon/lexicon.py | 3 +- services/services.py | 6 ++- 5 files changed, 94 insertions(+), 28 deletions(-) diff --git a/bot.py b/bot.py index 622c052..746add3 100644 --- a/bot.py +++ b/bot.py @@ -21,7 +21,7 @@ async def main(): lobbies_id = lobby_database.get_all_lobby_stat() users_without_lobby = users_without_lobbies_database.get_statistic_of_users() for i in lobbies_id: - await lobby_database.reset_lobby(lobby_id=i[0]) + await lobby_database.delete_lobby(lobby_id=i[0]) for i in users_without_lobby: await users_without_lobbies_database.delete_chat_id(i[0]) logging.basicConfig(level=logging.INFO, diff --git a/data/sql_database.py b/data/sql_database.py index f459e4a..b1795af 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -22,9 +22,9 @@ async def enter_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): cur.execute(f"""SELECT users FROM {self.name} WHERE rowid={lobby_id}; """) - pairs = cur.fetchone()[0].split() + pairs = cur.fetchone()[0].split('~~~') pairs.append(f"""{user_chat_id}-{user_name}""") - cur.execute(f"""UPDATE {self.name} SET users='{' '.join(pairs)}' WHERE rowid={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(pairs)}' WHERE rowid={lobby_id};""") conn.commit() cur.close() @@ -33,9 +33,9 @@ async def exit_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): cur.execute(f"""SELECT users FROM {self.name} WHERE rowid={lobby_id}; """) - pairs = cur.fetchone()[0].split() + pairs = cur.fetchone()[0].split('~~~') pairs.remove(f"""{user_chat_id}-{user_name}""") - cur.execute(f"""UPDATE {self.name} SET users='{' '.join(pairs)}' WHERE rowid={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(pairs)}' WHERE rowid={lobby_id};""") conn.commit() cur.close() @@ -49,13 +49,14 @@ def get_lobby_stat(self, lobby_id: int): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} WHERE rowid={lobby_id};""") - s = cur.fetchone()[0].split() + s = cur.fetchone()[0].split('~~~') conn.commit() cur.close() return s def create_new_lobby(self, user_chat_id: str, user_name: str): cur = conn.cursor() + print(f'{user_chat_id}-{user_name}') cur.execute(f"""INSERT INTO {self.name} VALUES (NULL, '{user_chat_id}-{user_name}')""") cur.execute(f"""SELECT rowid FROM {self.name} WHERE users='{user_chat_id}-{user_name}';""") @@ -70,7 +71,7 @@ def get_all_lobby_stat(self): all_lobby_stat = cur.fetchall() return all_lobby_stat - def delete_lobby(self, lobby_id: int): + async def delete_lobby(self, lobby_id: int): cur = conn.cursor() cur.execute(f"""DELETE FROM {self.name} WHERE rowid={lobby_id};""") conn.commit() diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index a496615..ebf0925 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -8,6 +8,7 @@ from keyboards.keyboards import create_inline_kb, LobbyCallbackFactory from aiogram.fsm.context import FSMContext from aiogram.fsm.state import default_state +from aiogram.fsm.storage.base import StorageKey from services.services import FSMLobbyClass, create_lobbies_page, send_messages_to_users, get_lobby_members router = Router() @@ -26,12 +27,13 @@ async def start(message: Message, user_name=message.from_user.full_name) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) if not len(lobby_stat): - lobby_database.delete_lobby(data['lobby']) + await lobby_database.delete_lobby(data['lobby']) else: await send_messages_to_users(bot=bot, - message=f'{message.from_user.full_name} вышел из лобби\n\n' + message=f'{message.from_user.full_name} вышел(-а) из лобби\n\n' f'Текущие участники:\n' f'{get_lobby_members(lobby_stat)}\n\n' + f'Приготовиться - /ready\n' f'Информация о лобби - /info\n' f'Выйти - /exit', users=lobby_stat) @@ -61,12 +63,13 @@ async def lobbies(message: Message, user_name=message.from_user.full_name) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) if not len(lobby_stat): - lobby_database.delete_lobby(data['lobby']) + await lobby_database.delete_lobby(data['lobby']) else: await send_messages_to_users(bot=bot, - message=f'{message.from_user.full_name} вышел из лобби\n\n' + message=f'{message.from_user.full_name} вышел(-a) из лобби\n\n' f'Текущие участники:\n' f'{get_lobby_members(lobby_stat)}\n\n' + f'Приготовиться - /ready\n' f'Информация о лобби - /info\n' f'Выйти - /exit', users=lobby_stat) @@ -91,15 +94,17 @@ async def lobby_page(callback: CallbackQuery, state: FSMContext): lobby_stat_1 = lobby_database.get_lobby_stat(callback_data.lobby_id) if len(lobby_stat_1) < 4: + await state.update_data(lobby=callback_data.lobby_id, ready=0) await state.set_state(FSMLobbyClass.in_lobby) await lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id), user_name=callback.from_user.full_name) lobby_pages = create_lobbies_page() keyboard = create_inline_kb(width=2, dct=lobby_pages) lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) - await callback.message.edit_text(text=f'Вы вошли в лобби!\n\n' + await callback.message.edit_text(text=f'Вы вошли(-а) в лобби!\n\n' f'Участники:\n' f'{get_lobby_members(lobby_stat)}\n\n' + f'Приготовиться - /ready\n' f'Информация о лобби - /info\n' f'Выйти - /exit', reply_markup=None) @@ -111,11 +116,12 @@ async def lobby_page(callback: CallbackQuery, reply_markup=keyboard) except TelegramBadRequest: pass - await state.update_data(lobby=callback_data.lobby_id) + await send_messages_to_users(bot=bot, - message=f'{callback.from_user.full_name} зашел в лобби\n\n' + message=f'{callback.from_user.full_name} зашел(-а) в лобби\n\n' f'Текущие участники:\n' f'{get_lobby_members(lobby_stat)}\n\n' + f'Приготовиться - /ready\n' f'Информация о лобби - /info\n' f'Выйти - /exit', users=lobby_stat_1) @@ -127,17 +133,17 @@ async def lobby_page(callback: CallbackQuery, async def exit_command(message: Message, state: FSMContext): data = await state.get_data() - print(data) await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), user_name=message.from_user.full_name) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - if not len(lobby_stat): - lobby_database.delete_lobby(data['lobby']) + if not len(lobby_stat[0]): + await lobby_database.delete_lobby(data['lobby']) else: await send_messages_to_users(bot=bot, - message=f'{message.from_user.full_name} вышел из лобби\n\n' + message=f'{message.from_user.full_name} вышел(-а) из лобби\n\n' f'Текущие участники:\n' f'{get_lobby_members(lobby_stat)}\n\n' + f'Приготовиться - /ready\n' f'Информация о лобби - /info\n' f'Выйти - /exit', users=lobby_stat) @@ -164,18 +170,66 @@ async def info_command(message: Message, lobby_stat = lobby_database.get_lobby_stat(data['lobby']) await message.answer(text=f'Участники:\n' f'{get_lobby_members(lobby_stat)}\n\n' + f'Приготовиться - /ready\n' f'Выйти - /exit') -@router.message(StateFilter(FSMLobbyClass.in_lobby)) +@router.message(Command(commands='ready'), StateFilter(FSMLobbyClass.in_lobby)) async def ready_command_others(message: Message, state: FSMContext): + storage = state.storage data = await state.get_data() - people = lobby_database.get_lobby_stat(data['lobby']) - for i in people: - if int(i.split('-')[0]) != message.chat.id: - await bot.send_message(chat_id=int(i.split('-')[0]), - text=f"""{message.from_user.full_name}: {message.text}""") + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=message.chat.id, + user_id=message.chat.id)) + print(storage_data) + if not storage_data['ready']: + storage_data['ready'] = 1 + await storage.update_data(StorageKey(bot_id=bot.id, + chat_id=message.chat.id, + user_id=message.chat.id), data=storage_data) + users_unready = [] + users_unready_counter = 0 + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + answer_for_other_text = f'{message.from_user.full_name} готов к игре!\n\n' + other_text = '' + for pair in lobby_stat: + print(pair) + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(pair.split('-')[0]), + user_id=int(pair.split('-')[0]))) + print(storage_data) + if storage_data['ready']: + users_unready.append(f'{pair.split("-")[1]} - готов') + else: + users_unready_counter += 1 + users_unready.append(f'{pair.split("-")[1]} - не готов') + if users_unready_counter == 0: + if len(lobby_stat) == 2: + other_text += ('Все игроки готовы! Игра начинается!\n\n' + 'Информация о лобби - /info\n' + 'Выйти - /exit') + for pair in lobby_stat: + await storage.set_state(StorageKey(bot_id=bot.id, + chat_id=int(pair.split('-')[0]), + user_id=int(pair.split('-')[0])), state=FSMLobbyClass.in_game) + + else: + other_text += '\n'.join(users_unready) + other_text += ('\n\nОжидаем других игроков\n\n' + 'Информация о лобби - /info\n' + 'Выйти - /exit') + else: + other_text += '\n'.join(users_unready) + other_text += ('\n\nОжидаем других игроков\n\n' + 'Информация о лобби - /info\n' + 'Выйти - /exit') + await message.answer(text='Вы приготовились!\n\n'+other_text) + for pair in lobby_stat: + if pair.split('-')[0] != str(message.chat.id): + await bot.send_message(chat_id=pair.split('-')[0], text=answer_for_other_text+other_text) + else: + await message.answer(text='Вы уже готовы!') @router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) @@ -184,8 +238,9 @@ async def create_new_lobby(callback: CallbackQuery, lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id), user_name=callback.from_user.full_name) await state.set_state(FSMLobbyClass.in_lobby) - await state.update_data(lobby=lobby_id) + await state.update_data(lobby=lobby_id, ready=0) await callback.message.edit_text(text='Вы создали новое лобби!\n\n' + 'Приготовиться - /ready\n' 'Информация о лобби - /info\n' 'Выйти - /exit') await users_without_lobbies_database.delete_chat_id(chat_id=callback.message.chat.id) @@ -199,3 +254,10 @@ async def create_new_lobby(callback: CallbackQuery, reply_markup=keyboard) except TelegramBadRequest: pass + print(lobby_database.get_lobby_stat(lobby_id=lobby_id)) + + +@router.message(StateFilter(FSMLobbyClass.in_game)) +async def game(message: Message, + state: FSMContext): + await message.answer(text='Вы играити, ура') diff --git a/lexicon/lexicon.py b/lexicon/lexicon.py index dfe3d55..55450c2 100644 --- a/lexicon/lexicon.py +++ b/lexicon/lexicon.py @@ -2,7 +2,8 @@ '/start': 'Запуск или обновление', '/lobbies': 'Все лобби', '/info': 'Информация о лобби', - '/exit': 'Выйти из лобби' + '/exit': 'Выйти из лобби', + '/ready': 'Приготовиться к игре' } keyboard_lexicon = {'create_new_lobby': 'Новое лобби'} diff --git a/services/services.py b/services/services.py index 740531e..2ac7098 100644 --- a/services/services.py +++ b/services/services.py @@ -9,7 +9,9 @@ class FSMLobbyClass(StatesGroup): in_lobby = State() + in_game = State() select_lobby = State() + ready = State() lobby = State() @@ -17,13 +19,13 @@ def create_lobby_short_name(users): names = list(map(lambda x: x.split('-')[1], users)) lobby_short_name = ', '.join(names) lobby_short_name.strip(', ') - return lobby_short_name[:10]+'...' if len(lobby_short_name) < 10 else lobby_short_name + return lobby_short_name[:10]+'...' if len(lobby_short_name) > 12 else lobby_short_name def create_lobbies_page(): all_lobby_stat = lobby_database.get_all_lobby_stat() return {LobbyCallbackFactory(lobby_id=lobby[0]).pack(): - f"""{create_lobby_short_name(lobby[1].split())} {len(lobby[1].split())}/4""" + f"""{create_lobby_short_name(lobby[1].split('~~~'))} {len(lobby[1].split('~~~'))}/4""" for lobby in all_lobby_stat if lobby[1]} From 0d27fa9f9ffe03f21ada1e57997e332dfdc25579 Mon Sep 17 00:00:00 2001 From: ilyak Date: Thu, 4 Jan 2024 23:12:25 +0500 Subject: [PATCH 06/14] 1 --- data/sql_database.py | 22 ++++++++++++++--- handlers/user_handlers.py | 51 ++++++++++++++++++++++++++++----------- lexicon/lexicon.py | 4 +++ services/services.py | 17 +++++++++++++ 4 files changed, 76 insertions(+), 18 deletions(-) diff --git a/data/sql_database.py b/data/sql_database.py index b1795af..0d7e1b6 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -11,7 +11,8 @@ async def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} (lobby_id INT PRIMARY KEY, - users TEXT); + users TEXT, + deck TEXT); """) conn.commit() cur.close() @@ -54,10 +55,9 @@ def get_lobby_stat(self, lobby_id: int): cur.close() return s - def create_new_lobby(self, user_chat_id: str, user_name: str): + def create_new_lobby(self, user_chat_id: str, user_name: str, deck: str): cur = conn.cursor() - print(f'{user_chat_id}-{user_name}') - cur.execute(f"""INSERT INTO {self.name} VALUES (NULL, '{user_chat_id}-{user_name}')""") + cur.execute(f"""INSERT INTO {self.name} VALUES (NULL, '{user_chat_id}-{user_name}', '{deck}')""") cur.execute(f"""SELECT rowid FROM {self.name} WHERE users='{user_chat_id}-{user_name}';""") lobby_id = cur.fetchone()[0] @@ -77,6 +77,20 @@ async def delete_lobby(self, lobby_id: int): conn.commit() cur.close() + def get_lobby_deck(self, lobby_id): + cur = conn.cursor() + cur.execute(f"""SELECT deck FROM {self.name} WHERE rowid={lobby_id}""") + deck = cur.fetchone()[0] + conn.commit() + cur.close() + return deck + + async def update_deck(self, deck, lobby_id): + cur = conn.cursor() + cur.execute(f"""UPDATE {self.name} SET deck='{deck}' WHERE rowid={lobby_id};""") + conn.commit() + cur.close() + class UsersWithoutLobbiesDatabase: def __init__(self, name): diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index ebf0925..a1af01c 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -9,7 +9,9 @@ from aiogram.fsm.context import FSMContext from aiogram.fsm.state import default_state from aiogram.fsm.storage.base import StorageKey -from services.services import FSMLobbyClass, create_lobbies_page, send_messages_to_users, get_lobby_members +from services.services import (FSMLobbyClass, create_lobbies_page, send_messages_to_users, + get_lobby_members, create_deck, get_next_cards) +from lexicon.lexicon import lexicon_card_colors, lexicon_card_faces router = Router() lobby_database = LobbyDatabase('test6') @@ -184,7 +186,12 @@ async def ready_command_others(message: Message, user_id=message.chat.id)) print(storage_data) if not storage_data['ready']: + deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']) + cards = get_next_cards(deck=deck, cards_num=6) storage_data['ready'] = 1 + storage_data['current_cards'] = cards[0] + deck = '~~~'.join(cards[1]) + await lobby_database.update_deck(deck=deck, lobby_id=data['lobby']) await storage.update_data(StorageKey(bot_id=bot.id, chat_id=message.chat.id, user_id=message.chat.id), data=storage_data) @@ -193,12 +200,14 @@ async def ready_command_others(message: Message, lobby_stat = lobby_database.get_lobby_stat(data['lobby']) answer_for_other_text = f'{message.from_user.full_name} готов к игре!\n\n' other_text = '' + user_cards = {} + info_text = '\n\nИнформация о лобби - /info\nВыйти - /exit' + print(storage_data) for pair in lobby_stat: print(pair) storage_data = await storage.get_data(StorageKey(bot_id=bot.id, chat_id=int(pair.split('-')[0]), user_id=int(pair.split('-')[0]))) - print(storage_data) if storage_data['ready']: users_unready.append(f'{pair.split("-")[1]} - готов') else: @@ -206,28 +215,41 @@ async def ready_command_others(message: Message, users_unready.append(f'{pair.split("-")[1]} - не готов') if users_unready_counter == 0: if len(lobby_stat) == 2: - other_text += ('Все игроки готовы! Игра начинается!\n\n' - 'Информация о лобби - /info\n' - 'Выйти - /exit') + other_text = 'Все игроки готовы! Игра начинается!\n\nВаши карты:\n' for pair in lobby_stat: await storage.set_state(StorageKey(bot_id=bot.id, chat_id=int(pair.split('-')[0]), user_id=int(pair.split('-')[0])), state=FSMLobbyClass.in_game) + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(pair.split('-')[0]), + user_id=int(pair.split('-')[0]))) + user_cards[int(pair.split('-')[0])] = sorted([x.replace('-', ' ') + for x in storage_data['current_cards']], + key=lambda x: (lexicon_card_colors[x.split()[1]], + lexicon_card_faces.get(x.split()[0], + x.split()[0]))) else: other_text += '\n'.join(users_unready) - other_text += ('\n\nОжидаем других игроков\n\n' - 'Информация о лобби - /info\n' - 'Выйти - /exit') + other_text += '\n\nОжидаем других игроков' else: other_text += '\n'.join(users_unready) - other_text += ('\n\nОжидаем других игроков\n\n' - 'Информация о лобби - /info\n' - 'Выйти - /exit') - await message.answer(text='Вы приготовились!\n\n'+other_text) + other_text += '\n\nОжидаем других игроков' for pair in lobby_stat: if pair.split('-')[0] != str(message.chat.id): - await bot.send_message(chat_id=pair.split('-')[0], text=answer_for_other_text+other_text) + if user_cards: + await bot.send_message(chat_id=pair.split('-')[0], + text=answer_for_other_text + other_text + '\n'.join(user_cards[ + int(pair.split('-')[0])]) + info_text) + else: + await bot.send_message(chat_id=pair.split('-')[0], + text=answer_for_other_text + other_text + info_text) + else: + if user_cards: + await message.answer(text='Вы приготовились!\n\n'+other_text+'\n'.join(user_cards[ + int(pair.split('-')[0])])+info_text) + else: + await message.answer(text='Вы приготовились!\n\n'+other_text+info_text) else: await message.answer(text='Вы уже готовы!') @@ -235,8 +257,9 @@ async def ready_command_others(message: Message, @router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) async def create_new_lobby(callback: CallbackQuery, state: FSMContext): + deck = create_deck() lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id), - user_name=callback.from_user.full_name) + user_name=callback.from_user.full_name, deck=deck) await state.set_state(FSMLobbyClass.in_lobby) await state.update_data(lobby=lobby_id, ready=0) await callback.message.edit_text(text='Вы создали новое лобби!\n\n' diff --git a/lexicon/lexicon.py b/lexicon/lexicon.py index 55450c2..70531c7 100644 --- a/lexicon/lexicon.py +++ b/lexicon/lexicon.py @@ -7,3 +7,7 @@ } keyboard_lexicon = {'create_new_lobby': 'Новое лобби'} + +lexicon_card_colors = {'♥️': 1, '♦️': 2, '♣️': 3, '♠️': 4} + +lexicon_card_faces = {'Валет': 11, 'Дама': 12, 'Король': 13, 'Туз': 14} diff --git a/services/services.py b/services/services.py index 2ac7098..188b351 100644 --- a/services/services.py +++ b/services/services.py @@ -13,6 +13,7 @@ class FSMLobbyClass(StatesGroup): select_lobby = State() ready = State() lobby = State() + current_cards = State() def create_lobby_short_name(users): @@ -37,3 +38,19 @@ async def send_messages_to_users(bot: Bot, message: str, users: list): def get_lobby_members(pairs: list): members = list(map(lambda x: x.split('-')[1], pairs)) return '\n'.join(members) + + +def create_deck(): + faces = list(range(6, 11)) + [faces.append(i) for i in ["Король", "Дама", "Валет", "Туз"]] + colour = ["♥️", "♦️", "♣️", "♠️"] + from itertools import product + from random import shuffle + deck = ["{}-{}".format(*card) for card in product(faces, colour)] + shuffle(deck) + return '~~~'.join(deck) + + +def get_next_cards(deck, cards_num): + deck = deck.split('~~~') + return [deck[:cards_num], deck[cards_num:]] From 8a6545b5794824821ea2512d72f45279b64f953e Mon Sep 17 00:00:00 2001 From: ilyak Date: Mon, 8 Jan 2024 15:28:50 +0500 Subject: [PATCH 07/14] 1 --- bot.py | 13 +- data/sql_database.py | 146 +++++++++--- handlers/user_handlers.py | 482 +++++++++++++++++++------------------- lexicon/lexicon.py | 11 +- services/services.py | 95 +++++++- 5 files changed, 451 insertions(+), 296 deletions(-) diff --git a/bot.py b/bot.py index 746add3..4e51949 100644 --- a/bot.py +++ b/bot.py @@ -2,14 +2,16 @@ import asyncio from aiogram import Bot, Dispatcher + from config.config import Config, load_config from handlers import user_handlers -from data.sql_database import LobbyDatabase, UsersWithoutLobbiesDatabase +from data.sql_database import LobbyDatabase, UsersDatabase from services.set_menu import set_main_menu + logger = logging.getLogger(__name__) lobby_database = LobbyDatabase('test6') -users_without_lobbies_database = UsersWithoutLobbiesDatabase('test5') +users_database = UsersDatabase('test5') config: Config = load_config() bot = Bot(token=config.tg_bot.token, parse_mode='HTML') @@ -17,13 +19,10 @@ async def main(): await lobby_database.create_table() - await users_without_lobbies_database.create_table() + await users_database.create_table() lobbies_id = lobby_database.get_all_lobby_stat() - users_without_lobby = users_without_lobbies_database.get_statistic_of_users() for i in lobbies_id: await lobby_database.delete_lobby(lobby_id=i[0]) - for i in users_without_lobby: - await users_without_lobbies_database.delete_chat_id(i[0]) logging.basicConfig(level=logging.INFO, format='%(filename)s:%(lineno)d #%(levelname)-8s ' '[%(asctime)s] - %(name)s - %(message)s') @@ -40,4 +39,4 @@ async def main(): if __name__ == '__main__': - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) diff --git a/data/sql_database.py b/data/sql_database.py index 0d7e1b6..bba5674 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -1,6 +1,6 @@ -import sqlite3 +import psycopg2 -conn = sqlite3.connect('test1.py') +conn = psycopg2.connect(host='localhost', dbname='postgres', user='postgres', password='1234', port=5432) class LobbyDatabase: @@ -10,7 +10,7 @@ def __init__(self, name): async def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} - (lobby_id INT PRIMARY KEY, + (lobby_id SERIAL PRIMARY KEY, users TEXT, deck TEXT); """) @@ -18,48 +18,42 @@ async def create_table(self): cur.close() print('[INFO] TABLE CREATED SUCCESSFULLY') - async def enter_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): + async def enter_lobby(self, lobby_id: int, user_chat_id: str): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} - WHERE rowid={lobby_id}; + WHERE lobby_id={lobby_id}; """) pairs = cur.fetchone()[0].split('~~~') - pairs.append(f"""{user_chat_id}-{user_name}""") - cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(pairs)}' WHERE rowid={lobby_id};""") + pairs.append(f"""{user_chat_id}""") + cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(pairs)}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() - async def exit_lobby(self, lobby_id: int, user_chat_id: str, user_name: str): + async def exit_lobby(self, lobby_id: int, user_chat_id: str): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} - WHERE rowid={lobby_id}; + WHERE lobby_id={lobby_id}; """) pairs = cur.fetchone()[0].split('~~~') - pairs.remove(f"""{user_chat_id}-{user_name}""") - cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(pairs)}' WHERE rowid={lobby_id};""") - conn.commit() - cur.close() - - async def reset_lobby(self, lobby_id: int): - cur = conn.cursor() - cur.execute(f"""UPDATE {self.name} SET users='' WHERE rowid={lobby_id};""") + pairs.remove(f"""{user_chat_id}""") + cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(pairs)}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() def get_lobby_stat(self, lobby_id: int): cur = conn.cursor() cur.execute(f"""SELECT users FROM {self.name} - WHERE rowid={lobby_id};""") + WHERE lobby_id={lobby_id};""") s = cur.fetchone()[0].split('~~~') conn.commit() cur.close() return s - def create_new_lobby(self, user_chat_id: str, user_name: str, deck: str): + def create_new_lobby(self, user_chat_id: str, deck: str): cur = conn.cursor() - cur.execute(f"""INSERT INTO {self.name} VALUES (NULL, '{user_chat_id}-{user_name}', '{deck}')""") - cur.execute(f"""SELECT rowid FROM {self.name} - WHERE users='{user_chat_id}-{user_name}';""") + cur.execute(f"""INSERT INTO {self.name} (users, deck) VALUES ('{user_chat_id}', '{deck}')""") + cur.execute(f"""SELECT lobby_id FROM {self.name} + WHERE users='{user_chat_id}';""") lobby_id = cur.fetchone()[0] conn.commit() cur.close() @@ -67,19 +61,19 @@ def create_new_lobby(self, user_chat_id: str, user_name: str, deck: str): def get_all_lobby_stat(self): cur = conn.cursor() - cur.execute(f"""SELECT rowid, users FROM {self.name}""") + cur.execute(f"""SELECT lobby_id, users FROM {self.name}""") all_lobby_stat = cur.fetchall() return all_lobby_stat async def delete_lobby(self, lobby_id: int): cur = conn.cursor() - cur.execute(f"""DELETE FROM {self.name} WHERE rowid={lobby_id};""") + cur.execute(f"""DELETE FROM {self.name} WHERE lobby_id={lobby_id};""") conn.commit() cur.close() def get_lobby_deck(self, lobby_id): cur = conn.cursor() - cur.execute(f"""SELECT deck FROM {self.name} WHERE rowid={lobby_id}""") + cur.execute(f"""SELECT deck FROM {self.name} WHERE lobby_id={lobby_id}""") deck = cur.fetchone()[0] conn.commit() cur.close() @@ -87,12 +81,12 @@ def get_lobby_deck(self, lobby_id): async def update_deck(self, deck, lobby_id): cur = conn.cursor() - cur.execute(f"""UPDATE {self.name} SET deck='{deck}' WHERE rowid={lobby_id};""") + cur.execute(f"""UPDATE {self.name} SET deck='{deck}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() -class UsersWithoutLobbiesDatabase: +class UsersDatabase: def __init__(self, name): self.name = name @@ -100,31 +94,107 @@ async def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} (chat_id INT PRIMARY KEY, - message_id INT);""") + user_name TEXT, + lobbies_page_message_id INT, + game_page_message_id INT, + balance INT, + games_amount INT, + wines_amount INT, + loses_amount INT, + last_free_reward_date_timestamp INT);""") conn.commit() cur.close() print('[INFO] TABLE CREATED SUCCESSFULLY') - async def insert_users_message_id(self, chat_id, message_id): + async def insert_new_user(self, chat_id: int, user_name: str): cur = conn.cursor() - cur.execute(f"""INSERT INTO {self.name} (chat_id, message_id) - VALUES ({chat_id}, {message_id}) - ON CONFLICT(chat_id) - DO UPDATE SET message_id={message_id}; - """) + cur.execute(f"""INSERT INTO {self.name} + (chat_id, user_name, lobbies_page_message_id, games_amount, wines_amount, loses_amount, balance, + last_free_reward_date_timestamp) + VALUES ({chat_id}, '{user_name}', NULL, 0, 0, 0, 1000, 0) + ON CONFLICT (chat_id) DO NOTHING; + """) conn.commit() cur.close() - def get_statistic_of_users(self): + def get_statistic_of_users_without_lobby(self): cur = conn.cursor() - cur.execute(f"""SELECT chat_id, message_id FROM {self.name}""") + cur.execute(f"""SELECT chat_id, lobbies_page_message_id FROM {self.name} + WHERE lobbies_page_message_id IS NOT NULL;""") stat = cur.fetchall() conn.commit() cur.close() return stat - async def delete_chat_id(self, chat_id): + def get_user_name(self, chat_id: int): + cur = conn.cursor() + cur.execute(f"""SELECT user_name FROM {self.name} WHERE chat_id={chat_id}""") + user_name = cur.fetchone() + conn.commit() + cur.close() + return user_name[0] + + async def update_lobbies_page_message_id(self, chat_id: int, lobbies_page_message_id: int): + cur = conn.cursor() + cur.execute(f"""UPDATE {self.name} SET lobbies_page_message_id={lobbies_page_message_id} + WHERE chat_id={chat_id};""") + conn.commit() + cur.close() + + async def delete_lobbies_page_message_id(self, chat_id: int): + cur = conn.cursor() + cur.execute(f"""UPDATE {self.name} SET lobbies_page_message_id=NULL WHERE chat_id={chat_id};""") + conn.commit() + cur.close() + + def get_user_statistic(self, chat_id): + cur = conn.cursor() + cur.execute(f"""SELECT user_name, balance, games_amount, wines_amount, loses_amount + FROM {self.name} WHERE chat_id={chat_id}""") + stat = cur.fetchall() + conn.commit() + cur.close() + return stat[0] + + def get_user_balance(self, chat_id): + cur = conn.cursor() + cur.execute(f"""SELECT balance FROM {self.name} WHERE chat_id={chat_id}""") + balance = cur.fetchone() + conn.commit() + cur.close() + return balance[0] + + def update_user_balance(self, chat_id: int, balance: int): + cur = conn.cursor() + cur.execute(f"""UPDATE {self.name} SET balance={balance} WHERE chat_id={chat_id};""") + conn.commit() + cur.close() + + def update_game_page_message_id(self, chat_id, message_id): + cur = conn.cursor() + cur.execute(f"""UPDATE {self.name} SET game_page_message_id={message_id} WHERE chat_id={chat_id};""") + conn.commit() + cur.close() + + def get_user_game_page_message_id(self, chat_id: int): + cur = conn.cursor() + cur.execute(f"""SELECT game_page_message_id FROM {self.name} WHERE chat_id={chat_id}""") + page_message_id = cur.fetchone() + conn.commit() + cur.close() + return page_message_id[0] + + def get_last_free_reward_date_timestamp(self, chat_id: int): + cur = conn.cursor() + cur.execute(f"""SELECT last_free_reward_date_timestamp FROM {self.name} WHERE chat_id={chat_id}""") + last_free_reward_date_timestamp = cur.fetchone() + conn.commit() + cur.close() + return last_free_reward_date_timestamp[0] + + def update_last_free_reward_date_timestamp(self, chat_id: int, last_free_reward_date_timestamp: int): cur = conn.cursor() - cur.execute(f"""DELETE FROM {self.name} WHERE chat_id={chat_id};""") + cur.execute(f"""UPDATE {self.name} SET last_free_reward_date_timestamp={last_free_reward_date_timestamp} + WHERE chat_id={chat_id}""") conn.commit() cur.close() diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index a1af01c..15a3f5f 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -1,286 +1,290 @@ from aiogram import Router, F from aiogram.exceptions import TelegramBadRequest from aiogram.filters import Command, StateFilter +from aiogram.fsm.storage.base import StorageKey from aiogram.types import Message, CallbackQuery -import locale -from bot import bot -from data.sql_database import LobbyDatabase, UsersWithoutLobbiesDatabase +from bot import bot, users_database, lobby_database from keyboards.keyboards import create_inline_kb, LobbyCallbackFactory from aiogram.fsm.context import FSMContext from aiogram.fsm.state import default_state -from aiogram.fsm.storage.base import StorageKey -from services.services import (FSMLobbyClass, create_lobbies_page, send_messages_to_users, - get_lobby_members, create_deck, get_next_cards) -from lexicon.lexicon import lexicon_card_colors, lexicon_card_faces +from services.services import exit_lobby, FSMLobbyClass, create_lobbies_page, create_deck, LobbyMessage, \ + update_previous_pages +from datetime import datetime +from lexicon.lexicon import lexicon_menu_keyboard, lexicon_user_statistic +from copy import deepcopy router = Router() -lobby_database = LobbyDatabase('test6') -users_without_lobbies_database = UsersWithoutLobbiesDatabase('test5') -locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8') @router.message(Command(commands='start')) async def start(message: Message, state: FSMContext): data = await state.get_data() + await users_database.insert_new_user(chat_id=message.chat.id, user_name=message.chat.full_name) + await users_database.delete_lobbies_page_message_id(chat_id=message.chat.id) if data.get('lobby'): - await state.update_data(lobby=None) - await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), - user_name=message.from_user.full_name) - lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - if not len(lobby_stat): - await lobby_database.delete_lobby(data['lobby']) - else: - await send_messages_to_users(bot=bot, - message=f'{message.from_user.full_name} вышел(-а) из лобби\n\n' - f'Текущие участники:\n' - f'{get_lobby_members(lobby_stat)}\n\n' - f'Приготовиться - /ready\n' - f'Информация о лобби - /info\n' - f'Выйти - /exit', - users=lobby_stat) - lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(width=2, dct=lobby_pages) - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() - for chat_id, message_id in people_without_lobby: - try: - await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, - reply_markup=keyboard) - except TelegramBadRequest: - pass + await exit_lobby(state=state, data=data, bot=bot, message=message) await state.set_state(default_state) - await message.answer(text='Это тренировочный бот для игры в ... с другими людьми.\nДля начала выберите лобби,' - ' использовав команду /lobbies') + keyboard = create_inline_kb(dct={'menu': 'Главное меню'}, width=1) + game_message_id = await message.answer(text='Это тренировочный бот для игры в Дурака с другими людьми.\n' + 'Для начала перейдите в главное меню', + reply_markup=keyboard) + await state.update_data(previous_pages=[], game_message_id=game_message_id.message_id) -@router.message(Command(commands='lobbies'), ~StateFilter(FSMLobbyClass.select_lobby)) -async def lobbies(message: Message, +@router.callback_query(F.data == 'menu', StateFilter(default_state, FSMLobbyClass.select_lobby)) +async def menu(callback: CallbackQuery, + state: FSMContext): + data = await state.get_data() + data_callback = callback.data + data = update_previous_pages(data, data_callback) + await state.update_data(data=data) + await state.set_state(default_state) + keyboard = create_inline_kb(dct=lexicon_menu_keyboard, width=1) + await callback.message.edit_text(text='Вы находитесь в главном меню', reply_markup=keyboard) + data['previous_pages'].append(callback.data) + + +@router.callback_query(F.data == 'statistics', StateFilter(default_state)) +async def statistic(callback: CallbackQuery, + state: FSMContext): + data = await state.get_data() + data_callback = callback.data + data = update_previous_pages(data, data_callback) + await state.update_data(data=data) + user_stat = users_database.get_user_statistic(chat_id=callback.message.chat.id) + keyboard = create_inline_kb(width=1, back_button=data['previous_pages'][-1]) + await callback.message.edit_text(text=lexicon_user_statistic.format(*user_stat), reply_markup=keyboard) + data['previous_pages'].append(callback.data) + + +@router.callback_query(F.data == 'free_reward', StateFilter(default_state)) +async def free_reward(callback: CallbackQuery): + balance = users_database.get_user_balance(chat_id=callback.message.chat.id) + if balance < 1450: + last_date = users_database.get_last_free_reward_date_timestamp(chat_id=callback.message.chat.id) + current_date = datetime.now().timestamp() + difference_date = current_date - last_date + if difference_date >= 3600: + await callback.answer(text='Беcплатная награда выдана (+1450)') + balance += 1450 + users_database.update_user_balance(chat_id=callback.message.chat.id, balance=balance) + users_database.update_last_free_reward_date_timestamp(chat_id=callback.message.chat.id, + last_free_reward_date_timestamp=current_date) + else: + normal_date = datetime.fromtimestamp(last_date+3600) + await callback.answer(text=f'Следующую награду можно получить в {normal_date.strftime("%X")}', + show_alert=True) + else: + await callback.answer(text='У вас достаточно средств', show_alert=True) + + +@router.callback_query(F.data == 'lobbies', StateFilter(default_state)) +async def lobbies(callback: CallbackQuery, state: FSMContext): - await state.set_state(FSMLobbyClass.select_lobby) data = await state.get_data() - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + data_callback = callback.data + data = update_previous_pages(data, data_callback) + await state.update_data(data=data) + await state.set_state(FSMLobbyClass.select_lobby) if data.get('lobby'): - await state.update_data(lobby=None) - await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), - user_name=message.from_user.full_name) - lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - if not len(lobby_stat): - await lobby_database.delete_lobby(data['lobby']) - else: - await send_messages_to_users(bot=bot, - message=f'{message.from_user.full_name} вышел(-a) из лобби\n\n' - f'Текущие участники:\n' - f'{get_lobby_members(lobby_stat)}\n\n' - f'Приготовиться - /ready\n' - f'Информация о лобби - /info\n' - f'Выйти - /exit', - users=lobby_stat) - lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') - for chat_id, message_id in people_without_lobby: - try: - await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, - reply_markup=keyboard) - except TelegramBadRequest: - pass + await exit_lobby(state=state, data=data, bot=bot, message=callback.message) lobby_pages = create_lobbies_page() - keyboards = create_inline_kb(2, dct=lobby_pages, last_btn='create_new_lobby') - bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboards) - await users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, - message_id=bot_message.message_id) + keyboards = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', + back_button=data['previous_pages'][-1]) + bot_message = await callback.message.edit_text(text='Список доступных лобби', reply_markup=keyboards) + await users_database.update_lobbies_page_message_id(chat_id=callback.message.chat.id, + lobbies_page_message_id=bot_message.message_id) + data['previous_pages'].append(callback.data) @router.callback_query(LobbyCallbackFactory.filter(), StateFilter(FSMLobbyClass.select_lobby)) async def lobby_page(callback: CallbackQuery, callback_data: LobbyCallbackFactory, state: FSMContext): - lobby_stat_1 = lobby_database.get_lobby_stat(callback_data.lobby_id) - if len(lobby_stat_1) < 4: - await state.update_data(lobby=callback_data.lobby_id, ready=0) - await state.set_state(FSMLobbyClass.in_lobby) - await lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id), - user_name=callback.from_user.full_name) - lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(width=2, dct=lobby_pages) - lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) - await callback.message.edit_text(text=f'Вы вошли(-а) в лобби!\n\n' - f'Участники:\n' - f'{get_lobby_members(lobby_stat)}\n\n' - f'Приготовиться - /ready\n' - f'Информация о лобби - /info\n' - f'Выйти - /exit', - reply_markup=None) - await users_without_lobbies_database.delete_chat_id(chat_id=callback.message.chat.id) - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() + lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) + if len(lobby_stat) < 4: + users_name = users_database.get_user_name(chat_id=callback.message.chat.id) + lobby_user_ids = deepcopy(lobby_stat) + lobby_user_ids.append(callback.message.chat.id) + lobby_message = LobbyMessage([users_database.get_user_name(chat_id) for chat_id in lobby_user_ids]) + keyboard = create_inline_kb(dct=lobby_message.lobby_keyboard_buttons, width=1) + bot_message = await callback.message.edit_text(text=str(lobby_message), reply_markup=keyboard) + await callback.answer(text='Вы зашли в лобби!') + await users_database.delete_lobbies_page_message_id(chat_id=callback.message.chat.id) + users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) + people_without_lobby = users_database.get_statistic_of_users_without_lobby() + storage = state.storage + for chat_id in lobby_stat: + try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + lobby_message = storage_data['lobby_message'] + lobby_message.add_user(users_name) + await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=chat_id), + reply_markup=lobby_message.keyboard) + except TelegramBadRequest: + pass for chat_id, message_id in people_without_lobby: try: await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: pass - - await send_messages_to_users(bot=bot, - message=f'{callback.from_user.full_name} зашел(-а) в лобби\n\n' - f'Текущие участники:\n' - f'{get_lobby_members(lobby_stat)}\n\n' - f'Приготовиться - /ready\n' - f'Информация о лобби - /info\n' - f'Выйти - /exit', - users=lobby_stat_1) + await lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id)) + await state.set_state(FSMLobbyClass.in_lobby) else: await callback.answer('Лобби заполнено') +# +# +# @router.message(Command(commands='exit'), StateFilter(FSMLobbyClass.in_lobby)) +# async def exit_command(message: Message, +# state: FSMContext): +# data = await state.get_data() +# await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), +# user_name=message.from_user.full_name) +# lobby_stat = lobby_database.get_lobby_stat(data['lobby']) +# if not len(lobby_stat[0]): +# await lobby_database.delete_lobby(data['lobby']) +# else: +# await send_messages_to_users(bot=bot, +# message=f'{message.from_user.full_name} вышел(-а) из лобби\n\n' +# f'Текущие участники:\n' +# f'{get_lobby_members(lobby_stat)}\n\n' +# f'Приготовиться - /ready\n' +# f'Информация о лобби - /info\n' +# f'Выйти - /exit', +# users=lobby_stat) +# lobby_pages = create_lobbies_page() +# keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') +# bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboard) +# people_without_lobby = users_database.get_statistic_of_users_without_lobby() +# await state.update_data(lobby=None) +# await state.set_state(FSMLobbyClass.select_lobby) +# await users_database.insert_users_message_id(chat_id=message.chat.id, +# message_id=bot_message.message_id) +# for chat_id, message_id in people_without_lobby: +# try: +# await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, +# reply_markup=keyboard) +# except TelegramBadRequest: +# pass +# if data.get('current_cards'): +# lobby_deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']).split('~~~') +# user_cards = data['current_cards'].split('~~~') +# for card in user_cards: +# lobby_deck.append(card) +# await lobby_database.update_deck(deck='~~~'.join(lobby_deck)) +# +# +# @router.message(Command(commands='info'), StateFilter(FSMLobbyClass.in_lobby)) +# async def info_command(message: Message, +# state: FSMContext): +# data = await state.get_data() +# lobby_stat = lobby_database.get_lobby_stat(data['lobby']) +# await message.answer(text=f'Участники:\n' +# f'{get_lobby_members(lobby_stat)}\n\n' +# f'Приготовиться - /ready\n' +# f'Выйти - /exit') +# +# +# @router.message(Command(commands='ready'), StateFilter(FSMLobbyClass.in_lobby)) +# async def ready_command_others(message: Message, +# state: FSMContext): +# storage = state.storage +# data = await state.get_data() +# storage_data = await storage.get_data(StorageKey(bot_id=bot.id, +# chat_id=message.chat.id, +# user_id=message.chat.id)) +# if not storage_data['ready']: +# deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']) +# cards = get_next_cards(deck=deck, cards_num=6) +# storage_data['ready'] = 1 +# storage_data['current_cards'] = cards[0] +# deck = '~~~'.join(cards[1]) +# await lobby_database.update_deck(deck=deck, lobby_id=data['lobby']) +# await storage.update_data(StorageKey(bot_id=bot.id, +# chat_id=message.chat.id, +# user_id=message.chat.id), data=storage_data) +# users_unready = [] +# users_unready_counter = 0 +# lobby_stat = lobby_database.get_lobby_stat(data['lobby']) +# answer_for_other_text = f'{message.from_user.full_name} готов к игре!\n\n' +# other_text = '' +# user_cards = {} +# info_text = '\n\nИнформация о лобби - /info\nВыйти - /exit' +# print(storage_data) +# for pair in lobby_stat: +# print(pair) +# storage_data = await storage.get_data(StorageKey(bot_id=bot.id, +# chat_id=int(pair.split('-')[0]), +# user_id=int(pair.split('-')[0]))) +# if storage_data['ready']: +# users_unready.append(f'{pair.split("-")[1]} - готов') +# else: +# users_unready_counter += 1 +# users_unready.append(f'{pair.split("-")[1]} - не готов') +# if users_unready_counter == 0: +# if len(lobby_stat) == 2: +# other_text = 'Все игроки готовы! Игра начинается!\n\nВаши карты:\n' +# for pair in lobby_stat: +# await storage.set_state(StorageKey(bot_id=bot.id, +# chat_id=int(pair.split('-')[0]), +# user_id=int(pair.split('-')[0])), state=FSMLobbyClass.in_game) +# storage_data = await storage.get_data(StorageKey(bot_id=bot.id, +# chat_id=int(pair.split('-')[0]), +# user_id=int(pair.split('-')[0]))) +# user_cards[int(pair.split('-')[0])] = sorted([x.replace('-', ' ') +# for x in storage_data['current_cards']], +# key=lambda x: (lexicon_card_colors[x.split()[1]], +# lexicon_card_faces[x.split()[0]])) +# +# else: +# other_text += '\n'.join(users_unready) +# other_text += '\n\nОжидаем других игроков' +# else: +# other_text += '\n'.join(users_unready) +# other_text += '\n\nОжидаем других игроков' +# for pair in lobby_stat: +# if pair.split('-')[0] != str(message.chat.id): +# if user_cards: +# await bot.send_message(chat_id=pair.split('-')[0], +# text=answer_for_other_text + other_text + '\n'.join(user_cards[ +# int(pair.split('-')[0])]) + info_text) +# else: +# await bot.send_message(chat_id=pair.split('-')[0], +# text=answer_for_other_text + other_text + info_text) +# else: +# if user_cards: +# await message.answer(text='Вы приготовились!\n\n'+other_text+'\n'.join(user_cards[ +# int(pair.split('-')[0])])+info_text) +# else: +# await message.answer(text='Вы приготовились!\n\n'+other_text+info_text) +# else: +# await message.answer(text='Вы уже готовы!') -@router.message(Command(commands='exit'), StateFilter(FSMLobbyClass.in_lobby)) -async def exit_command(message: Message, - state: FSMContext): - data = await state.get_data() - await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), - user_name=message.from_user.full_name) - lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - if not len(lobby_stat[0]): - await lobby_database.delete_lobby(data['lobby']) - else: - await send_messages_to_users(bot=bot, - message=f'{message.from_user.full_name} вышел(-а) из лобби\n\n' - f'Текущие участники:\n' - f'{get_lobby_members(lobby_stat)}\n\n' - f'Приготовиться - /ready\n' - f'Информация о лобби - /info\n' - f'Выйти - /exit', - users=lobby_stat) +@router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) +async def create_new_lobby(callback: CallbackQuery, + state: FSMContext): + deck = create_deck() + lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id), deck=deck) + lobby_message = LobbyMessage([callback.message.chat.full_name]) + bot_message = await callback.message.edit_text(text=str(lobby_message), reply_markup=lobby_message.keyboard) + await callback.answer(text='Вы создали лобби!') + await state.set_state(FSMLobbyClass.in_lobby) + await state.update_data(lobby=lobby_id, ready=0, lobby_message=lobby_message) + await users_database.delete_lobbies_page_message_id(chat_id=callback.message.chat.id) + users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) + people_without_lobby = users_database.get_statistic_of_users_without_lobby() lobby_pages = create_lobbies_page() keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') - bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboard) - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() - await state.update_data(lobby=None) - await state.set_state(FSMLobbyClass.select_lobby) - await users_without_lobbies_database.insert_users_message_id(chat_id=message.chat.id, - message_id=bot_message.message_id) for chat_id, message_id in people_without_lobby: try: await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: pass - - -@router.message(Command(commands='info'), StateFilter(FSMLobbyClass.in_lobby)) -async def info_command(message: Message, - state: FSMContext): - data = await state.get_data() - lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - await message.answer(text=f'Участники:\n' - f'{get_lobby_members(lobby_stat)}\n\n' - f'Приготовиться - /ready\n' - f'Выйти - /exit') - - -@router.message(Command(commands='ready'), StateFilter(FSMLobbyClass.in_lobby)) -async def ready_command_others(message: Message, - state: FSMContext): - storage = state.storage - data = await state.get_data() - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=message.chat.id, - user_id=message.chat.id)) - print(storage_data) - if not storage_data['ready']: - deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']) - cards = get_next_cards(deck=deck, cards_num=6) - storage_data['ready'] = 1 - storage_data['current_cards'] = cards[0] - deck = '~~~'.join(cards[1]) - await lobby_database.update_deck(deck=deck, lobby_id=data['lobby']) - await storage.update_data(StorageKey(bot_id=bot.id, - chat_id=message.chat.id, - user_id=message.chat.id), data=storage_data) - users_unready = [] - users_unready_counter = 0 - lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - answer_for_other_text = f'{message.from_user.full_name} готов к игре!\n\n' - other_text = '' - user_cards = {} - info_text = '\n\nИнформация о лобби - /info\nВыйти - /exit' - print(storage_data) - for pair in lobby_stat: - print(pair) - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(pair.split('-')[0]), - user_id=int(pair.split('-')[0]))) - if storage_data['ready']: - users_unready.append(f'{pair.split("-")[1]} - готов') - else: - users_unready_counter += 1 - users_unready.append(f'{pair.split("-")[1]} - не готов') - if users_unready_counter == 0: - if len(lobby_stat) == 2: - other_text = 'Все игроки готовы! Игра начинается!\n\nВаши карты:\n' - for pair in lobby_stat: - await storage.set_state(StorageKey(bot_id=bot.id, - chat_id=int(pair.split('-')[0]), - user_id=int(pair.split('-')[0])), state=FSMLobbyClass.in_game) - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(pair.split('-')[0]), - user_id=int(pair.split('-')[0]))) - user_cards[int(pair.split('-')[0])] = sorted([x.replace('-', ' ') - for x in storage_data['current_cards']], - key=lambda x: (lexicon_card_colors[x.split()[1]], - lexicon_card_faces.get(x.split()[0], - x.split()[0]))) - - else: - other_text += '\n'.join(users_unready) - other_text += '\n\nОжидаем других игроков' - else: - other_text += '\n'.join(users_unready) - other_text += '\n\nОжидаем других игроков' - for pair in lobby_stat: - if pair.split('-')[0] != str(message.chat.id): - if user_cards: - await bot.send_message(chat_id=pair.split('-')[0], - text=answer_for_other_text + other_text + '\n'.join(user_cards[ - int(pair.split('-')[0])]) + info_text) - else: - await bot.send_message(chat_id=pair.split('-')[0], - text=answer_for_other_text + other_text + info_text) - else: - if user_cards: - await message.answer(text='Вы приготовились!\n\n'+other_text+'\n'.join(user_cards[ - int(pair.split('-')[0])])+info_text) - else: - await message.answer(text='Вы приготовились!\n\n'+other_text+info_text) - else: - await message.answer(text='Вы уже готовы!') - - -@router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) -async def create_new_lobby(callback: CallbackQuery, - state: FSMContext): - deck = create_deck() - lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id), - user_name=callback.from_user.full_name, deck=deck) - await state.set_state(FSMLobbyClass.in_lobby) - await state.update_data(lobby=lobby_id, ready=0) - await callback.message.edit_text(text='Вы создали новое лобби!\n\n' - 'Приготовиться - /ready\n' - 'Информация о лобби - /info\n' - 'Выйти - /exit') - await users_without_lobbies_database.delete_chat_id(chat_id=callback.message.chat.id) - people_without_lobby = users_without_lobbies_database.get_statistic_of_users() - if people_without_lobby: - lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') - for chat_id, message_id in people_without_lobby: - try: - await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, - reply_markup=keyboard) - except TelegramBadRequest: - pass - print(lobby_database.get_lobby_stat(lobby_id=lobby_id)) - - -@router.message(StateFilter(FSMLobbyClass.in_game)) -async def game(message: Message, - state: FSMContext): - await message.answer(text='Вы играити, ура') diff --git a/lexicon/lexicon.py b/lexicon/lexicon.py index 70531c7..229fd0b 100644 --- a/lexicon/lexicon.py +++ b/lexicon/lexicon.py @@ -10,4 +10,13 @@ lexicon_card_colors = {'♥️': 1, '♦️': 2, '♣️': 3, '♠️': 4} -lexicon_card_faces = {'Валет': 11, 'Дама': 12, 'Король': 13, 'Туз': 14} +lexicon_card_faces = {'6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'Валет': 11, 'Дама': 12, 'Король': 13, 'Туз': 14} + +lexicon_menu_keyboard = {'lobbies': 'Выбрать комнату', 'statistics': 'Статистика пользователя', + 'free_reward': 'Бесплатная награда', 'info': 'Информация о боте'} + +lexicon_user_statistic = ('Ваше имя: {}\n' + 'Баланс: {}\n\n' + 'Количество сыгранных партий: {}\n' + 'Количество побед: {}\n' + 'Количество поражений: {}') diff --git a/services/services.py b/services/services.py index 188b351..a296e0c 100644 --- a/services/services.py +++ b/services/services.py @@ -1,25 +1,35 @@ +from typing import Optional + from aiogram import Bot +from aiogram.exceptions import TelegramBadRequest +from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup - -from data.sql_database import LobbyDatabase -from keyboards.keyboards import LobbyCallbackFactory - -lobby_database = LobbyDatabase('test6') +from aiogram.fsm.storage.base import StorageKey +from aiogram.types import InlineKeyboardMarkup, Message +from bot import users_database, lobby_database +from keyboards.keyboards import LobbyCallbackFactory, create_inline_kb class FSMLobbyClass(StatesGroup): + select_lobby = State() in_lobby = State() in_game = State() - select_lobby = State() ready = State() lobby = State() current_cards = State() + previous_pages = State() + lobby_message = State() + game_message_id = State() + + +def create_user_list_for_lobby(users: list): + users_list_for_lobby = '\n'.join([f'{i}. {users[i-1]}' if i <= len(users) else f'{i}. Ждем игрока' for i in range(1, 5)]) + return users_list_for_lobby def create_lobby_short_name(users): - names = list(map(lambda x: x.split('-')[1], users)) + names = list(map(lambda x: users_database.get_user_name(x), users)) lobby_short_name = ', '.join(names) - lobby_short_name.strip(', ') return lobby_short_name[:10]+'...' if len(lobby_short_name) > 12 else lobby_short_name @@ -30,13 +40,18 @@ def create_lobbies_page(): for lobby in all_lobby_stat if lobby[1]} -async def send_messages_to_users(bot: Bot, message: str, users: list): +async def send_messages_to_users(bot: Bot, message: str, users: list, markup: Optional[InlineKeyboardMarkup]): + for i in users: + await bot.send_message(chat_id=int(i), text=message, reply_markup=markup) + + +async def edit_users_messages(bot: Bot, message: str, users: list, markup: Optional[InlineKeyboardMarkup]): for i in users: - await bot.send_message(chat_id=int(i.split('-')[0]), text=message) + await bot.edit_message_text(chat_id=int(i), text=message, reply_markup=markup) def get_lobby_members(pairs: list): - members = list(map(lambda x: x.split('-')[1], pairs)) + members = list(map(lambda x: users_database.get_user_name(x), pairs)) return '\n'.join(members) @@ -54,3 +69,61 @@ def create_deck(): def get_next_cards(deck, cards_num): deck = deck.split('~~~') return [deck[:cards_num], deck[cards_num:]] + + +class LobbyMessage: + ready_text = 'Вы не готовы!\n\n' + lobby_keyboard_buttons = {'ready': 'Приготовиться', 'exit': 'Выйти'} + keyboard = create_inline_kb(dct=lobby_keyboard_buttons, width=1) + + def __init__(self, users: list): + self.users = users + + def __str__(self): + users_list = create_user_list_for_lobby(self.users) + lobby_text = self.ready_text + f'Участники лобби:\n{users_list}' + return lobby_text + + def delete_user(self, user: str): + self.users.remove(user) + + def add_user(self, user: str): + self.users.append(user) + + +async def exit_lobby(state: FSMContext, data, bot, message: Message): + await state.update_data(lobby=None) + await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id)) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + storage = state.storage + if lobby_stat[0] == '': + await lobby_database.delete_lobby(data['lobby']) + else: + for chat_id in lobby_stat: + try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + lobby_message = storage_data['lobby_message'] + lobby_message.delete_user(users_database.get_user_name(chat_id=chat_id)) + await bot.edit_message_text(chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=message.chat.id), + reply_markup=lobby_message.keyboard) + except TelegramBadRequest: + pass + lobby_pages = create_lobbies_page() + keyboard = create_inline_kb(width=2, dct=lobby_pages) + people_without_lobby = users_database.get_statistic_of_users_without_lobby() + for chat_id, message_id in people_without_lobby: + try: + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) + except TelegramBadRequest: + pass + + +def update_previous_pages(data, callback_data): + if callback_data in data['previous_pages']: + data['previous_pages'] = data['previous_pages'][:-2] + return data From 192ef9438f14841cd904a939ba821fc8956cb457 Mon Sep 17 00:00:00 2001 From: ilyak Date: Mon, 8 Jan 2024 22:12:39 +0500 Subject: [PATCH 08/14] 1 --- data/sql_database.py | 8 ++-- handlers/user_handlers.py | 80 +++++++++++++++++---------------------- services/services.py | 7 ++-- 3 files changed, 42 insertions(+), 53 deletions(-) diff --git a/data/sql_database.py b/data/sql_database.py index bba5674..f41f5ee 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -10,7 +10,7 @@ def __init__(self, name): async def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} - (lobby_id SERIAL PRIMARY KEY, + (lobby_id BIGSERIAL PRIMARY KEY, users TEXT, deck TEXT); """) @@ -93,10 +93,10 @@ def __init__(self, name): async def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} - (chat_id INT PRIMARY KEY, + (chat_id BIGINT PRIMARY KEY, user_name TEXT, - lobbies_page_message_id INT, - game_page_message_id INT, + lobbies_page_message_id BIGINT, + game_page_message_id BIGINT, balance INT, games_amount INT, wines_amount INT, diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index 15a3f5f..0178e73 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -107,9 +107,9 @@ async def lobby_page(callback: CallbackQuery, users_name = users_database.get_user_name(chat_id=callback.message.chat.id) lobby_user_ids = deepcopy(lobby_stat) lobby_user_ids.append(callback.message.chat.id) - lobby_message = LobbyMessage([users_database.get_user_name(chat_id) for chat_id in lobby_user_ids]) - keyboard = create_inline_kb(dct=lobby_message.lobby_keyboard_buttons, width=1) - bot_message = await callback.message.edit_text(text=str(lobby_message), reply_markup=keyboard) + lobby_message_1 = LobbyMessage([users_database.get_user_name(chat_id) for chat_id in lobby_user_ids]) + keyboard = create_inline_kb(dct=lobby_message_1.lobby_keyboard_buttons, width=1) + bot_message = await callback.message.edit_text(text=str(lobby_message_1), reply_markup=keyboard) await callback.answer(text='Вы зашли в лобби!') await users_database.delete_lobbies_page_message_id(chat_id=callback.message.chat.id) users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) @@ -136,50 +136,40 @@ async def lobby_page(callback: CallbackQuery, pass await lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id)) await state.set_state(FSMLobbyClass.in_lobby) + await state.update_data(lobby=callback_data.lobby_id, lobby_message=lobby_message_1, ready=0) else: await callback.answer('Лобби заполнено') -# -# -# @router.message(Command(commands='exit'), StateFilter(FSMLobbyClass.in_lobby)) -# async def exit_command(message: Message, -# state: FSMContext): -# data = await state.get_data() -# await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id), -# user_name=message.from_user.full_name) -# lobby_stat = lobby_database.get_lobby_stat(data['lobby']) -# if not len(lobby_stat[0]): -# await lobby_database.delete_lobby(data['lobby']) -# else: -# await send_messages_to_users(bot=bot, -# message=f'{message.from_user.full_name} вышел(-а) из лобби\n\n' -# f'Текущие участники:\n' -# f'{get_lobby_members(lobby_stat)}\n\n' -# f'Приготовиться - /ready\n' -# f'Информация о лобби - /info\n' -# f'Выйти - /exit', -# users=lobby_stat) -# lobby_pages = create_lobbies_page() -# keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') -# bot_message = await message.answer(text='Список доступных лобби', reply_markup=keyboard) -# people_without_lobby = users_database.get_statistic_of_users_without_lobby() -# await state.update_data(lobby=None) -# await state.set_state(FSMLobbyClass.select_lobby) -# await users_database.insert_users_message_id(chat_id=message.chat.id, -# message_id=bot_message.message_id) -# for chat_id, message_id in people_without_lobby: -# try: -# await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, -# reply_markup=keyboard) -# except TelegramBadRequest: -# pass -# if data.get('current_cards'): -# lobby_deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']).split('~~~') -# user_cards = data['current_cards'].split('~~~') -# for card in user_cards: -# lobby_deck.append(card) -# await lobby_database.update_deck(deck='~~~'.join(lobby_deck)) -# -# + + +@router.callback_query(F.data == 'exit', StateFilter(FSMLobbyClass.in_lobby)) +async def exit_command(callback: CallbackQuery, + state: FSMContext): + data = await state.get_data() + data_callback = callback.data + data = update_previous_pages(data, data_callback) + await state.update_data(data=data) + await state.set_state(FSMLobbyClass.select_lobby) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + if not len(lobby_stat[0]): + await lobby_database.delete_lobby(data['lobby']) + else: + await exit_lobby(state=state, bot=bot, message=callback.message, data=data) + lobby_pages = create_lobbies_page() + keyboards = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', + back_button=data['previous_pages'][-1]) + await callback.answer(text='Вы вышли из лобби!') + bot_message = await callback.message.edit_text(text='Список доступных лобби', reply_markup=keyboards) + await users_database.update_lobbies_page_message_id(chat_id=callback.message.chat.id, + lobbies_page_message_id=bot_message.message_id) + data['previous_pages'].append(callback.data) + if data.get('current_cards'): + lobby_deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']).split('~~~') + user_cards = data['current_cards'].split('~~~') + for card in user_cards: + lobby_deck.append(card) + await lobby_database.update_deck(deck='~~~'.join(lobby_deck)) + + # @router.message(Command(commands='info'), StateFilter(FSMLobbyClass.in_lobby)) # async def info_command(message: Message, # state: FSMContext): diff --git a/services/services.py b/services/services.py index a296e0c..f4fd103 100644 --- a/services/services.py +++ b/services/services.py @@ -1,5 +1,4 @@ from typing import Optional - from aiogram import Bot from aiogram.exceptions import TelegramBadRequest from aiogram.fsm.context import FSMContext @@ -50,8 +49,8 @@ async def edit_users_messages(bot: Bot, message: str, users: list, markup: Optio await bot.edit_message_text(chat_id=int(i), text=message, reply_markup=markup) -def get_lobby_members(pairs: list): - members = list(map(lambda x: users_database.get_user_name(x), pairs)) +def get_lobby_members(users_ids: list): + members = list(map(lambda user_id: users_database.get_user_name(user_id), users_ids)) return '\n'.join(members) @@ -106,7 +105,7 @@ async def exit_lobby(state: FSMContext, data, bot, message: Message): user_id=int(chat_id))) lobby_message = storage_data['lobby_message'] lobby_message.delete_user(users_database.get_user_name(chat_id=chat_id)) - await bot.edit_message_text(chat_id=chat_id, + await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=message.chat.id), reply_markup=lobby_message.keyboard) From 857289848c058c143bceb4d4a558f4510f2128db Mon Sep 17 00:00:00 2001 From: ilyak Date: Tue, 9 Jan 2024 00:44:59 +0500 Subject: [PATCH 09/14] 1 --- handlers/user_handlers.py | 139 +++++++++++++------------------------- services/services.py | 21 +++++- 2 files changed, 64 insertions(+), 96 deletions(-) diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index 0178e73..2078d1a 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -1,3 +1,4 @@ +import aiogram.types from aiogram import Router, F from aiogram.exceptions import TelegramBadRequest from aiogram.filters import Command, StateFilter @@ -8,7 +9,7 @@ from aiogram.fsm.context import FSMContext from aiogram.fsm.state import default_state from services.services import exit_lobby, FSMLobbyClass, create_lobbies_page, create_deck, LobbyMessage, \ - update_previous_pages + update_previous_pages, get_next_cards from datetime import datetime from lexicon.lexicon import lexicon_menu_keyboard, lexicon_user_statistic from copy import deepcopy @@ -108,13 +109,10 @@ async def lobby_page(callback: CallbackQuery, lobby_user_ids = deepcopy(lobby_stat) lobby_user_ids.append(callback.message.chat.id) lobby_message_1 = LobbyMessage([users_database.get_user_name(chat_id) for chat_id in lobby_user_ids]) - keyboard = create_inline_kb(dct=lobby_message_1.lobby_keyboard_buttons, width=1) - bot_message = await callback.message.edit_text(text=str(lobby_message_1), reply_markup=keyboard) - await callback.answer(text='Вы зашли в лобби!') await users_database.delete_lobbies_page_message_id(chat_id=callback.message.chat.id) - users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) people_without_lobby = users_database.get_statistic_of_users_without_lobby() storage = state.storage + lobby_pages = create_lobbies_page() for chat_id in lobby_stat: try: storage_data = await storage.get_data(StorageKey(bot_id=bot.id, @@ -128,8 +126,14 @@ async def lobby_page(callback: CallbackQuery, reply_markup=lobby_message.keyboard) except TelegramBadRequest: pass + storage = state.storage for chat_id, message_id in people_without_lobby: try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', + back_button=storage_data['previous_pages'][-1]) await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: @@ -137,6 +141,9 @@ async def lobby_page(callback: CallbackQuery, await lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id)) await state.set_state(FSMLobbyClass.in_lobby) await state.update_data(lobby=callback_data.lobby_id, lobby_message=lobby_message_1, ready=0) + bot_message = await callback.message.edit_text(text=str(lobby_message_1), reply_markup=lobby_message_1.keyboard) + await callback.answer(text='Вы зашли в лобби!') + users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) else: await callback.answer('Лобби заполнено') @@ -170,91 +177,36 @@ async def exit_command(callback: CallbackQuery, await lobby_database.update_deck(deck='~~~'.join(lobby_deck)) -# @router.message(Command(commands='info'), StateFilter(FSMLobbyClass.in_lobby)) -# async def info_command(message: Message, -# state: FSMContext): -# data = await state.get_data() -# lobby_stat = lobby_database.get_lobby_stat(data['lobby']) -# await message.answer(text=f'Участники:\n' -# f'{get_lobby_members(lobby_stat)}\n\n' -# f'Приготовиться - /ready\n' -# f'Выйти - /exit') -# -# -# @router.message(Command(commands='ready'), StateFilter(FSMLobbyClass.in_lobby)) -# async def ready_command_others(message: Message, -# state: FSMContext): -# storage = state.storage -# data = await state.get_data() -# storage_data = await storage.get_data(StorageKey(bot_id=bot.id, -# chat_id=message.chat.id, -# user_id=message.chat.id)) -# if not storage_data['ready']: -# deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']) -# cards = get_next_cards(deck=deck, cards_num=6) -# storage_data['ready'] = 1 -# storage_data['current_cards'] = cards[0] -# deck = '~~~'.join(cards[1]) -# await lobby_database.update_deck(deck=deck, lobby_id=data['lobby']) -# await storage.update_data(StorageKey(bot_id=bot.id, -# chat_id=message.chat.id, -# user_id=message.chat.id), data=storage_data) -# users_unready = [] -# users_unready_counter = 0 -# lobby_stat = lobby_database.get_lobby_stat(data['lobby']) -# answer_for_other_text = f'{message.from_user.full_name} готов к игре!\n\n' -# other_text = '' -# user_cards = {} -# info_text = '\n\nИнформация о лобби - /info\nВыйти - /exit' -# print(storage_data) -# for pair in lobby_stat: -# print(pair) -# storage_data = await storage.get_data(StorageKey(bot_id=bot.id, -# chat_id=int(pair.split('-')[0]), -# user_id=int(pair.split('-')[0]))) -# if storage_data['ready']: -# users_unready.append(f'{pair.split("-")[1]} - готов') -# else: -# users_unready_counter += 1 -# users_unready.append(f'{pair.split("-")[1]} - не готов') -# if users_unready_counter == 0: -# if len(lobby_stat) == 2: -# other_text = 'Все игроки готовы! Игра начинается!\n\nВаши карты:\n' -# for pair in lobby_stat: -# await storage.set_state(StorageKey(bot_id=bot.id, -# chat_id=int(pair.split('-')[0]), -# user_id=int(pair.split('-')[0])), state=FSMLobbyClass.in_game) -# storage_data = await storage.get_data(StorageKey(bot_id=bot.id, -# chat_id=int(pair.split('-')[0]), -# user_id=int(pair.split('-')[0]))) -# user_cards[int(pair.split('-')[0])] = sorted([x.replace('-', ' ') -# for x in storage_data['current_cards']], -# key=lambda x: (lexicon_card_colors[x.split()[1]], -# lexicon_card_faces[x.split()[0]])) -# -# else: -# other_text += '\n'.join(users_unready) -# other_text += '\n\nОжидаем других игроков' -# else: -# other_text += '\n'.join(users_unready) -# other_text += '\n\nОжидаем других игроков' -# for pair in lobby_stat: -# if pair.split('-')[0] != str(message.chat.id): -# if user_cards: -# await bot.send_message(chat_id=pair.split('-')[0], -# text=answer_for_other_text + other_text + '\n'.join(user_cards[ -# int(pair.split('-')[0])]) + info_text) -# else: -# await bot.send_message(chat_id=pair.split('-')[0], -# text=answer_for_other_text + other_text + info_text) -# else: -# if user_cards: -# await message.answer(text='Вы приготовились!\n\n'+other_text+'\n'.join(user_cards[ -# int(pair.split('-')[0])])+info_text) -# else: -# await message.answer(text='Вы приготовились!\n\n'+other_text+info_text) -# else: -# await message.answer(text='Вы уже готовы!') +@router.callback_query(F.data == 'ready', StateFilter(FSMLobbyClass.in_lobby)) +async def ready_command_others(callback: CallbackQuery, + state: FSMContext): + data = await state.get_data() + if not data['ready']: + lobby_message = data['lobby_message'] + lobby_message.update_ready_info(ready=1, user=users_database.get_user_name(chat_id=callback.message.chat.id)) + storage = state.storage + deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']) + cards = get_next_cards(deck=deck, cards_num=6) + data['ready'] = 1 + data['current_cards'] = cards[0] + deck = '~~~'.join(cards[1]) + await lobby_database.update_deck(deck=deck, lobby_id=data['lobby']) + await state.update_data(data=data) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + for chat_id in lobby_stat: + try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + lobby_message = storage_data['lobby_message'] + lobby_message.update_ready_info(ready=1, + user=users_database.get_user_name(chat_id=callback.message.chat.id)) + await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=chat_id), + reply_markup=lobby_message.keyboard) + except TelegramBadRequest: + pass @router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) @@ -263,12 +215,10 @@ async def create_new_lobby(callback: CallbackQuery, deck = create_deck() lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id), deck=deck) lobby_message = LobbyMessage([callback.message.chat.full_name]) - bot_message = await callback.message.edit_text(text=str(lobby_message), reply_markup=lobby_message.keyboard) - await callback.answer(text='Вы создали лобби!') + lobby_message.update_ready_info(ready=0, user=users_database.get_user_name(chat_id=callback.message.chat.id)) await state.set_state(FSMLobbyClass.in_lobby) await state.update_data(lobby=lobby_id, ready=0, lobby_message=lobby_message) await users_database.delete_lobbies_page_message_id(chat_id=callback.message.chat.id) - users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) people_without_lobby = users_database.get_statistic_of_users_without_lobby() lobby_pages = create_lobbies_page() keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') @@ -278,3 +228,6 @@ async def create_new_lobby(callback: CallbackQuery, reply_markup=keyboard) except TelegramBadRequest: pass + bot_message = await callback.message.edit_text(text=str(lobby_message), reply_markup=lobby_message.keyboard) + await callback.answer(text='Вы создали лобби!') + users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) diff --git a/services/services.py b/services/services.py index f4fd103..65551ce 100644 --- a/services/services.py +++ b/services/services.py @@ -21,8 +21,10 @@ class FSMLobbyClass(StatesGroup): game_message_id = State() -def create_user_list_for_lobby(users: list): - users_list_for_lobby = '\n'.join([f'{i}. {users[i-1]}' if i <= len(users) else f'{i}. Ждем игрока' for i in range(1, 5)]) +def create_user_list_for_lobby(users: list, ready_dict: dict): + users_list_for_lobby = ( + '\n'.join([f'{i}. {users[i-1]} - {"Готов" if ready_dict[users[i-1]] else "Не готов"}' if i <= len(users) else + f'{i}. Ждем игрока' for i in range(1, 5)])) return users_list_for_lobby @@ -74,21 +76,34 @@ class LobbyMessage: ready_text = 'Вы не готовы!\n\n' lobby_keyboard_buttons = {'ready': 'Приготовиться', 'exit': 'Выйти'} keyboard = create_inline_kb(dct=lobby_keyboard_buttons, width=1) + ready_dict = {} def __init__(self, users: list): self.users = users def __str__(self): - users_list = create_user_list_for_lobby(self.users) + users_list = create_user_list_for_lobby(users=self.users, ready_dict=self.ready_dict) lobby_text = self.ready_text + f'Участники лобби:\n{users_list}' return lobby_text def delete_user(self, user: str): self.users.remove(user) + self.ready_dict.pop(user) def add_user(self, user: str): self.users.append(user) + def update_ready_info(self, ready: int, user: str): + self.ready_dict[user] = ready + if ready == 1: + self.lobby_keyboard_buttons = {'exit': 'Выйти'} + self.keyboard = create_inline_kb(dct=self.lobby_keyboard_buttons, width=1) + self.ready_text = 'Вы готовы! \nОжидаем других игроков!\n\n' + else: + self.lobby_keyboard_buttons = {'ready': 'Приготовиться', 'exit': 'Выйти'} + self.keyboard = create_inline_kb(dct=self.lobby_keyboard_buttons, width=1) + self.ready_text = 'Вы не готовы!\n\n' + async def exit_lobby(state: FSMContext, data, bot, message: Message): await state.update_data(lobby=None) From 57f131027cb68be7acab401797544db4a1fbc4ff Mon Sep 17 00:00:00 2001 From: ilyak Date: Wed, 10 Jan 2024 20:33:44 +0500 Subject: [PATCH 10/14] 1 --- handlers/user_handlers.py | 26 +++++++++++++---- keyboards/keyboards.py | 11 +++++++- lexicon/lexicon.py | 2 +- services/services.py | 59 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 89 insertions(+), 9 deletions(-) diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index 2078d1a..8df99e1 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -1,4 +1,3 @@ -import aiogram.types from aiogram import Router, F from aiogram.exceptions import TelegramBadRequest from aiogram.filters import Command, StateFilter @@ -193,20 +192,35 @@ async def ready_command_others(callback: CallbackQuery, await lobby_database.update_deck(deck=deck, lobby_id=data['lobby']) await state.update_data(data=data) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - for chat_id in lobby_stat: - try: + all_users_ready = lobby_message.get_all_users_ready() + if all_users_ready: + for chat_id in lobby_stat: storage_data = await storage.get_data(StorageKey(bot_id=bot.id, chat_id=int(chat_id), user_id=int(chat_id))) + storage_data['lobby_message'] = None lobby_message = storage_data['lobby_message'] lobby_message.update_ready_info(ready=1, user=users_database.get_user_name(chat_id=callback.message.chat.id)) await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( - chat_id=chat_id), + chat_id=chat_id), reply_markup=lobby_message.keyboard) - except TelegramBadRequest: - pass + else: + for chat_id in lobby_stat: + try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + lobby_message = storage_data['lobby_message'] + lobby_message.update_ready_info(ready=1, + user=users_database.get_user_name(chat_id=callback.message.chat.id)) + await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=chat_id), + reply_markup=lobby_message.keyboard) + except TelegramBadRequest: + pass @router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) diff --git a/keyboards/keyboards.py b/keyboards/keyboards.py index 0b236b1..88c012f 100644 --- a/keyboards/keyboards.py +++ b/keyboards/keyboards.py @@ -58,7 +58,7 @@ def create_inline_kb(width: int, )) if back_button: kb_builder.row(InlineKeyboardButton( - text='Назад', + text=keyboard_lexicon[back_button] if back_button in keyboard_lexicon else 'Назад', callback_data=back_button )) return kb_builder.as_markup() @@ -70,3 +70,12 @@ class LobbyCallbackFactory(CallbackData, prefix='lobby', sep='|'): def __init__(self, lobby_id): super().__init__(lobby_id=lobby_id) + + +@dataclass +class CardsCallbackFactory(CallbackData, prefix='card', sep='|'): + face: str + color: str + + def __init__(self, face, color): + super().__init__(face=face, color=color) diff --git a/lexicon/lexicon.py b/lexicon/lexicon.py index 229fd0b..ee97bd3 100644 --- a/lexicon/lexicon.py +++ b/lexicon/lexicon.py @@ -6,7 +6,7 @@ '/ready': 'Приготовиться к игре' } -keyboard_lexicon = {'create_new_lobby': 'Новое лобби'} +keyboard_lexicon = {'create_new_lobby': 'Новое лобби', 'bito': 'Бито', 'beru': 'Беру', 'exit': 'Выйти'} lexicon_card_colors = {'♥️': 1, '♦️': 2, '♣️': 3, '♠️': 4} diff --git a/services/services.py b/services/services.py index 65551ce..43a2fbf 100644 --- a/services/services.py +++ b/services/services.py @@ -6,7 +6,7 @@ from aiogram.fsm.storage.base import StorageKey from aiogram.types import InlineKeyboardMarkup, Message from bot import users_database, lobby_database -from keyboards.keyboards import LobbyCallbackFactory, create_inline_kb +from keyboards.keyboards import LobbyCallbackFactory, create_inline_kb, CardsCallbackFactory class FSMLobbyClass(StatesGroup): @@ -34,6 +34,11 @@ def create_lobby_short_name(users): return lobby_short_name[:10]+'...' if len(lobby_short_name) > 12 else lobby_short_name +def create_game_keyboard_dict(cards: list): + return {CardsCallbackFactory(face=card.split('-')[0], color=card.split('-')[1]): + f'{" ".join(card.split("-"))}' for card in cards} + + def create_lobbies_page(): all_lobby_stat = lobby_database.get_all_lobby_stat() return {LobbyCallbackFactory(lobby_id=lobby[0]).pack(): @@ -104,6 +109,58 @@ def update_ready_info(self, ready: int, user: str): self.keyboard = create_inline_kb(dct=self.lobby_keyboard_buttons, width=1) self.ready_text = 'Вы не готовы!\n\n' + def get_all_users_ready(self): + values = self.ready_dict.values() + return all(values) and len(values) == 4 + + +class GameMessage: + def __init__(self, users: list, deck: list, royal_card: str): + self.users = users + self.deck = deck + self.royal_card = royal_card + + cards_on_table = [] + user_from_index = 0 + user_to_index = 1 + user_from = 0 + user_to = 0 + users_cards = {} + users_wined = [] + user_from_bito = 0 + + def next_user(self): + self.user_from = self.users[self.user_from_index] + self.user_to = self.users[self.user_to_index] + self.user_from_index = (self.user_from_index + 1) % 4 + self.user_to_index = (self.user_to_index + 1) % 4 + + def update_user_cards(self, user_chat_id: int, user_cards: list): + self.users_cards[user_chat_id] = user_cards + + def delete_user_card(self, card: str, user_chat_id: int): + cards = self.users_cards[user_chat_id] + cards.remove(card) + self.users_cards[user_chat_id] = cards + + def create_game_keyboard(self, chat_id: int): + if self.user_from == chat_id: + dct = create_game_keyboard_dict(self.users_cards[chat_id]) + if self.cards_on_table: + return create_inline_kb(width=1, dct=dct, last_btn='bito', back_button='exit') + else: + return create_inline_kb(width=1, dct=dct, back_button='exit') + if self.user_to == chat_id: + dct = create_game_keyboard_dict(self.users_cards[chat_id]) + if self.cards_on_table: + return create_inline_kb(width=1, dct=dct, last_btn='beru', back_button='exit') + else: + return create_inline_kb(width=1, dct={'exit': 'Выйти'}, back_button='exit') + if self.user_from_bito: + dct = create_game_keyboard_dict(self.users_cards[chat_id]) + return create_inline_kb(width=1, dct=dct, last_btn='bito', back_button='exit') + return create_inline_kb(width=1, back_button='exit') + async def exit_lobby(state: FSMContext, data, bot, message: Message): await state.update_data(lobby=None) From f4a1cc48b63e3004fcf546f6fd4ad4e9bc92b609 Mon Sep 17 00:00:00 2001 From: ilyak Date: Thu, 11 Jan 2024 22:54:09 +0500 Subject: [PATCH 11/14] 1 --- data/sql_database.py | 35 +++----- handlers/user_handlers.py | 169 +++++++++++++++++++------------------- services/services.py | 99 ++++++++++++++-------- 3 files changed, 161 insertions(+), 142 deletions(-) diff --git a/data/sql_database.py b/data/sql_database.py index f41f5ee..5508f7d 100644 --- a/data/sql_database.py +++ b/data/sql_database.py @@ -11,8 +11,7 @@ async def create_table(self): cur = conn.cursor() cur.execute(f"""CREATE TABLE IF NOT EXISTS {self.name} (lobby_id BIGSERIAL PRIMARY KEY, - users TEXT, - deck TEXT); + users TEXT); """) conn.commit() cur.close() @@ -23,9 +22,9 @@ async def enter_lobby(self, lobby_id: int, user_chat_id: str): cur.execute(f"""SELECT users FROM {self.name} WHERE lobby_id={lobby_id}; """) - pairs = cur.fetchone()[0].split('~~~') - pairs.append(f"""{user_chat_id}""") - cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(pairs)}' WHERE lobby_id={lobby_id};""") + users = cur.fetchone()[0].split('~~~') + users.append(f"""{user_chat_id}""") + cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(users)}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() @@ -34,9 +33,9 @@ async def exit_lobby(self, lobby_id: int, user_chat_id: str): cur.execute(f"""SELECT users FROM {self.name} WHERE lobby_id={lobby_id}; """) - pairs = cur.fetchone()[0].split('~~~') - pairs.remove(f"""{user_chat_id}""") - cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(pairs)}' WHERE lobby_id={lobby_id};""") + users = cur.fetchone()[0].split('~~~') + users.remove(f"""{user_chat_id}""") + cur.execute(f"""UPDATE {self.name} SET users='{'~~~'.join(users)}' WHERE lobby_id={lobby_id};""") conn.commit() cur.close() @@ -49,9 +48,9 @@ def get_lobby_stat(self, lobby_id: int): cur.close() return s - def create_new_lobby(self, user_chat_id: str, deck: str): + def create_new_lobby(self, user_chat_id: str): cur = conn.cursor() - cur.execute(f"""INSERT INTO {self.name} (users, deck) VALUES ('{user_chat_id}', '{deck}')""") + cur.execute(f"""INSERT INTO {self.name} (users) VALUES ('{user_chat_id}')""") cur.execute(f"""SELECT lobby_id FROM {self.name} WHERE users='{user_chat_id}';""") lobby_id = cur.fetchone()[0] @@ -71,20 +70,6 @@ async def delete_lobby(self, lobby_id: int): conn.commit() cur.close() - def get_lobby_deck(self, lobby_id): - cur = conn.cursor() - cur.execute(f"""SELECT deck FROM {self.name} WHERE lobby_id={lobby_id}""") - deck = cur.fetchone()[0] - conn.commit() - cur.close() - return deck - - async def update_deck(self, deck, lobby_id): - cur = conn.cursor() - cur.execute(f"""UPDATE {self.name} SET deck='{deck}' WHERE lobby_id={lobby_id};""") - conn.commit() - cur.close() - class UsersDatabase: def __init__(self, name): @@ -170,7 +155,7 @@ def update_user_balance(self, chat_id: int, balance: int): conn.commit() cur.close() - def update_game_page_message_id(self, chat_id, message_id): + async def update_game_page_message_id(self, chat_id, message_id): cur = conn.cursor() cur.execute(f"""UPDATE {self.name} SET game_page_message_id={message_id} WHERE chat_id={chat_id};""") conn.commit() diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index 8df99e1..3b7bf76 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -8,10 +8,9 @@ from aiogram.fsm.context import FSMContext from aiogram.fsm.state import default_state from services.services import exit_lobby, FSMLobbyClass, create_lobbies_page, create_deck, LobbyMessage, \ - update_previous_pages, get_next_cards + update_previous_pages, GameMessage, lobbies_messages_dict, games_messages_dict from datetime import datetime from lexicon.lexicon import lexicon_menu_keyboard, lexicon_user_statistic -from copy import deepcopy router = Router() @@ -29,20 +28,19 @@ async def start(message: Message, game_message_id = await message.answer(text='Это тренировочный бот для игры в Дурака с другими людьми.\n' 'Для начала перейдите в главное меню', reply_markup=keyboard) - await state.update_data(previous_pages=[], game_message_id=game_message_id.message_id) + await state.update_data(previous_pages=[], game_message_id=game_message_id.message_id, + user_name=users_database.get_user_name(chat_id=message.chat.id)) @router.callback_query(F.data == 'menu', StateFilter(default_state, FSMLobbyClass.select_lobby)) async def menu(callback: CallbackQuery, state: FSMContext): data = await state.get_data() - data_callback = callback.data - data = update_previous_pages(data, data_callback) - await state.update_data(data=data) await state.set_state(default_state) keyboard = create_inline_kb(dct=lexicon_menu_keyboard, width=1) await callback.message.edit_text(text='Вы находитесь в главном меню', reply_markup=keyboard) data['previous_pages'].append(callback.data) + await state.update_data(data=data) @router.callback_query(F.data == 'statistics', StateFilter(default_state)) @@ -51,11 +49,11 @@ async def statistic(callback: CallbackQuery, data = await state.get_data() data_callback = callback.data data = update_previous_pages(data, data_callback) - await state.update_data(data=data) user_stat = users_database.get_user_statistic(chat_id=callback.message.chat.id) keyboard = create_inline_kb(width=1, back_button=data['previous_pages'][-1]) await callback.message.edit_text(text=lexicon_user_statistic.format(*user_stat), reply_markup=keyboard) data['previous_pages'].append(callback.data) + await state.update_data(previous_pages=data['previous_pages']) @router.callback_query(F.data == 'free_reward', StateFilter(default_state)) @@ -85,7 +83,6 @@ async def lobbies(callback: CallbackQuery, data = await state.get_data() data_callback = callback.data data = update_previous_pages(data, data_callback) - await state.update_data(data=data) await state.set_state(FSMLobbyClass.select_lobby) if data.get('lobby'): await exit_lobby(state=state, data=data, bot=bot, message=callback.message) @@ -96,6 +93,7 @@ async def lobbies(callback: CallbackQuery, await users_database.update_lobbies_page_message_id(chat_id=callback.message.chat.id, lobbies_page_message_id=bot_message.message_id) data['previous_pages'].append(callback.data) + await state.update_data(previous_pages=data['previous_pages']) @router.callback_query(LobbyCallbackFactory.filter(), StateFilter(FSMLobbyClass.select_lobby)) @@ -104,45 +102,49 @@ async def lobby_page(callback: CallbackQuery, state: FSMContext): lobby_stat = lobby_database.get_lobby_stat(callback_data.lobby_id) if len(lobby_stat) < 4: - users_name = users_database.get_user_name(chat_id=callback.message.chat.id) - lobby_user_ids = deepcopy(lobby_stat) - lobby_user_ids.append(callback.message.chat.id) - lobby_message_1 = LobbyMessage([users_database.get_user_name(chat_id) for chat_id in lobby_user_ids]) + data = await state.get_data() + user_name = data['user_name'] await users_database.delete_lobbies_page_message_id(chat_id=callback.message.chat.id) people_without_lobby = users_database.get_statistic_of_users_without_lobby() - storage = state.storage lobby_pages = create_lobbies_page() - for chat_id in lobby_stat: - try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) - lobby_message = storage_data['lobby_message'] - lobby_message.add_user(users_name) - await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, - message_id=users_database.get_user_game_page_message_id( - chat_id=chat_id), - reply_markup=lobby_message.keyboard) - except TelegramBadRequest: - pass - storage = state.storage - for chat_id, message_id in people_without_lobby: - try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) - keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', - back_button=storage_data['previous_pages'][-1]) - await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, - reply_markup=keyboard) - except TelegramBadRequest: - pass - await lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, user_chat_id=str(callback.message.chat.id)) - await state.set_state(FSMLobbyClass.in_lobby) - await state.update_data(lobby=callback_data.lobby_id, lobby_message=lobby_message_1, ready=0) - bot_message = await callback.message.edit_text(text=str(lobby_message_1), reply_markup=lobby_message_1.keyboard) - await callback.answer(text='Вы зашли в лобби!') - users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) + lobby_message = lobbies_messages_dict.get(callback_data.lobby_id) + lobby_message.update_ready_info(ready=0, user=user_name) + game_message = games_messages_dict[callback_data.lobby_id] + game_message.update_user_name(chat_id=callback.message.chat.id, user_name=user_name) + game_message.add_user(callback.message.chat.id) + if lobby_message: + lobby_message.add_user(user_name) + for chat_id in lobby_stat: + try: + await bot.edit_message_text(text=lobby_message.return_message(user_name), chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=chat_id), + reply_markup=lobby_message.create_keyboard(user_name)) + except TelegramBadRequest: + pass + storage = state.storage + for chat_id, message_id in people_without_lobby: + try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', + back_button=storage_data['previous_pages'][-1]) + await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, + reply_markup=keyboard) + except TelegramBadRequest: + pass + await lobby_database.enter_lobby(lobby_id=callback_data.lobby_id, + user_chat_id=str(callback.message.chat.id)) + await state.set_state(FSMLobbyClass.in_lobby) + await state.update_data(lobby=callback_data.lobby_id, ready=0) + bot_message = await callback.message.edit_text(text=lobby_message.return_message(user_name), + reply_markup=lobby_message.create_keyboard(user_name)) + await callback.answer(text='Вы зашли в лобби!') + await users_database.update_game_page_message_id(chat_id=callback.message.chat.id, + message_id=bot_message.message_id) + else: + await callback.answer('Лобби не существует') else: await callback.answer('Лобби заполнено') @@ -153,13 +155,8 @@ async def exit_command(callback: CallbackQuery, data = await state.get_data() data_callback = callback.data data = update_previous_pages(data, data_callback) - await state.update_data(data=data) await state.set_state(FSMLobbyClass.select_lobby) - lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - if not len(lobby_stat[0]): - await lobby_database.delete_lobby(data['lobby']) - else: - await exit_lobby(state=state, bot=bot, message=callback.message, data=data) + await exit_lobby(state=state, bot=bot, message=callback.message, data=data) lobby_pages = create_lobbies_page() keyboards = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', back_button=data['previous_pages'][-1]) @@ -180,68 +177,74 @@ async def exit_command(callback: CallbackQuery, async def ready_command_others(callback: CallbackQuery, state: FSMContext): data = await state.get_data() - if not data['ready']: - lobby_message = data['lobby_message'] - lobby_message.update_ready_info(ready=1, user=users_database.get_user_name(chat_id=callback.message.chat.id)) + if data['ready'] == 0: + await state.update_data(ready=1) + user_name = data['user_name'] + lobby_message = lobbies_messages_dict[data['lobby']] + game_message = games_messages_dict[data['lobby']] + game_message.give_next_cards_to_user(user_chat_id=callback.message.chat.id, value=6) + game_message.update_user_name(chat_id=callback.message.chat.id, user_name=user_name) + lobby_message.update_ready_info(ready=1, user=user_name) storage = state.storage - deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']) - cards = get_next_cards(deck=deck, cards_num=6) - data['ready'] = 1 - data['current_cards'] = cards[0] - deck = '~~~'.join(cards[1]) - await lobby_database.update_deck(deck=deck, lobby_id=data['lobby']) - await state.update_data(data=data) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) all_users_ready = lobby_message.get_all_users_ready() if all_users_ready: + game_message.next_user() for chat_id in lobby_stat: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) - storage_data['lobby_message'] = None - lobby_message = storage_data['lobby_message'] - lobby_message.update_ready_info(ready=1, - user=users_database.get_user_name(chat_id=callback.message.chat.id)) - await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, + await bot.edit_message_text(text='Игра началась!', + chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( - chat_id=chat_id), - reply_markup=lobby_message.keyboard) + chat_id=chat_id), + reply_markup=None) + await bot.send_message(text=str(game_message), + chat_id=chat_id, + reply_markup=game_message.create_game_keyboard(chat_id=chat_id)) else: for chat_id in lobby_stat: try: storage_data = await storage.get_data(StorageKey(bot_id=bot.id, chat_id=int(chat_id), user_id=int(chat_id))) - lobby_message = storage_data['lobby_message'] - lobby_message.update_ready_info(ready=1, - user=users_database.get_user_name(chat_id=callback.message.chat.id)) - await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, + await bot.edit_message_text(text=lobby_message.return_message(storage_data['user_name']), + chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=chat_id), - reply_markup=lobby_message.keyboard) - except TelegramBadRequest: - pass + reply_markup=lobby_message.create_keyboard(storage_data['user_name'])) + except TelegramBadRequest as e: + print(e) + else: + await callback.answer('Вы уже готовы!') @router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) async def create_new_lobby(callback: CallbackQuery, state: FSMContext): deck = create_deck() - lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id), deck=deck) + data = await state.get_data() + user_name = data['user_name'] + lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id)) lobby_message = LobbyMessage([callback.message.chat.full_name]) - lobby_message.update_ready_info(ready=0, user=users_database.get_user_name(chat_id=callback.message.chat.id)) + game_message = GameMessage(users=[callback.message.chat.id], + deck=deck, + royal_card=deck[-1]) + lobby_message.update_ready_info(ready=0, user=user_name) await state.set_state(FSMLobbyClass.in_lobby) - await state.update_data(lobby=lobby_id, ready=0, lobby_message=lobby_message) + await state.update_data(lobby=lobby_id, ready=0) await users_database.delete_lobbies_page_message_id(chat_id=callback.message.chat.id) people_without_lobby = users_database.get_statistic_of_users_without_lobby() lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby') + keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', back_button='lobbies') for chat_id, message_id in people_without_lobby: try: await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: pass - bot_message = await callback.message.edit_text(text=str(lobby_message), reply_markup=lobby_message.keyboard) + bot_message = await callback.message.edit_text(text=lobby_message.return_message(user_name), + reply_markup=lobby_message.create_keyboard(user_name)) await callback.answer(text='Вы создали лобби!') - users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) + await users_database.update_game_page_message_id(chat_id=callback.message.chat.id, + message_id=bot_message.message_id) + lobbies_messages_dict[lobby_id] = lobby_message + games_messages_dict[lobby_id] = game_message + game_message.update_user_name(chat_id=callback.message.chat.id, user_name=user_name) diff --git a/services/services.py b/services/services.py index 43a2fbf..5661a42 100644 --- a/services/services.py +++ b/services/services.py @@ -9,6 +9,10 @@ from keyboards.keyboards import LobbyCallbackFactory, create_inline_kb, CardsCallbackFactory +lobbies_messages_dict = {} +games_messages_dict = {} + + class FSMLobbyClass(StatesGroup): select_lobby = State() in_lobby = State() @@ -17,8 +21,7 @@ class FSMLobbyClass(StatesGroup): lobby = State() current_cards = State() previous_pages = State() - lobby_message = State() - game_message_id = State() + user_name = State() def create_user_list_for_lobby(users: list, ready_dict: dict): @@ -69,26 +72,21 @@ def create_deck(): from random import shuffle deck = ["{}-{}".format(*card) for card in product(faces, colour)] shuffle(deck) - return '~~~'.join(deck) - - -def get_next_cards(deck, cards_num): - deck = deck.split('~~~') - return [deck[:cards_num], deck[cards_num:]] + return deck class LobbyMessage: - ready_text = 'Вы не готовы!\n\n' - lobby_keyboard_buttons = {'ready': 'Приготовиться', 'exit': 'Выйти'} - keyboard = create_inline_kb(dct=lobby_keyboard_buttons, width=1) + ready_text = 'Вы готовы!\n\n' + unready_text = 'Вы не готовы!\n\n' ready_dict = {} def __init__(self, users: list): self.users = users - def __str__(self): + def return_message(self, user: str): users_list = create_user_list_for_lobby(users=self.users, ready_dict=self.ready_dict) - lobby_text = self.ready_text + f'Участники лобби:\n{users_list}' + lobby_text = (self.ready_text if self.ready_dict.get(user) else self.unready_text) + (f'Участники лобби:\n' + f'{users_list}') return lobby_text def delete_user(self, user: str): @@ -100,18 +98,16 @@ def add_user(self, user: str): def update_ready_info(self, ready: int, user: str): self.ready_dict[user] = ready - if ready == 1: - self.lobby_keyboard_buttons = {'exit': 'Выйти'} - self.keyboard = create_inline_kb(dct=self.lobby_keyboard_buttons, width=1) - self.ready_text = 'Вы готовы! \nОжидаем других игроков!\n\n' - else: - self.lobby_keyboard_buttons = {'ready': 'Приготовиться', 'exit': 'Выйти'} - self.keyboard = create_inline_kb(dct=self.lobby_keyboard_buttons, width=1) - self.ready_text = 'Вы не готовы!\n\n' def get_all_users_ready(self): values = self.ready_dict.values() - return all(values) and len(values) == 4 + return all(values) and len(values) == 2 + + def create_keyboard(self, user: str): + if self.ready_dict.get(user) == 1: + return create_inline_kb(dct={'exit': 'Выйти'}, width=1) + else: + return create_inline_kb(dct={'ready': 'Приготовиться', 'exit': 'Выйти'}, width=1) class GameMessage: @@ -120,14 +116,29 @@ def __init__(self, users: list, deck: list, royal_card: str): self.deck = deck self.royal_card = royal_card - cards_on_table = [] + game_text = ('Ходит игрок: {}\n' + 'Кроется игрок: {}\n\n' + 'Карт в колоде: {}\n' + 'Козырная карта: {}\n') + cards_on_table_text = 'Карты на столе:\n' + users_text = 'Игроки:\n' + + def __str__(self): + user_from = self.users_names[self.user_from] + user_to = self.users_names[self.user_to] + cards_value = len(self.deck) + royal_card = self.royal_card + return self.game_text.format(user_from, user_to, cards_value, royal_card) + + cards_on_table = {} user_from_index = 0 user_to_index = 1 user_from = 0 user_to = 0 users_cards = {} users_wined = [] - user_from_bito = 0 + user_from_bito = False + users_names = {} def next_user(self): self.user_from = self.users[self.user_from_index] @@ -135,9 +146,6 @@ def next_user(self): self.user_from_index = (self.user_from_index + 1) % 4 self.user_to_index = (self.user_to_index + 1) % 4 - def update_user_cards(self, user_chat_id: int, user_cards: list): - self.users_cards[user_chat_id] = user_cards - def delete_user_card(self, card: str, user_chat_id: int): cards = self.users_cards[user_chat_id] cards.remove(card) @@ -161,22 +169,40 @@ def create_game_keyboard(self, chat_id: int): return create_inline_kb(width=1, dct=dct, last_btn='bito', back_button='exit') return create_inline_kb(width=1, back_button='exit') + def give_next_cards_to_user(self, user_chat_id: int, value: int): + if self.users_cards.get(user_chat_id): + if len(self.deck) <= value: + self.users_cards[user_chat_id].extend(self.deck) + self.deck = [] + else: + self.users_cards[user_chat_id].extend(self.deck[:value]) + self.deck = self.deck[value:] + else: + if len(self.deck) <= value: + self.users_cards[user_chat_id] = self.deck + self.deck = [] + else: + self.users_cards[user_chat_id] = self.deck[:value] + self.deck = self.deck[value:] + + def update_user_name(self, chat_id: int, user_name: str): + self.users_names[chat_id] = user_name + + def add_user(self, user_chat_id: int): + self.users.append(user_chat_id) + async def exit_lobby(state: FSMContext, data, bot, message: Message): await state.update_data(lobby=None) await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id)) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - storage = state.storage if lobby_stat[0] == '': await lobby_database.delete_lobby(data['lobby']) else: + lobby_message = lobbies_messages_dict.get(data['lobby']) + lobby_message.delete_user(data['user_name']) for chat_id in lobby_stat: try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) - lobby_message = storage_data['lobby_message'] - lobby_message.delete_user(users_database.get_user_name(chat_id=chat_id)) await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=message.chat.id), @@ -184,10 +210,15 @@ async def exit_lobby(state: FSMContext, data, bot, message: Message): except TelegramBadRequest: pass lobby_pages = create_lobbies_page() - keyboard = create_inline_kb(width=2, dct=lobby_pages) + storage = state.storage people_without_lobby = users_database.get_statistic_of_users_without_lobby() for chat_id, message_id in people_without_lobby: try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', + back_button=storage_data['previous_pages'][-1]) await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: From 74f16cb4ad12e39edfc0f36979f0b61d48ea372e Mon Sep 17 00:00:00 2001 From: ilyak Date: Sat, 13 Jan 2024 15:54:46 +0500 Subject: [PATCH 12/14] 1 --- handlers/user_handlers.py | 51 +++++++++------ lexicon/lexicon.py | 2 +- services/services.py | 131 ++++++++++++++++++++++++++++---------- 3 files changed, 127 insertions(+), 57 deletions(-) diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index 3b7bf76..0c4747d 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -25,10 +25,10 @@ async def start(message: Message, await exit_lobby(state=state, data=data, bot=bot, message=message) await state.set_state(default_state) keyboard = create_inline_kb(dct={'menu': 'Главное меню'}, width=1) - game_message_id = await message.answer(text='Это тренировочный бот для игры в Дурака с другими людьми.\n' - 'Для начала перейдите в главное меню', - reply_markup=keyboard) - await state.update_data(previous_pages=[], game_message_id=game_message_id.message_id, + await message.answer(text='Это тренировочный бот для игры в Дурака с другими людьми.\n' + 'Для начала перейдите в главное меню', + reply_markup=keyboard) + await state.update_data(previous_pages=[], user_name=users_database.get_user_name(chat_id=message.chat.id)) @@ -109,20 +109,21 @@ async def lobby_page(callback: CallbackQuery, lobby_pages = create_lobbies_page() lobby_message = lobbies_messages_dict.get(callback_data.lobby_id) lobby_message.update_ready_info(ready=0, user=user_name) - game_message = games_messages_dict[callback_data.lobby_id] - game_message.update_user_name(chat_id=callback.message.chat.id, user_name=user_name) - game_message.add_user(callback.message.chat.id) + storage = state.storage if lobby_message: lobby_message.add_user(user_name) for chat_id in lobby_stat: try: - await bot.edit_message_text(text=lobby_message.return_message(user_name), chat_id=chat_id, + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + await bot.edit_message_text(text=lobby_message.return_message(storage_data['user_name']), + chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=chat_id), - reply_markup=lobby_message.create_keyboard(user_name)) + reply_markup=lobby_message.create_keyboard(storage_data['user_name'])) except TelegramBadRequest: pass - storage = state.storage for chat_id, message_id in people_without_lobby: try: storage_data = await storage.get_data(StorageKey(bot_id=bot.id, @@ -155,7 +156,6 @@ async def exit_command(callback: CallbackQuery, data = await state.get_data() data_callback = callback.data data = update_previous_pages(data, data_callback) - await state.set_state(FSMLobbyClass.select_lobby) await exit_lobby(state=state, bot=bot, message=callback.message, data=data) lobby_pages = create_lobbies_page() keyboards = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', @@ -164,6 +164,7 @@ async def exit_command(callback: CallbackQuery, bot_message = await callback.message.edit_text(text='Список доступных лобби', reply_markup=keyboards) await users_database.update_lobbies_page_message_id(chat_id=callback.message.chat.id, lobbies_page_message_id=bot_message.message_id) + await state.set_state(FSMLobbyClass.select_lobby) data['previous_pages'].append(callback.data) if data.get('current_cards'): lobby_deck = lobby_database.get_lobby_deck(lobby_id=data['lobby']).split('~~~') @@ -181,9 +182,17 @@ async def ready_command_others(callback: CallbackQuery, await state.update_data(ready=1) user_name = data['user_name'] lobby_message = lobbies_messages_dict[data['lobby']] - game_message = games_messages_dict[data['lobby']] - game_message.give_next_cards_to_user(user_chat_id=callback.message.chat.id, value=6) + if games_messages_dict.get(data['lobby']): + game_message = games_messages_dict[data['lobby']] + game_message.add_user(callback.message.chat.id) + else: + deck = create_deck() + game_message = GameMessage(users=[callback.message.chat.id], + deck=deck, + royal_card=' '.join(deck[-1].split('-'))) + games_messages_dict[data['lobby']] = game_message game_message.update_user_name(chat_id=callback.message.chat.id, user_name=user_name) + game_message.give_next_cards_to_user(user_chat_id=callback.message.chat.id, value=6) lobby_message.update_ready_info(ready=1, user=user_name) storage = state.storage lobby_stat = lobby_database.get_lobby_stat(data['lobby']) @@ -191,6 +200,10 @@ async def ready_command_others(callback: CallbackQuery, if all_users_ready: game_message.next_user() for chat_id in lobby_stat: + await storage.set_state(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id)), + state=FSMLobbyClass.in_game) await bot.edit_message_text(text='Игра началась!', chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( @@ -198,7 +211,7 @@ async def ready_command_others(callback: CallbackQuery, reply_markup=None) await bot.send_message(text=str(game_message), chat_id=chat_id, - reply_markup=game_message.create_game_keyboard(chat_id=chat_id)) + reply_markup=game_message.create_game_keyboard(chat_id=int(chat_id))) else: for chat_id in lobby_stat: try: @@ -219,17 +232,15 @@ async def ready_command_others(callback: CallbackQuery, @router.callback_query(F.data == 'create_new_lobby', StateFilter(FSMLobbyClass.select_lobby)) async def create_new_lobby(callback: CallbackQuery, state: FSMContext): - deck = create_deck() data = await state.get_data() user_name = data['user_name'] lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id)) + data['lobby'] = lobby_id + data['ready'] = 0 lobby_message = LobbyMessage([callback.message.chat.full_name]) - game_message = GameMessage(users=[callback.message.chat.id], - deck=deck, - royal_card=deck[-1]) lobby_message.update_ready_info(ready=0, user=user_name) await state.set_state(FSMLobbyClass.in_lobby) - await state.update_data(lobby=lobby_id, ready=0) + await state.update_data(data=data) await users_database.delete_lobbies_page_message_id(chat_id=callback.message.chat.id) people_without_lobby = users_database.get_statistic_of_users_without_lobby() lobby_pages = create_lobbies_page() @@ -246,5 +257,3 @@ async def create_new_lobby(callback: CallbackQuery, await users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) lobbies_messages_dict[lobby_id] = lobby_message - games_messages_dict[lobby_id] = game_message - game_message.update_user_name(chat_id=callback.message.chat.id, user_name=user_name) diff --git a/lexicon/lexicon.py b/lexicon/lexicon.py index ee97bd3..7202316 100644 --- a/lexicon/lexicon.py +++ b/lexicon/lexicon.py @@ -13,7 +13,7 @@ lexicon_card_faces = {'6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'Валет': 11, 'Дама': 12, 'Король': 13, 'Туз': 14} lexicon_menu_keyboard = {'lobbies': 'Выбрать комнату', 'statistics': 'Статистика пользователя', - 'free_reward': 'Бесплатная награда', 'info': 'Информация о боте'} + 'free_reward': 'Бесплатная награда'} lexicon_user_statistic = ('Ваше имя: {}\n' 'Баланс: {}\n\n' diff --git a/services/services.py b/services/services.py index 5661a42..656d839 100644 --- a/services/services.py +++ b/services/services.py @@ -1,12 +1,14 @@ from typing import Optional from aiogram import Bot from aiogram.exceptions import TelegramBadRequest +from aiogram.filters import StateFilter from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from aiogram.fsm.storage.base import StorageKey from aiogram.types import InlineKeyboardMarkup, Message from bot import users_database, lobby_database from keyboards.keyboards import LobbyCallbackFactory, create_inline_kb, CardsCallbackFactory +from dataclasses import dataclass lobbies_messages_dict = {} @@ -38,7 +40,7 @@ def create_lobby_short_name(users): def create_game_keyboard_dict(cards: list): - return {CardsCallbackFactory(face=card.split('-')[0], color=card.split('-')[1]): + return {CardsCallbackFactory(face=card.split('-')[0], color=card.split('-')[1]).pack(): f'{" ".join(card.split("-"))}' for card in cards} @@ -75,13 +77,13 @@ def create_deck(): return deck +@dataclass class LobbyMessage: - ready_text = 'Вы готовы!\n\n' - unready_text = 'Вы не готовы!\n\n' - ready_dict = {} - def __init__(self, users: list): self.users = users + self.ready_text = 'Вы готовы!\n\n' + self.unready_text = 'Вы не готовы!\n\n' + self.ready_dict = {} def return_message(self, user: str): users_list = create_user_list_for_lobby(users=self.users, ready_dict=self.ready_dict) @@ -110,11 +112,21 @@ def create_keyboard(self, user: str): return create_inline_kb(dct={'ready': 'Приготовиться', 'exit': 'Выйти'}, width=1) +@dataclass class GameMessage: def __init__(self, users: list, deck: list, royal_card: str): self.users = users self.deck = deck self.royal_card = royal_card + self.cards_on_table = {} + self.user_from_index = 0 + self.user_to_index = 1 + self.user_from = 0 + self.user_to = 0 + self.users_cards = {} + self.users_wined = [] + self.user_from_bito = False + self.users_names = {} game_text = ('Ходит игрок: {}\n' 'Кроется игрок: {}\n\n' @@ -130,21 +142,12 @@ def __str__(self): royal_card = self.royal_card return self.game_text.format(user_from, user_to, cards_value, royal_card) - cards_on_table = {} - user_from_index = 0 - user_to_index = 1 - user_from = 0 - user_to = 0 - users_cards = {} - users_wined = [] - user_from_bito = False - users_names = {} - def next_user(self): self.user_from = self.users[self.user_from_index] self.user_to = self.users[self.user_to_index] self.user_from_index = (self.user_from_index + 1) % 4 self.user_to_index = (self.user_to_index + 1) % 4 + print(self.user_to, self.user_from, self.users) def delete_user_card(self, card: str, user_chat_id: int): cards = self.users_cards[user_chat_id] @@ -152,21 +155,25 @@ def delete_user_card(self, card: str, user_chat_id: int): self.users_cards[user_chat_id] = cards def create_game_keyboard(self, chat_id: int): - if self.user_from == chat_id: - dct = create_game_keyboard_dict(self.users_cards[chat_id]) + if str(self.user_from) == str(chat_id): if self.cards_on_table: - return create_inline_kb(width=1, dct=dct, last_btn='bito', back_button='exit') + return create_inline_kb(width=1, dct=create_game_keyboard_dict(self.users_cards[chat_id]), + last_btn='bito', back_button='exit') else: - return create_inline_kb(width=1, dct=dct, back_button='exit') - if self.user_to == chat_id: - dct = create_game_keyboard_dict(self.users_cards[chat_id]) + return create_inline_kb(width=1, + dct=create_game_keyboard_dict(self.users_cards[chat_id]), + back_button='exit') + if str(self.user_to) == str(chat_id): if self.cards_on_table: - return create_inline_kb(width=1, dct=dct, last_btn='beru', back_button='exit') + return create_inline_kb(width=1, + dct=create_game_keyboard_dict(self.users_cards[chat_id]), last_btn='beru', + back_button='exit') else: - return create_inline_kb(width=1, dct={'exit': 'Выйти'}, back_button='exit') + return create_inline_kb(width=1, back_button='exit') if self.user_from_bito: - dct = create_game_keyboard_dict(self.users_cards[chat_id]) - return create_inline_kb(width=1, dct=dct, last_btn='bito', back_button='exit') + return create_inline_kb(width=1, + dct=create_game_keyboard_dict(self.users_cards[chat_id]), last_btn='bito', + back_button='exit') return create_inline_kb(width=1, back_button='exit') def give_next_cards_to_user(self, user_chat_id: int, value: int): @@ -184,6 +191,7 @@ def give_next_cards_to_user(self, user_chat_id: int, value: int): else: self.users_cards[user_chat_id] = self.deck[:value] self.deck = self.deck[value:] + print(self.users_cards) def update_user_name(self, chat_id: int, user_name: str): self.users_names[chat_id] = user_name @@ -191,27 +199,80 @@ def update_user_name(self, chat_id: int, user_name: str): def add_user(self, user_chat_id: int): self.users.append(user_chat_id) + def delete_user(self, user_chat_id: int, is_add_cards: int): + if is_add_cards: + deleted_cards = self.users_cards.pop(user_chat_id, []) + print(deleted_cards) + self.deck = deleted_cards + self.deck + self.users.remove(user_chat_id) + del self.users_names[user_chat_id] + async def exit_lobby(state: FSMContext, data, bot, message: Message): - await state.update_data(lobby=None) await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id)) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + storage = state.storage if lobby_stat[0] == '': + del lobbies_messages_dict[data['lobby']] + games_messages_dict[data['lobby']] = None await lobby_database.delete_lobby(data['lobby']) else: lobby_message = lobbies_messages_dict.get(data['lobby']) lobby_message.delete_user(data['user_name']) - for chat_id in lobby_stat: - try: - await bot.edit_message_text(text=str(lobby_message), chat_id=chat_id, - message_id=users_database.get_user_game_page_message_id( - chat_id=message.chat.id), - reply_markup=lobby_message.keyboard) - except TelegramBadRequest: - pass + st = await state.get_state() + if st == FSMLobbyClass.in_lobby: + print(0) + if games_messages_dict.get(data['lobby']): + game_message = games_messages_dict[data['lobby']] + if message.chat.id in game_message.users: + game_message.delete_user(message.chat.id, 1) + + for chat_id in lobby_stat: + try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + await bot.edit_message_text(text=lobby_message.return_message(storage_data['user_name']), + chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=chat_id), + reply_markup=lobby_message.create_keyboard(storage_data['user_name'])) + except TelegramBadRequest: + pass + if st == FSMLobbyClass.in_game: + print(1) + game_message = games_messages_dict.get(data['lobby']) + if message.chat.id in game_message.users_wined: + game_message.delete_user(message.chat.id, 0) + for chat_id in lobby_stat: + try: + await bot.edit_message_text(text=str(game_message), chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=message.chat.id), + reply_markup=game_message.create_game_keyboard(chat_id= + int(chat_id))) + except TelegramBadRequest: + pass + else: + games_messages_dict[data['lobby']] = None + for chat_id in lobby_stat: + try: + storage_data = await storage.get_data(StorageKey(bot_id=bot.id, + chat_id=int(chat_id), + user_id=int(chat_id))) + lobby_message.update_ready_info(ready=0, user=storage_data['user_name']) + await bot.edit_message_text(text=f'Игрок {data["user_name"]} покинул игру', chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=message.chat.id), + reply_markup=None) + await bot.send_message(text=lobby_message.return_message(data['user_name']), + chat_id=chat_id, + reply_markup=lobby_message.create_keyboard(data['user_name'])) + except TelegramBadRequest: + pass lobby_pages = create_lobbies_page() - storage = state.storage people_without_lobby = users_database.get_statistic_of_users_without_lobby() + await state.update_data(lobby=None) for chat_id, message_id in people_without_lobby: try: storage_data = await storage.get_data(StorageKey(bot_id=bot.id, From 9ae0d1ba5113319e6167ec0f532a513ae7a88444 Mon Sep 17 00:00:00 2001 From: ilyak Date: Sat, 13 Jan 2024 23:51:05 +0500 Subject: [PATCH 13/14] 1 --- handlers/user_handlers.py | 24 ++++++++---------------- services/services.py | 27 ++++++++++----------------- 2 files changed, 18 insertions(+), 33 deletions(-) diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index 0c4747d..e8952e9 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -109,28 +109,22 @@ async def lobby_page(callback: CallbackQuery, lobby_pages = create_lobbies_page() lobby_message = lobbies_messages_dict.get(callback_data.lobby_id) lobby_message.update_ready_info(ready=0, user=user_name) - storage = state.storage if lobby_message: lobby_message.add_user(user_name) for chat_id in lobby_stat: try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) - await bot.edit_message_text(text=lobby_message.return_message(storage_data['user_name']), + user_name = lobby_message.return_message(users_database.get_user_name(chat_id)) + await bot.edit_message_text(text=user_name, chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=chat_id), - reply_markup=lobby_message.create_keyboard(storage_data['user_name'])) + reply_markup=lobby_message.create_keyboard(user_name)) except TelegramBadRequest: pass for chat_id, message_id in people_without_lobby: try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', - back_button=storage_data['previous_pages'][-1]) + back_button='menu') await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: @@ -215,14 +209,12 @@ async def ready_command_others(callback: CallbackQuery, else: for chat_id in lobby_stat: try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) - await bot.edit_message_text(text=lobby_message.return_message(storage_data['user_name']), + user_name = lobby_message.return_message(users_database.get_user_name(chat_id)) + await bot.edit_message_text(text=lobby_message.return_message(user_name), chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=chat_id), - reply_markup=lobby_message.create_keyboard(storage_data['user_name'])) + reply_markup=lobby_message.create_keyboard(user_name)) except TelegramBadRequest as e: print(e) else: @@ -233,7 +225,7 @@ async def ready_command_others(callback: CallbackQuery, async def create_new_lobby(callback: CallbackQuery, state: FSMContext): data = await state.get_data() - user_name = data['user_name'] + user_name = users_database.get_user_name(chat_id=callback.message.chat.id) lobby_id = lobby_database.create_new_lobby(user_chat_id=str(callback.message.chat.id)) data['lobby'] = lobby_id data['ready'] = 0 diff --git a/services/services.py b/services/services.py index 656d839..3976818 100644 --- a/services/services.py +++ b/services/services.py @@ -1,7 +1,6 @@ from typing import Optional from aiogram import Bot from aiogram.exceptions import TelegramBadRequest -from aiogram.filters import StateFilter from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from aiogram.fsm.storage.base import StorageKey @@ -229,14 +228,12 @@ async def exit_lobby(state: FSMContext, data, bot, message: Message): for chat_id in lobby_stat: try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) - await bot.edit_message_text(text=lobby_message.return_message(storage_data['user_name']), + user_name = lobby_message.return_message(users_database.get_user_name(chat_id)) + await bot.edit_message_text(text=lobby_message.return_message(user_name), chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=chat_id), - reply_markup=lobby_message.create_keyboard(storage_data['user_name'])) + reply_markup=lobby_message.create_keyboard(user_name)) except TelegramBadRequest: pass if st == FSMLobbyClass.in_game: @@ -249,23 +246,22 @@ async def exit_lobby(state: FSMContext, data, bot, message: Message): await bot.edit_message_text(text=str(game_message), chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=message.chat.id), - reply_markup=game_message.create_game_keyboard(chat_id= - int(chat_id))) + reply_markup=game_message.create_game_keyboard( + chat_id=int(chat_id)) + ) except TelegramBadRequest: pass else: games_messages_dict[data['lobby']] = None for chat_id in lobby_stat: try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) - lobby_message.update_ready_info(ready=0, user=storage_data['user_name']) + user_name = lobby_message.return_message(users_database.get_user_name(chat_id)) + lobby_message.update_ready_info(ready=0, user=user_name) await bot.edit_message_text(text=f'Игрок {data["user_name"]} покинул игру', chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( chat_id=message.chat.id), reply_markup=None) - await bot.send_message(text=lobby_message.return_message(data['user_name']), + await bot.send_message(text=lobby_message.return_message(user_name), chat_id=chat_id, reply_markup=lobby_message.create_keyboard(data['user_name'])) except TelegramBadRequest: @@ -275,11 +271,8 @@ async def exit_lobby(state: FSMContext, data, bot, message: Message): await state.update_data(lobby=None) for chat_id, message_id in people_without_lobby: try: - storage_data = await storage.get_data(StorageKey(bot_id=bot.id, - chat_id=int(chat_id), - user_id=int(chat_id))) keyboard = create_inline_kb(width=2, dct=lobby_pages, last_btn='create_new_lobby', - back_button=storage_data['previous_pages'][-1]) + back_button='menu') await bot.edit_message_reply_markup(chat_id=chat_id, message_id=message_id, reply_markup=keyboard) except TelegramBadRequest: From 962f4b44f56cd9a6dab16c0acd933fdd3c089aeb Mon Sep 17 00:00:00 2001 From: ilyak Date: Thu, 18 Jan 2024 20:15:58 +0500 Subject: [PATCH 14/14] 1 --- bot.py | 3 ++ handlers/user_handlers.py | 71 ++++++++++++++++++++++++++++++++++----- keyboards/keyboards.py | 5 +-- services/services.py | 70 +++++++++++++++++++++++++++++--------- 4 files changed, 123 insertions(+), 26 deletions(-) diff --git a/bot.py b/bot.py index 4e51949..5f808fd 100644 --- a/bot.py +++ b/bot.py @@ -2,6 +2,7 @@ import asyncio from aiogram import Bot, Dispatcher +from aiogram.fsm.storage.redis import RedisStorage, Redis from config.config import Config, load_config from handlers import user_handlers @@ -15,6 +16,8 @@ config: Config = load_config() bot = Bot(token=config.tg_bot.token, parse_mode='HTML') +redis = Redis(host='127.0.0.1:6379') +storage = RedisStorage(redis=redis) async def main(): diff --git a/handlers/user_handlers.py b/handlers/user_handlers.py index e8952e9..ec66622 100644 --- a/handlers/user_handlers.py +++ b/handlers/user_handlers.py @@ -4,11 +4,11 @@ from aiogram.fsm.storage.base import StorageKey from aiogram.types import Message, CallbackQuery from bot import bot, users_database, lobby_database -from keyboards.keyboards import create_inline_kb, LobbyCallbackFactory +from keyboards.keyboards import create_inline_kb, LobbyCallbackFactory, CardsCallbackFactory from aiogram.fsm.context import FSMContext from aiogram.fsm.state import default_state from services.services import exit_lobby, FSMLobbyClass, create_lobbies_page, create_deck, LobbyMessage, \ - update_previous_pages, GameMessage, lobbies_messages_dict, games_messages_dict + update_previous_pages, GameMessage, lobbies_messages_dict, games_messages_dict, get_valid_cards, get_valid_faces from datetime import datetime from lexicon.lexicon import lexicon_menu_keyboard, lexicon_user_statistic @@ -70,7 +70,7 @@ async def free_reward(callback: CallbackQuery): users_database.update_last_free_reward_date_timestamp(chat_id=callback.message.chat.id, last_free_reward_date_timestamp=current_date) else: - normal_date = datetime.fromtimestamp(last_date+3600) + normal_date = datetime.fromtimestamp(last_date + 3600) await callback.answer(text=f'Следующую награду можно получить в {normal_date.strftime("%X")}', show_alert=True) else: @@ -183,7 +183,7 @@ async def ready_command_others(callback: CallbackQuery, deck = create_deck() game_message = GameMessage(users=[callback.message.chat.id], deck=deck, - royal_card=' '.join(deck[-1].split('-'))) + royal_card=deck[-1]) games_messages_dict[data['lobby']] = game_message game_message.update_user_name(chat_id=callback.message.chat.id, user_name=user_name) game_message.give_next_cards_to_user(user_chat_id=callback.message.chat.id, value=6) @@ -203,13 +203,14 @@ async def ready_command_others(callback: CallbackQuery, message_id=users_database.get_user_game_page_message_id( chat_id=chat_id), reply_markup=None) - await bot.send_message(text=str(game_message), - chat_id=chat_id, - reply_markup=game_message.create_game_keyboard(chat_id=int(chat_id))) + bot_message = await bot.send_message(text=str(game_message), + chat_id=chat_id, + reply_markup=game_message.create_game_keyboard(chat_id=int(chat_id))) + await users_database.update_game_page_message_id(chat_id=chat_id, message_id=bot_message.message_id) else: for chat_id in lobby_stat: try: - user_name = lobby_message.return_message(users_database.get_user_name(chat_id)) + user_name = users_database.get_user_name(chat_id=int(chat_id)) await bot.edit_message_text(text=lobby_message.return_message(user_name), chat_id=chat_id, message_id=users_database.get_user_game_page_message_id( @@ -249,3 +250,57 @@ async def create_new_lobby(callback: CallbackQuery, await users_database.update_game_page_message_id(chat_id=callback.message.chat.id, message_id=bot_message.message_id) lobbies_messages_dict[lobby_id] = lobby_message + + +# GAME HANDLERS +@router.callback_query(CardsCallbackFactory.filter(), StateFilter(FSMLobbyClass.in_game)) +async def game_process(callback: CallbackQuery, + callback_data: CardsCallbackFactory, + state: FSMContext): + data = await state.get_data() + game_message = games_messages_dict[data['lobby']] + if callback_data.to_or_from == 'to': + if len(game_message.cards_on_table.values()): + if not all([1 if i != '' else 0 for i in game_message.cards_on_table.keys()]): + valid_cards = get_valid_cards(cards=[i[0] for i in game_message.cards_on_table.items() if i[1] == ''], + card=[callback_data.face, callback_data.color], + royal_card=game_message.royal_card) + if len(valid_cards) == 1: + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + game_message.cards_on_table[valid_cards[0]] = '-'.join([callback_data.face, callback_data.color]) + game_message.delete_user_card(card='-'.join([callback_data.face, callback_data.color]), + user_chat_id=callback.message.chat.id) + for chat_id in lobby_stat: + await bot.edit_message_text(text=str(game_message), + chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=chat_id), + reply_markup=game_message.create_game_keyboard(chat_id=int(chat_id))) + elif len(valid_cards) >= 2: + await callback.answer(text='Падажи 2 карты если можешь покрыть пока не работает') + else: + await callback.answer(text='Вы не можете покрыться этой картой') + else: + await callback.answer(text='Все карты покрыты') + else: + await callback.answer(text='Нет карт для покрытия') + else: + cards = list(game_message.cards_on_table.values()) + cards.extend(game_message.cards_on_table.keys()) + valid_faces = get_valid_faces(cards=cards) + if len(game_message.cards_on_table.items()) < len(game_message.users_cards[game_message.user_to]): + if callback_data.face in valid_faces or not len(game_message.cards_on_table.values()): + game_message.delete_user_card(card='-'.join([callback_data.face, callback_data.color]), + user_chat_id=callback.message.chat.id) + lobby_stat = lobby_database.get_lobby_stat(data['lobby']) + game_message.cards_on_table['-'.join([callback_data.face, callback_data.color])] = '' + for chat_id in lobby_stat: + await bot.edit_message_text(text=str(game_message), + chat_id=chat_id, + message_id=users_database.get_user_game_page_message_id( + chat_id=chat_id), + reply_markup=game_message.create_game_keyboard(chat_id=int(chat_id))) + else: + await callback.answer(text='Вы не можете подкинуть эту карту') + else: + await callback.answer(text='На столе достаточно карт!') diff --git a/keyboards/keyboards.py b/keyboards/keyboards.py index 88c012f..ff84fe1 100644 --- a/keyboards/keyboards.py +++ b/keyboards/keyboards.py @@ -76,6 +76,7 @@ def __init__(self, lobby_id): class CardsCallbackFactory(CallbackData, prefix='card', sep='|'): face: str color: str + to_or_from: str - def __init__(self, face, color): - super().__init__(face=face, color=color) + def __init__(self, face, color, to_or_from): + super().__init__(face=face, color=color, to_or_from=to_or_from) diff --git a/services/services.py b/services/services.py index 3976818..02afa4c 100644 --- a/services/services.py +++ b/services/services.py @@ -3,11 +3,11 @@ from aiogram.exceptions import TelegramBadRequest from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup -from aiogram.fsm.storage.base import StorageKey from aiogram.types import InlineKeyboardMarkup, Message from bot import users_database, lobby_database from keyboards.keyboards import LobbyCallbackFactory, create_inline_kb, CardsCallbackFactory from dataclasses import dataclass +from lexicon.lexicon import lexicon_card_faces, lexicon_card_colors lobbies_messages_dict = {} @@ -38,8 +38,9 @@ def create_lobby_short_name(users): return lobby_short_name[:10]+'...' if len(lobby_short_name) > 12 else lobby_short_name -def create_game_keyboard_dict(cards: list): - return {CardsCallbackFactory(face=card.split('-')[0], color=card.split('-')[1]).pack(): +def create_game_keyboard_dict(cards: list, to_or_from: str): + cards.sort(key=lambda x: (lexicon_card_colors[x.split('-')[1]], lexicon_card_faces[x.split('-')[0]])) + return {CardsCallbackFactory(face=card.split('-')[0], color=card.split('-')[1], to_or_from=to_or_from).pack(): f'{" ".join(card.split("-"))}' for card in cards} @@ -130,16 +131,18 @@ def __init__(self, users: list, deck: list, royal_card: str): game_text = ('Ходит игрок: {}\n' 'Кроется игрок: {}\n\n' 'Карт в колоде: {}\n' - 'Козырная карта: {}\n') - cards_on_table_text = 'Карты на столе:\n' - users_text = 'Игроки:\n' + 'Козырная карта: {}\n\n' + 'Карты на столе: {}') def __str__(self): user_from = self.users_names[self.user_from] user_to = self.users_names[self.user_to] cards_value = len(self.deck) - royal_card = self.royal_card - return self.game_text.format(user_from, user_to, cards_value, royal_card) + royal_card = ' '.join(self.royal_card.split('-')) + cards_on_table = '\n'.join([f'{" ".join(i[0].split("-"))} покрыта картой {" ".join(i[1].split("-"))}' + if i[1] != '' else f'{" ".join(i[0].split("-"))} не покрыта' + for i in self.cards_on_table.items()]) + return self.game_text.format(user_from, user_to, cards_value, royal_card, cards_on_table) def next_user(self): self.user_from = self.users[self.user_from_index] @@ -156,22 +159,33 @@ def delete_user_card(self, card: str, user_chat_id: int): def create_game_keyboard(self, chat_id: int): if str(self.user_from) == str(chat_id): if self.cards_on_table: - return create_inline_kb(width=1, dct=create_game_keyboard_dict(self.users_cards[chat_id]), - last_btn='bito', back_button='exit') + return create_inline_kb(width=1, + dct=create_game_keyboard_dict(cards=self.users_cards[chat_id], + to_or_from='from'), + last_btn='bito', + back_button='exit') else: return create_inline_kb(width=1, - dct=create_game_keyboard_dict(self.users_cards[chat_id]), + dct=create_game_keyboard_dict(cards=self.users_cards[chat_id], + to_or_from='from'), back_button='exit') if str(self.user_to) == str(chat_id): - if self.cards_on_table: + if self.cards_on_table and not all(self.cards_on_table.values()): return create_inline_kb(width=1, - dct=create_game_keyboard_dict(self.users_cards[chat_id]), last_btn='beru', + dct=create_game_keyboard_dict(cards=self.users_cards[chat_id], + to_or_from='to'), + last_btn='beru', back_button='exit') else: - return create_inline_kb(width=1, back_button='exit') + return create_inline_kb(width=1, + dct=create_game_keyboard_dict(cards=self.users_cards[chat_id], + to_or_from='to'), + back_button='exit') if self.user_from_bito: return create_inline_kb(width=1, - dct=create_game_keyboard_dict(self.users_cards[chat_id]), last_btn='bito', + dct=create_game_keyboard_dict(cards=self.users_cards[chat_id], + to_or_from='from'), + last_btn='bito', back_button='exit') return create_inline_kb(width=1, back_button='exit') @@ -210,7 +224,6 @@ def delete_user(self, user_chat_id: int, is_add_cards: int): async def exit_lobby(state: FSMContext, data, bot, message: Message): await lobby_database.exit_lobby(lobby_id=data['lobby'], user_chat_id=str(message.chat.id)) lobby_stat = lobby_database.get_lobby_stat(data['lobby']) - storage = state.storage if lobby_stat[0] == '': del lobbies_messages_dict[data['lobby']] games_messages_dict[data['lobby']] = None @@ -283,3 +296,28 @@ def update_previous_pages(data, callback_data): if callback_data in data['previous_pages']: data['previous_pages'] = data['previous_pages'][:-2] return data + + +def get_valid_cards(cards: list, card: list, royal_card: str): + valid_cards = [] + royal_card = royal_card.split('-') + print(royal_card, card, cards) + if card[1] == royal_card[1]: + print(1) + for i in cards: + cur_card = i.split('-') + if cur_card[1] == royal_card[1] and lexicon_card_faces[card[0]] > lexicon_card_faces[cur_card[0]]: + valid_cards.append(i) + elif cur_card[1] != royal_card[1]: + valid_cards.append(i) + else: + for i in cards: + cur_card = i.split('-') + if cur_card[1] == card[1] and lexicon_card_faces[card[0]] > lexicon_card_faces[cur_card[0]]: + valid_cards.append(i) + return valid_cards + + +def get_valid_faces(cards: list): + cards = [i.split('-') for i in cards] + return [i[0] for i in cards]