Move game_list to mongo

This commit is contained in:
2024-11-17 11:55:29 +01:00
parent d6716ea49b
commit 5f3bb3c1f8
3 changed files with 133 additions and 72 deletions

View File

@@ -87,27 +87,44 @@ async def add(
game: str, game: str,
date: str | None = None 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): 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 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.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_message.edit(content=str(game_list))
await game_list.save(streamer.twitch.id)
await interaction.response.send_message("Игра добавлена!", ephemeral=True) await interaction.response.send_message("Игра добавлена!", ephemeral=True)
@@ -116,18 +133,17 @@ async def game_list_autocomplete(
interaction: discord.Interaction, interaction: discord.Interaction,
current: str, current: str,
) -> list[app_commands.Choice[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 [] return []
channel_to_message = await get_game_list_channel_to_message_map() game_list = await GameList.get(streamer.twitch.id)
message_id = channel_to_message.get(interaction.channel.id) if game_list is None:
if message_id is None:
return [] 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) return game_list.get_choices(current)
@@ -135,27 +151,44 @@ async def game_list_autocomplete(
@app_commands.describe(game="Игра") @app_commands.describe(game="Игра")
@app_commands.autocomplete(game=game_list_autocomplete) @app_commands.autocomplete(game=game_list_autocomplete)
async def delete(interaction: discord.Interaction, game: str): 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): 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 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.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_message.edit(content=str(game_list))
await game_list.save(streamer.twitch.id)
await interaction.response.send_message("Игра удалена!", ephemeral=True) await interaction.response.send_message("Игра удалена!", ephemeral=True)

View File

@@ -1,10 +1,11 @@
from typing import Self from typing import Self
from datetime import datetime from datetime import datetime
import re
from discord import app_commands from discord import app_commands
from pydantic import BaseModel from pydantic import BaseModel
from core.mongo import mongo_manager
class GameItem(BaseModel): class GameItem(BaseModel):
name: str name: str
@@ -17,20 +18,6 @@ class GameItem(BaseModel):
else: else:
return f"* {self.name} ({self.customer})" 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): class Category(BaseModel):
name: str name: str
@@ -38,6 +25,8 @@ class Category(BaseModel):
class GameList: class GameList:
COLLECTION_NAME = "games_list_data"
CATEGORY_MAP = { CATEGORY_MAP = {
"points": "Заказанные игры (за 12к)", "points": "Заказанные игры (за 12к)",
"paids": "Проплачены 🤑 ", "paids": "Проплачены 🤑 ",
@@ -48,20 +37,33 @@ class GameList:
self.data = data self.data = data
@classmethod @classmethod
def parse(cls, message: str) -> Self: async def get(cls, twitch_id: int) -> Self | None:
categories = [] async with mongo_manager.connect() as client:
db = client.get_default_database()
collection = db[cls.COLLECTION_NAME]
for line in message.split("\n"): doc = await collection.find_one({"twitch_id": twitch_id})
if line == "".strip(): if doc is None:
continue return None
if not line.startswith("*"): return cls([
name = line.replace(":", "") Category(**category)
categories.append(Category(name=name, games=[])) for category in doc["data"]
else: ])
categories[-1].games.append(GameItem.parse(line.strip()))
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): def add_game(self, category: str, game_item: GameItem):
_category = self.CATEGORY_MAP.get(category) _category = self.CATEGORY_MAP.get(category)
@@ -79,6 +81,16 @@ class GameList:
if game.name.startswith(game_name): if game.name.startswith(game_name):
category.games.remove(game) 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: def __str__(self) -> str:
result = "" result = ""
@@ -91,13 +103,3 @@ class GameList:
result += "\n\n" result += "\n\n"
return result 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]

View File

@@ -18,6 +18,32 @@ class StreamerConfigRepository:
return StreamerConfig(**doc) 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 @classmethod
async def all(cls) -> list[StreamerConfig]: async def all(cls) -> list[StreamerConfig]:
async with mongo_manager.connect() as client: async with mongo_manager.connect() as client: