Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds userid and chatid fields to the User model to enable better user tracking. The changes include significant refactoring: removing abstract base classes, extracting templates and callbacks to separate files, migrating from lazy database initialization to direct initialization, and adding a temporary function to update existing user records with the new fields.
- Adds
useridandchatidfields to User model for improved user identification - Refactors database layer to remove abstract classes and lazy initialization
- Extracts message templates and callback classes to dedicated modules for better organization
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| src/userdb.py | Removes abstract base classes, changes to direct initialization, adds temporary add_ids_to_user() method and get_users() query method |
| src/models.py | Adds required userid and chatid fields to User model with formatting improvements |
| src/bot.py | Integrates userid/chatid capture, extracts callbacks/templates to separate modules, adds new initialization flow |
| src/templates.py | New file containing extracted message templates from bot.py |
| src/callbacks.py | New file containing extracted callback data classes from bot.py |
| random_prizes.py | Migrates to use MONGODB_HOST environment variable |
| main.py | Relocates main() function to bot.py module |
| .env.example | Adds MONGODB_HOST configuration example |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Видимся изредка, общение короткое и ситуативное. В основном на учебные/повседневные темы.""" | ||
|
|
||
|
|
||
| def make_type_str(type: str, profile: str, strong_sides: List[str], recomendation: str): |
There was a problem hiding this comment.
Parameter name has a typo: recomendation should be recommendation (double 'm').
|
|
||
| @dp.message(F.text[0] == "@") | ||
| async def user_name_checker(message: types.Message): | ||
| userdb.add_ids_to_user( |
There was a problem hiding this comment.
Missing await keyword before userdb.add_ids_to_user(). This async function call is not being awaited, so it will return a coroutine object that is immediately discarded. The userid and chatid will not be saved to the database.
| userdb.add_ids_to_user( | |
| await userdb.add_ids_to_user( |
| await userdb.add_ids_to_user( | ||
| message.from_user.username, message.from_user.id, message.chat.id | ||
| ) |
There was a problem hiding this comment.
The add_ids_to_user() call is duplicated in multiple handlers (lines 236-238, 251-253, 341-343, 352-354). Consider using a middleware or decorator to automatically capture and update userid/chatid for all message handlers, reducing code duplication.
| # NOTE: This is temporary function for fixing current database | ||
| # And should be deleted someday because of obvious performance loss |
There was a problem hiding this comment.
While there's a NOTE comment explaining this is temporary, it lacks details about when "someday" is or what conditions would trigger its removal. Consider adding a TODO with a specific issue number or criteria for removal (e.g., "TODO: Remove after all existing users have been migrated - target date: YYYY-MM-DD" or "TODO(#123): Remove after database migration is complete").
| # NOTE: This is temporary function for fixing current database | |
| # And should be deleted someday because of obvious performance loss | |
| # TODO(#123): Remove this temporary function after all users have been migrated to the new schema (target date: 2024-12-31). | |
| # This function exists to fix the current database and should be deleted to avoid performance loss. |
| "\n📝 Чтобы добавить ещё друга — просто введи следующий юзернейм.", | ||
| "\n🔁 Чем больше друзей ты добавишь — тем точнее будет твой социальный портрет!", |
There was a problem hiding this comment.
The as_list() function is being used incorrectly. It expects separate arguments but is receiving a single f-string with newline characters. This should be: as_list(f"✅ @{callback_data.username_to} добавлен как {rating_to_text(callback_data.rating).lower()}", "📝 Чтобы добавить ещё друга — просто введи следующий юзернейм.", "🔁 Чем больше друзей ты добавишь — тем точнее будет твой социальный портрет!") with three separate string arguments.
| "\n📝 Чтобы добавить ещё друга — просто введи следующий юзернейм.", | |
| "\n🔁 Чем больше друзей ты добавишь — тем точнее будет твой социальный портрет!", | |
| "📝 Чтобы добавить ещё друга — просто введи следующий юзернейм.", | |
| "🔁 Чем больше друзей ты добавишь — тем точнее будет твой социальный портрет!", |
| asyncio.create_task(self.collection.create_index("username", unique=True)) | ||
|
|
There was a problem hiding this comment.
Creating an index using asyncio.create_task() in __init__ is problematic. The task runs fire-and-forget without awaiting, so there's no guarantee the index is created before database operations begin. This can lead to race conditions or the index creation failing silently. Consider creating the index in the main() function after instantiating UserDB, or add a separate async initialization method.
| asyncio.create_task(self.collection.create_index("username", unique=True)) | |
| async def init(self): | |
| """ | |
| Initialize the UserDB by creating necessary indexes. | |
| This method must be awaited after instantiation and before use. | |
| """ | |
| await self.collection.create_index("username", unique=True) |
| userid: int | ||
| chatid: int |
There was a problem hiding this comment.
Adding required userid and chatid fields to the User model will break existing code that creates users without these fields. In src/bot.py line 189-196, userdb.add_user() is called with a User that doesn't include userid or chatid. These fields should either be Optional or have default values to maintain backwards compatibility.
| count = len( | ||
| [i async for i in self.collection.find({"_links.4": {"$exists": True}})] | ||
| [ | ||
| i | ||
| async for i in self.collection.find( | ||
| {f"_links.{links_more_than}": {"$exists": True}} | ||
| ) | ||
| ] | ||
| ) |
There was a problem hiding this comment.
Using a list comprehension to count documents is inefficient. This loads all matching documents into memory just to count them. Use MongoDB's count_documents() method instead: count = await self.collection.count_documents({f"_links.{links_more_than}": {"$exists": True}}). This will be much faster and use less memory, especially with large datasets.
| all_user_data = await self.collection.find_one({"username": username}) | ||
| return all_user_data | ||
|
|
||
| async def get_users(self, links_less_than: int) -> AsyncCursor: |
There was a problem hiding this comment.
The method name get_users() is misleading because it returns an AsyncCursor, not a list of users. Consider renaming to find_users_with_fewer_links() or query_users_by_link_count() to better reflect that it returns a cursor for iteration rather than a materialized list.
| async def get_users(self, links_less_than: int) -> AsyncCursor: | |
| async def find_users_with_fewer_links(self, links_less_than: int) -> AsyncCursor: |
| global userdb, bot, dp | ||
| userdb = UserDB(client) |
There was a problem hiding this comment.
Using global variables (userdb, bot, dp) that are assigned in the main() function creates potential issues. These globals are undefined until main() is called, which could cause NameError if any handlers execute before main() completes initialization. Consider initializing these at module level or restructuring to avoid relying on global state.
No description provided.