Worked on #13 and #4. There are some caching issues left, though. Introduced abstract class Cacheable. Replaced async_pymongo with pymongo

This commit is contained in:
2025-05-06 02:54:30 +02:00
parent 9d562e2e9d
commit 86c75d06fa
22 changed files with 412 additions and 137 deletions

View File

@@ -88,14 +88,15 @@ class CogConfig(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
try:
timezone_parsed: ZoneInfo = ZoneInfo(timezone)
except ZoneInfoNotFoundError:
await ctx.respond(
self.bot._("timezone_invalid", "messages", locale=ctx.locale).format(timezone=timezone)
self.bot._("timezone_invalid", "messages", locale=ctx.locale).format(timezone=timezone),
ephemeral=True,
)
return
@@ -130,7 +131,7 @@ class CogConfig(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
await guild.purge(self.bot.cache)
@@ -146,11 +147,13 @@ class CogConfig(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale), ephemeral=True
)
return
await ctx.respond(

View File

@@ -84,11 +84,13 @@ class CogEvent(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale), ephemeral=True
)
return
guild_timezone: ZoneInfo = ZoneInfo(guild.timezone)
@@ -97,7 +99,9 @@ class CogEvent(Cog):
start_date: datetime = datetime.strptime(start, "%d.%m.%Y %H:%M").replace(tzinfo=guild_timezone)
end_date: datetime = datetime.strptime(end, "%d.%m.%Y %H:%M").replace(tzinfo=guild_timezone)
except ValueError:
await ctx.respond(self.bot._("event_dates_parsing_failed", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("event_dates_parsing_failed", "messages", locale=ctx.locale), ephemeral=True
)
return
if not await validate_event_validity(ctx, name, start_date, end_date, to_utc=True):
@@ -180,7 +184,7 @@ class CogEvent(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
try:
@@ -190,7 +194,9 @@ class CogEvent(Cog):
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale), ephemeral=True
)
return
guild_timezone: ZoneInfo = ZoneInfo(guild.timezone)
@@ -202,7 +208,9 @@ class CogEvent(Cog):
else datetime.strptime(start, "%d.%m.%Y %H:%M").replace(tzinfo=guild_timezone)
)
except ValueError:
await ctx.respond(self.bot._("event_start_date_parsing_failed", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("event_start_date_parsing_failed", "messages", locale=ctx.locale), ephemeral=True
)
return
try:
@@ -212,7 +220,9 @@ class CogEvent(Cog):
else datetime.strptime(end, "%d.%m.%Y %H:%M").replace(tzinfo=guild_timezone)
)
except ValueError:
await ctx.respond(self.bot._("event_end_date_parsing_failed", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("event_end_date_parsing_failed", "messages", locale=ctx.locale), ephemeral=True
)
return
if not await validate_event_validity(
@@ -280,7 +290,7 @@ class CogEvent(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
try:
@@ -290,7 +300,9 @@ class CogEvent(Cog):
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale), ephemeral=True
)
return
start_date: datetime = pycord_event.starts.replace(tzinfo=ZoneInfo("UTC"))
@@ -305,7 +317,8 @@ class CogEvent(Cog):
await ctx.respond(
self.bot._("event_not_editable", "messages", locale=ctx.locale).format(
event_name=pycord_event.name
)
),
ephemeral=True,
)
return

View File

@@ -34,11 +34,13 @@ class CogGuess(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured", "messages", locale=ctx.locale), ephemeral=True
)
return
user: PycordUser = await self.bot.find_user(ctx.author, ctx.guild)

View File

