From 5f3bb3c1f8f536c1469a4a722cc404d425ecf5c2 Mon Sep 17 00:00:00 2001 From: Bulat Kurbanov Date: Sun, 17 Nov 2024 11:55:29 +0100 Subject: [PATCH] Move game_list to mongo --- src/modules/games_list/discord.py | 105 ++++++++++++++++++--------- src/modules/games_list/games_list.py | 74 ++++++++++--------- src/repositories/streamers.py | 26 +++++++ 3 files changed, 133 insertions(+), 72 deletions(-) diff --git a/src/modules/games_list/discord.py b/src/modules/games_list/discord.py index 861200c..800bf1c 100644 --- a/src/modules/games_list/discord.py +++ b/src/modules/games_list/discord.py @@ -87,27 +87,44 @@ async def add( game: str, date: str | None = None ): - channel_to_message = await get_game_list_channel_to_message_map() - - if interaction.channel is None: - await interaction.response.send_message("Команда не доступна в этом канале (#1)", ephemeral=True) - return - - message_id = channel_to_message.get(interaction.channel.id) - if message_id is None: - await interaction.response.send_message("Команда не доступна в этом канале (#3)", ephemeral=True) - return - if not isinstance(interaction.channel, Messageable): - await interaction.response.send_message("Команда не доступна в этом канале (#2)", ephemeral=True) + await interaction.response.send_message( + "Interation not allowed in this channel!", ephemeral=True + ) return - game_list_message = await interaction.channel.fetch_message(message_id) + streamer = await StreamerConfigRepository.find_one( + integration_discord_guild_id=interaction.guild_id, + integration_discord_games_list_channel_id=interaction.channel_id + ) + + if streamer is None: + await interaction.response.send_message( + "Interation not allowed in this channel!", ephemeral=True + ) + return + + if streamer.integrations.discord is None or streamer.integrations.discord.games_list is None: + await interaction.response.send_message( + "Need setup!", ephemeral=True + ) + return + + game_list = await GameList.get(streamer.twitch.id) + if game_list is None: + await interaction.response.send_message( + "Game list not found!", ephemeral=True + ) + return - game_list = GameList.parse(game_list_message.content) game_list.add_game(category, GameItem(name=game, customer=customer, date=date)) + game_list_message = await interaction.channel.fetch_message( + streamer.integrations.discord.games_list.message_id + ) + await game_list_message.edit(content=str(game_list)) + await game_list.save(streamer.twitch.id) await interaction.response.send_message("Игра добавлена!", ephemeral=True) @@ -116,18 +133,17 @@ async def game_list_autocomplete( interaction: discord.Interaction, current: str, ) -> list[app_commands.Choice[str]]: - if not isinstance(interaction.channel, Messageable): + streamer = await StreamerConfigRepository.find_one( + integration_discord_guild_id=interaction.guild_id, + integration_discord_games_list_channel_id=interaction.channel_id + ) + if streamer is None: return [] - channel_to_message = await get_game_list_channel_to_message_map() - message_id = channel_to_message.get(interaction.channel.id) - if message_id is None: + game_list = await GameList.get(streamer.twitch.id) + if game_list is None: return [] - game_list_message = await interaction.channel.fetch_message(message_id) - - game_list = GameList.parse(game_list_message.content) - return game_list.get_choices(current) @@ -135,27 +151,44 @@ async def game_list_autocomplete( @app_commands.describe(game="Игра") @app_commands.autocomplete(game=game_list_autocomplete) async def delete(interaction: discord.Interaction, game: str): - channel_to_message = await get_game_list_channel_to_message_map() - - if interaction.channel is None: - await interaction.response.send_message("Команда не доступна в этом канале (#1)", ephemeral=True) - return - - message_id = channel_to_message.get(interaction.channel.id) - if message_id is None: - await interaction.response.send_message("Команда не доступна в этом канале (#3)", ephemeral=True) - return - if not isinstance(interaction.channel, Messageable): - await interaction.response.send_message("Команда не доступна в этом канале (#2)", ephemeral=True) + await interaction.response.send_message( + "Interation not allowed in this channel!", ephemeral=True + ) return - game_list_message = await interaction.channel.fetch_message(message_id) + streamer = await StreamerConfigRepository.find_one( + integration_discord_guild_id=interaction.guild_id, + integration_discord_games_list_channel_id=interaction.channel_id + ) + + if streamer is None: + await interaction.response.send_message( + "Interation not allowed in this channel!", ephemeral=True + ) + return + + if streamer.integrations.discord is None or streamer.integrations.discord.games_list is None: + await interaction.response.send_message( + "Need setup!", ephemeral=True + ) + return + + game_list = await GameList.get(streamer.twitch.id) + if game_list is None: + await interaction.response.send_message( + "Game list not found!", ephemeral=True + ) + return - game_list = GameList.parse(game_list_message.content) game_list.delete_game(game) + game_list_message = await interaction.channel.fetch_message( + streamer.integrations.discord.games_list.message_id + ) + await game_list_message.edit(content=str(game_list)) + await game_list.save(streamer.twitch.id) await interaction.response.send_message("Игра удалена!", ephemeral=True) diff --git a/src/modules/games_list/games_list.py b/src/modules/games_list/games_list.py index a3d65f3..e4e4cfd 100644 --- a/src/modules/games_list/games_list.py +++ b/src/modules/games_list/games_list.py @@ -1,10 +1,11 @@ from typing import Self from datetime import datetime -import re from discord import app_commands from pydantic import BaseModel +from core.mongo import mongo_manager + class GameItem(BaseModel): name: str @@ -17,20 +18,6 @@ class GameItem(BaseModel): else: return f"* {self.name} ({self.customer})" - @classmethod - def parse(cls, line: str) -> Self: - regex_result_with_date = re.search(r"^\* (.+) \((.+)\) \| (.+)$", line) - if regex_result_with_date is not None: - name, customer, date = regex_result_with_date.groups() - return cls(name=name, customer=customer, date=date) - - regex_result_without_date = re.search(r"^\* (.+) \((.+)\)$", line) - if regex_result_without_date is not None: - name, customer = regex_result_without_date.groups() - return cls(name=name, customer=customer, date=None) - - raise ValueError(f"Invalid line: {line}") - class Category(BaseModel): name: str @@ -38,6 +25,8 @@ class Category(BaseModel): class GameList: + COLLECTION_NAME = "games_list_data" + CATEGORY_MAP = { "points": "Заказанные игры (за 12к)", "paids": "Проплачены 🤑 ", @@ -48,20 +37,33 @@ class GameList: self.data = data @classmethod - def parse(cls, message: str) -> Self: - categories = [] + async def get(cls, twitch_id: int) -> Self | None: + async with mongo_manager.connect() as client: + db = client.get_default_database() + collection = db[cls.COLLECTION_NAME] - for line in message.split("\n"): - if line == "".strip(): - continue + doc = await collection.find_one({"twitch_id": twitch_id}) + if doc is None: + return None - if not line.startswith("*"): - name = line.replace(":", "") - categories.append(Category(name=name, games=[])) - else: - categories[-1].games.append(GameItem.parse(line.strip())) + return cls([ + Category(**category) + for category in doc["data"] + ]) - return cls(data=categories) + async def save(self, twitch_id: int): + async with mongo_manager.connect() as client: + db = client.get_default_database() + collection = db[self.COLLECTION_NAME] + + await collection.replace_one( + {"twitch_id": twitch_id}, + { + "twitch_id": twitch_id, + "data": [category.model_dump() for category in self.data] + }, + upsert=True + ) def add_game(self, category: str, game_item: GameItem): _category = self.CATEGORY_MAP.get(category) @@ -79,6 +81,16 @@ class GameList: if game.name.startswith(game_name): category.games.remove(game) + def get_choices(self, query: str) -> list[app_commands.Choice[str]]: + choices = [] + + for category in self.data: + for game in category.games: + if query.lower() in game.name.lower(): + choices.append(app_commands.Choice(name=game.name, value=game.name)) + + return choices[:25] + def __str__(self) -> str: result = "" @@ -91,13 +103,3 @@ class GameList: result += "\n\n" return result - - def get_choices(self, query: str) -> list[app_commands.Choice[str]]: - choices = [] - - for category in self.data: - for game in category.games: - if query.lower() in game.name.lower(): - choices.append(app_commands.Choice(name=game.name, value=game.name)) - - return choices[:25] diff --git a/src/repositories/streamers.py b/src/repositories/streamers.py index 9d5f851..ed00c72 100644 --- a/src/repositories/streamers.py +++ b/src/repositories/streamers.py @@ -18,6 +18,32 @@ class StreamerConfigRepository: return StreamerConfig(**doc) + @classmethod + async def find_one( + cls, + integration_discord_guild_id: int | None = None, + integration_discord_games_list_channel_id: int | None = None, + ) -> StreamerConfig | None: + filters = {} + + if integration_discord_guild_id is not None: + filters["integrations.discord.guild_id"] = integration_discord_guild_id + + if integration_discord_games_list_channel_id is not None: + filters[ + "integrations.discord.games_list.channel_id" + ] = integration_discord_games_list_channel_id + + async with mongo_manager.connect() as client: + db = client.get_default_database() + collection = db[cls.COLLECTION_NAME] + + doc = await collection.find_one(filters) + if doc is None: + return None + + return StreamerConfig(**doc) + @classmethod async def all(cls) -> list[StreamerConfig]: async with mongo_manager.connect() as client: