From 95dbd9cec8c49940e5397f838089b3e7b6d02772 Mon Sep 17 00:00:00 2001 From: profitroll Date: Thu, 3 Aug 2023 21:29:47 +0200 Subject: [PATCH] Added database and /language --- classes/pyroclient.py | 40 ++++++++++++++++++++++++++++++++++++ classes/pyrouser.py | 23 +++++++++++++++++++++ config_example.json | 7 +++++++ modules/database.py | 32 +++++++++++++++++++++++++++++ plugins/callback.py | 2 +- plugins/command.py | 2 +- plugins/handler.py | 2 +- plugins/inline.py | 2 +- plugins/language.py | 42 ++++++++++++++++++++++++++++++++++++++ plugins/remove_commands.py | 2 +- requirements.txt | 3 +++ 11 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 classes/pyroclient.py create mode 100644 classes/pyrouser.py create mode 100644 modules/database.py create mode 100644 plugins/language.py diff --git a/classes/pyroclient.py b/classes/pyroclient.py new file mode 100644 index 0000000..3e67efe --- /dev/null +++ b/classes/pyroclient.py @@ -0,0 +1,40 @@ +from typing import Union + +from libbot.pyrogram.classes import PyroClient +from pyrogram.types import User + +from classes.pyrouser import PyroUser +from modules.database import col_users + + +class PyroClient(PyroClient): + async def find_user(self, user: Union[int, User]) -> PyroUser: + """Find User by it's ID or User object + + ### Args: + * user (`Union[int, User]`): ID or User object to extract ID from + + ### Returns: + * `PyroUser`: PyroUser object + """ + if ( + col_users.find_one({"id": user.id if isinstance(user, User) else user}) + is None + ): + col_users.insert_one( + { + "id": user.id if isinstance(user, User) else user, + "locale": user.language_code if isinstance(user, User) else None, + } + ) + + db_record = col_users.find_one( + {"id": user.id if isinstance(user, User) else user} + ) + + if db_record is None: + raise TypeError( + f"User with ID {user.id if isinstance(user, User) else user} was not found in the database" + ) + + return PyroUser(**db_record) diff --git a/classes/pyrouser.py b/classes/pyrouser.py new file mode 100644 index 0000000..05c86bc --- /dev/null +++ b/classes/pyrouser.py @@ -0,0 +1,23 @@ +from typing import Union + +from attrs import define +from bson import ObjectId + +from modules.database import col_users + + +@define +class PyroUser: + """Dataclass of DB entry of a user""" + + _id: ObjectId + id: int + locale: Union[str, None] + + async def update_locale(self, locale: str) -> None: + """Change user's locale stored in the database + + ### Args: + * locale (`str`): New locale to be set + """ + col_users.update_one({"_id": self._id}, {"$set": {"locale": locale}}) diff --git a/config_example.json b/config_example.json index ef133a8..058bb17 100644 --- a/config_example.json +++ b/config_example.json @@ -9,6 +9,13 @@ "max_concurrent_transmissions": 1, "scoped_commands": true }, + "database": { + "user": null, + "password": null, + "host": "127.0.0.1", + "port": 27017, + "name": "pyrobot" + }, "reports": { "chat_id": "owner" }, diff --git a/modules/database.py b/modules/database.py new file mode 100644 index 0000000..e34f260 --- /dev/null +++ b/modules/database.py @@ -0,0 +1,32 @@ +"""Module that provides all database columns""" + +from pymongo import MongoClient +from ujson import loads + +with open("config.json", "r", encoding="utf-8") as f: + db_config = loads(f.read())["database"] + f.close() + +if db_config["user"] is not None and db_config["password"] is not None: + con_string = "mongodb://{0}:{1}@{2}:{3}/{4}".format( + db_config["user"], + db_config["password"], + db_config["host"], + db_config["port"], + db_config["name"], + ) +else: + con_string = "mongodb://{0}:{1}/{2}".format( + db_config["host"], db_config["port"], db_config["name"] + ) + +db_client = MongoClient(con_string) +db = db_client.get_database(name=db_config["name"]) + +collections = db.list_collection_names() + +for collection in ["users"]: + if collection not in collections: + db.create_collection(collection) + +col_users = db.get_collection("users") diff --git a/plugins/callback.py b/plugins/callback.py index d6de79a..9233d97 100644 --- a/plugins/callback.py +++ b/plugins/callback.py @@ -2,7 +2,7 @@ from pyrogram import filters from pyrogram.client import Client from pyrogram.types import CallbackQuery -from libbot.pyrogram.classes import PyroClient +from classes.pyroclient import PyroClient @Client.on_callback_query(filters.regex("nothing")) # type: ignore diff --git a/plugins/command.py b/plugins/command.py index afec5d5..97a136f 100644 --- a/plugins/command.py +++ b/plugins/command.py @@ -2,7 +2,7 @@ from pyrogram import filters from pyrogram.client import Client from pyrogram.types import Message -from libbot.pyrogram.classes import PyroClient +from classes.pyroclient import PyroClient @Client.on_message( diff --git a/plugins/handler.py b/plugins/handler.py index 26acb3a..9eb8622 100644 --- a/plugins/handler.py +++ b/plugins/handler.py @@ -2,7 +2,7 @@ from pyrogram import filters from pyrogram.client import Client from pyrogram.types import Message -from libbot.pyrogram.classes import PyroClient +from classes.pyroclient import PyroClient @Client.on_message(filters.text & filters.private) # type: ignore diff --git a/plugins/inline.py b/plugins/inline.py index 6db8edb..1daa5a8 100644 --- a/plugins/inline.py +++ b/plugins/inline.py @@ -5,7 +5,7 @@ from pyrogram.types import ( InputTextMessageContent, ) -from libbot.pyrogram.classes import PyroClient +from classes.pyroclient import PyroClient @Client.on_inline_query() # type: ignore diff --git a/plugins/language.py b/plugins/language.py new file mode 100644 index 0000000..5c0fbd5 --- /dev/null +++ b/plugins/language.py @@ -0,0 +1,42 @@ +from pykeyboard import InlineButton, InlineKeyboard +from pyrogram import filters +from pyrogram.client import Client +from pyrogram.types import CallbackQuery, Message + +from classes.pyroclient import PyroClient + + +@Client.on_message( + ~filters.scheduled & filters.private & filters.command(["language"], prefixes=["/"]) # type: ignore +) +async def command_language(app: PyroClient, message: Message): + user = await app.find_user(message.from_user) + keyboard = InlineKeyboard(row_width=2) + buttons = [] + + for locale, data in app.in_every_locale("metadata").items(): + buttons.append( + InlineButton(f"{data['flag']} {data['name']}", f"language:{locale}") + ) + + keyboard.add(*buttons) + + await message.reply_text( + app._("locale_choice", "messages", locale=user.locale), + reply_markup=keyboard, + ) + + +@Client.on_callback_query(filters.regex(r"language:[\s\S]*")) # type: ignore +async def callback_language(app: PyroClient, callback: CallbackQuery): + user = await app.find_user(callback.from_user) + language = str(callback.data).split(":")[1] + + await user.update_locale(language) + + await callback.answer( + app._("locale_set", "callbacks", locale=language).format( + locale=app._("name", "metadata", locale=language) + ), + show_alert=True, + ) diff --git a/plugins/remove_commands.py b/plugins/remove_commands.py index 9c8f58a..939dab5 100644 --- a/plugins/remove_commands.py +++ b/plugins/remove_commands.py @@ -2,7 +2,7 @@ from pyrogram import filters from pyrogram.client import Client from pyrogram.types import Message -from libbot.pyrogram.classes import PyroClient +from classes.pyroclient import PyroClient @Client.on_message( diff --git a/requirements.txt b/requirements.txt index 79815df..8050d76 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,10 @@ aiofiles~=23.1.0 apscheduler~=3.10.1 +attrs~=23.1.0 black~=23.7.0 convopyro==0.5 +pykeyboard==0.1.5 +pymongo==4.4.1 pyrogram==2.0.106 tgcrypto==1.2.5 ujson==5.8.0