@@ -4,7 +4,7 @@ from pathlib import Path
from zoneinfo import ZoneInfo
from bson.errors import InvalidId
from discord import ApplicationContext, Cog, TextChannel, option, slash_command, File
from discord import ApplicationContext, Cog, File, TextChannel, option, slash_command
from discord.utils import basic_autocomplete
from libbot.i18n import _, in_every_locale
@@ -39,7 +39,7 @@ class CogRegister(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
try:
@@ -49,17 +49,21 @@ class CogRegister(Cog):
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured", "messages", locale=ctx.locale), ephemeral=True
)
return
user: PycordUser = await self.bot.find_user(ctx.author, ctx.guild)
if user.is_jailed:
await ctx.respond(self.bot._("jailed_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("jailed_error", "messages", locale=ctx.locale), ephemeral=True)
return
if pycord_event._id in user.registered_event_ids:
await ctx.respond(self.bot._("register_already_registered", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("register_already_registered", "messages", locale=ctx.locale), ephemeral=True
)
return
await user.event_register(pycord_event._id, cache=self.bot.cache)

View File

@@ -84,11 +84,13 @@ class CogStage(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale), ephemeral=True
)
return
try:
@@ -196,11 +198,13 @@ class CogStage(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale), ephemeral=True
)
return
try:
@@ -215,11 +219,13 @@ class CogStage(Cog):
try:
event_stage: PycordEventStage = await self.bot.find_event_stage(stage)
except (InvalidId, EventStageNotFoundError):
await ctx.respond(self.bot._("stage_not_found", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("stage_not_found", "messages", locale=ctx.locale), ephemeral=True)
return
if order is not None and order > len(pycord_event.stage_ids):
await ctx.respond(self.bot._("stage_sequence_out_of_range", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("stage_sequence_out_of_range", "messages", locale=ctx.locale), ephemeral=True
)
return
processed_media: List[Dict[str, Any]] = (
@@ -278,11 +284,13 @@ class CogStage(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured_admin", "messages", locale=ctx.locale), ephemeral=True
)
return
try:
@@ -297,7 +305,7 @@ class CogStage(Cog):
try:
event_stage: PycordEventStage = await self.bot.find_event_stage(stage)
except (InvalidId, EventStageNotFoundError):
await ctx.respond(self.bot._("stage_not_found", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("stage_not_found", "messages", locale=ctx.locale), ephemeral=True)
return
await pycord_event.remove_stage(self.bot, event_stage._id, cache=self.bot.cache)

View File

@@ -43,7 +43,7 @@ class CogUnregister(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
try:
@@ -53,17 +53,22 @@ class CogUnregister(Cog):
return
if not guild.is_configured():
await ctx.respond(self.bot._("guild_unconfigured", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("guild_unconfigured", "messages", locale=ctx.locale), ephemeral=True
)
return
user: PycordUser = await self.bot.find_user(ctx.author, ctx.guild)
if user.is_jailed:
await ctx.respond(self.bot._("jailed_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("jailed_error", "messages", locale=ctx.locale), ephemeral=True)
return
# TODO Fix a bug where registered_event_ids is invalid because of caching
if pycord_event._id not in user.registered_event_ids:
await ctx.respond(self.bot._("unregister_not_registered", "messages", locale=ctx.locale))
await ctx.respond(
self.bot._("unregister_not_registered", "messages", locale=ctx.locale), ephemeral=True
)
return
await user.event_unregister(pycord_event._id, cache=self.bot.cache)

View File

@@ -1,27 +1,27 @@
from datetime import datetime
from logging import Logger
from pathlib import Path
from typing import List, Dict, Any
from typing import Any, Dict, List
from zoneinfo import ZoneInfo
from bson import ObjectId
from bson.errors import InvalidId
from discord import (
ApplicationContext,
File,
SlashCommandGroup,
TextChannel,
User,
option,
File,
TextChannel,
)
from discord.ext.commands import Cog
from libbot.i18n import _, in_every_locale
from classes import PycordUser, PycordEvent, PycordGuild
from classes import PycordEvent, PycordGuild, PycordUser
from classes.errors import GuildNotFoundError
from classes.pycord_bot import PycordBot
from modules.database import col_users
from modules.utils import is_operation_confirmed, get_logger
from modules.utils import get_logger, is_operation_confirmed, get_utc_now
logger: Logger = get_logger(__name__)
@@ -54,35 +54,45 @@ class CogUser(Cog):
try:
guild: PycordGuild = await self.bot.find_guild(ctx.guild.id)
except (InvalidId, GuildNotFoundError):
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale))
await ctx.respond(self.bot._("unexpected_error", "messages", locale=ctx.locale), ephemeral=True)
return
pycord_user: PycordUser = await self.bot.find_user(user.id, ctx.guild.id)
events: List[PycordEvent] = []
utc_now: datetime = get_utc_now()
pipeline: List[Dict[str, Any]] = [
{"$match": {"id": pycord_user.id}},
{
"$lookup": {
"from": "events",
"localField": "registered_event_ids",
"foreignField": "_id",
"let": {"event_ids": "$registered_event_ids"},
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{"$in": ["$_id", "$$event_ids"]},
{"$eq": ["$ended", None]},
{"$gt": ["$ends", utc_now]},
{"$lt": ["$starts", utc_now]},
{"$eq": ["$is_cancelled", False]},
]
}
}
}
],
"as": "registered_events",
}
},
{
"$match": {
"registered_events.ended": None,
"registered_events.ends": {"$gt": datetime.now(tz=ZoneInfo("UTC"))},
"registered_events.starts": {"$lt": datetime.now(tz=ZoneInfo("UTC"))},
"registered_events.is_cancelled": False,
}
},
{"$match": {"registered_events.0": {"$exists": True}}},
]
async for result in col_users.aggregate(pipeline):
for registered_event in result["registered_events"]:
events.append(PycordEvent(**registered_event))
async with await col_users.aggregate(pipeline) as cursor:
async for result in cursor:
for registered_event in result["registered_events"]:
events.append(PycordEvent(**registered_event))
for event in events:
if pycord_user.current_event_id is not None and pycord_user.current_event_id != event._id:

View File

@@ -6,13 +6,13 @@ from zoneinfo import ZoneInfo
from bson import ObjectId
from bson.errors import InvalidId
from discord import Activity, ActivityType, Cog, Member, TextChannel, File
from discord import Activity, ActivityType, Cog, File, Member, TextChannel
from classes import PycordEvent, PycordGuild, PycordUser
from classes.errors import GuildNotFoundError
from classes.pycord_bot import PycordBot
from modules.database import col_users
from modules.utils import get_logger
from modules.utils import get_logger, get_utc_now
logger: Logger = get_logger(__name__)
@@ -78,29 +78,39 @@ class CogUtility(Cog):
user: PycordUser = await self.bot.find_user(member.id, member.guild.id)
events: List[PycordEvent] = []
utc_now: datetime = get_utc_now()
pipeline: List[Dict[str, Any]] = [
{"$match": {"id": user.id}},
{
"$lookup": {
"from": "events",
"localField": "registered_event_ids",
"foreignField": "_id",
"let": {"event_ids": "$registered_event_ids"},
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{"$in": ["$_id", "$$event_ids"]},
{"$eq": ["$ended", None]},
{"$gt": ["$ends", utc_now]},
{"$lt": ["$starts", utc_now]},
{"$eq": ["$is_cancelled", False]},
]
}
}
}
],
"as": "registered_events",
}
},
{
"$match": {
"registered_events.ended": None,
"registered_events.ends": {"$gt": datetime.now(tz=ZoneInfo("UTC"))},
"registered_events.starts": {"$lt": datetime.now(tz=ZoneInfo("UTC"))},
"registered_events.is_cancelled": False,
}
},
{"$match": {"registered_events.0": {"$exists": True}}},
]
async for result in col_users.aggregate(pipeline):
for registered_event in result["registered_events"]:
events.append(PycordEvent(**registered_event))
async with await col_users.aggregate(pipeline) as cursor:
async for result in cursor:
for registered_event in result["registered_events"]:
events.append(PycordEvent(**registered_event))
for event in events:
if user.current_event_id is not None and user.current_event_id != event._id: