diff --git a/tgEasy/__init__.py b/tgEasy/__init__.py index 2c26582..2662445 100644 --- a/tgEasy/__init__.py +++ b/tgEasy/__init__.py @@ -18,8 +18,6 @@ import asyncio import logging as logger -import os -import typing import pyrogram from pyrogram import client @@ -31,8 +29,9 @@ from .config import Config from .decorater import * from .helpers import * +from .scaffold import Scaffold -__version__ = "1.2.6" +__version__ = "1.2.7" __copyright__ = "Copyright 2021 Jayant Hegde Kageri " __license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)" logging = logger.getLogger("tgEasy") diff --git a/tgEasy/config.py b/tgEasy/config.py index 2a4ddfd..1d24960 100644 --- a/tgEasy/config.py +++ b/tgEasy/config.py @@ -21,8 +21,8 @@ from prettyconf import Configuration from prettyconf.loaders import EnvFile, Environment -env_file = f"{os.getcwd()}/.env" -config = Configuration(loaders=[Environment(), EnvFile(filename=env_file)]) +config = Configuration( + loaders=[Environment(), EnvFile(filename=f"{os.getcwd()}/.env")]) class Config: diff --git a/tgEasy/decorater.py b/tgEasy/decorater.py deleted file mode 100644 index a1d213c..0000000 --- a/tgEasy/decorater.py +++ /dev/null @@ -1,215 +0,0 @@ -# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram -# Copyright (C) 2021 Jayant Hegde Kageri - -# This file is part of tgEasy. - -# tgEasy is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# tgEasy is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public License -# along with tgEasy. If not, see . - -import os -import typing - -import pyrogram - -import tgEasy -from tgEasy.scaffold import Scaffold - -from .config import Config -from .helpers import * - - -class Command(Scaffold): - def command(self, command: typing.Union[str, list], pm_only: typing.Union[bool, bool] = False, group_only: typing.Union[bool, bool] = False, self_admin: typing.Union[bool, bool] = False, self_only: typing.Union[bool] = False, filter: typing.Union[pyrogram.filters.Filter, pyrogram.filters.Filter] = None, *args, **kwargs): - """ - ### `tgEasy.tgClient.command` - - A decorater to Register Commands in simple way and manage errors in that Function itself, alternative for `@pyrogram.Client.on_message(pyrogram.filters.command('command'))` - - Parameters: - - command (str || list): - - The command to be handled for a function - - - group_only (bool) **optional**: - - If True, the command will only executed in Groups only, By Default False. - - - pm_only (bool) **optional**: - - If True, the command will only executed in Private Messages only, By Default False. - - - self_only (bool) **optional**: - - If True, the command will only excute if used by Self only, By Default False. - - - self_admin (bool) **optional**: - - If True, the command will only executeed if the Bot is Admin in the Chat, By Default False - - - filter (`~pyrogram.filters`) **optional**: - - Pyrogram Filters, hope you know about this, for Advaced usage. By Default `~pyrogram.filters.edited` and this can't be changed. Use `and` for seaperating filters. - - #### Example - .. code-block:: python - import pyrogram - from tgEasy import tgClient - - app = tgClient(pyrogram.Client()) - - @app.command("start", group_only=False, pm_only=False, self_admin=False, self_only=False, pyrogram.filters.chat("777000") and pyrogram.filters.text) - async def start(client, message): - await message.reply_text(f"Hello {message.from_user.mention}") - """ - if filter: - if self_only: - filter = pyrogram.filters.command(command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited & filter & filters.me if self_only else pyrogram.filters.command( - command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited & filter & pyrogram.filters.me - else: - filter = pyrogram.filters.command(command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited & filter & filters.me if self_only else pyrogram.filters.command( - command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited & filter - else: - if self_only: - filter = pyrogram.filters.command( - command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited & pyrogram.filters.me - else: - filter = pyrogram.filters.command( - command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited - - def wrapper(func): - async def decorator(client, message: pyrogram.types.Message): - if self_admin and message.chat.type != "supergroup": - return await message.reply_text("This command can be used in supergroups only.") - if self_admin: - me = await client.get_me() - mee = await client.get_chat_member(message.chat.id, me.id) - if not mee.status == "admin": - return await message.reply_text("I must be admin to execute this Command") - pass - if group_only and message.chat.type != "supergroup": - return await message.reply_text("This command can be used in supergroups only.") - if pm_only and message.chat.type != "private": - return await message.reply_text("This command can be used in PMs only.") - try: - await func(client, message) - except pyrogram.errors.exceptions.forbidden_403.ChatWriteForbidden: - await client.leave_chat(message.chat.id) - except BaseException as exception: - return await handle_error(exception, message) - self.__client__.add_handler(pyrogram.handlers.MessageHandler( - callback=decorator, filters=filter)) - return decorator - return wrapper - - -class Callback(Scaffold): - def callback(self, data: typing.Union[str, list], self_admin: typing.Union[bool, bool] = False, filter: typing.Union[pyrogram.filters.Filter, pyrogram.filters.Filter] = None, *args, **kwargs): - """ - ### `tgEasy.tgClient.callback` - - - A decorater to Register Callback Quiries in simple way and manage errors in that Function itself, alternative for `@pyrogram.Client.on_callback_query(pyrogram.filters.regex('^data.*'))` - - Parameters: - - data (str || list): - - The callback query to be handled for a function - - - self_admin (bool) **optional**: - - If True, the command will only executeed if the Bot is Admin in the Chat, By Default False - - - filter (`~pyrogram.filters`) **optional**: - - Pyrogram Filters, hope you know about this, for Advaced usage. Use `and` for seaperating filters. - - #### Example - .. code-block:: python - import pyrogram - from tgEasy import tgClient - - app = tgClient(pyrogram.Client()) - - @app.command("start") - async def start(client, message): - await message.reply_text( - f"Hello {message.from_user.mention}", - reply_markup=pyrogram.types.InlineKeyboardMarkup([[ - pyrogram.types.InlineKeyboardButton( - "Click Here", - "data" - ) - ]]) - ) - - @app.callback("data") - async def data(client, CallbackQuery): - await CallbackQuery.answer("Hello :)", show_alert=True) - """ - if filter: - filter = pyrogram.filters.regex(f"^{data}.*") & args["filter"] - else: - filter = pyrogram.filters.regex(f"^{data}.*") - - def wrapper(func): - async def decorator(client, CallbackQuery: pyrogram.types.CallbackQuery): - if self_admin: - me = await client.get_me() - mee = await client.get_chat_member(CallbackQuery.chat.id, me.id) - if not mee.status == "admin": - return await CallbackQuery.message.edit_text("I must be admin to execute this Command") - pass - try: - await func(client, CallbackQuery) - except pyrogram.errors.exceptions.forbidden_403.ChatAdminRequired: - pass - except BaseException as e: - return await handle_error(e, CallbackQuery) - self.__client__.add_handler( - pyrogram.handlers.CallbackQueryHandler(decorator, filter)) - return decorator - return wrapper - - -class AdminsOnly(Scaffold): - def adminsOnly(self, permission: typing.Union[str, list], TRUST_ANON_ADMINS: typing.Union[bool, bool] = False): - """ - ### `tgEasy.tgClient.adminsOnly` - - A decorater for running the function only if the admin have the specified Rights. - - We are still Working on this to make it to check Rights for Anonoymous Admins, Stay Tuned. - - Parameters: - - permission (str): - - Permission which the User must have to use the Functions - - - TRUST_ANON_ADMIN (bool) **optional**: - - If User is Anonymous Admin also, It Runs the Function, By Default False - - ### Example - .. code-block:: python - from tgEasy import tgClient - import pyrogram - - app = tgClient(pyrogram.Client()) - - @app.command("start") - @app.adminsOnly("can_change_info") - async def start(client, message): - await message.reply_text(f"Hello Admin {message.from_user.mention}") - """ - def wrapper(func): - async def decorator(client, message): - if not message.chat.type == "supergroup": - return await message.reply_text("This command can be used in supergroups only.") - if message.sender_chat and not TRUST_ANON_ADMINS: - return await message.reply_text( - "The Right Check for Anonymous Admins is in Development. So you cannot perform this Action for Now, If you don't want this and want to Allow Anonymous Admins for performing Actions in this time Please Contact Bot Owner." - ) - if not await is_admin(message.chat.id, message.from_user.id, client=client): - return await message.reply_text("Only admins can execute this Command!") - if not await check_rights(message.chat.id, message.from_user.id, permission, client=client): - return await message.reply_text(f"You are Missing the following Rights to use this Command:\n{permission}") - try: - await func(client, message) - except pyrogram.errors.exceptions.forbidden_403.ChatWriteForbidden: - await client.leave_chat(message.chat.id) - except BaseException as exception: - await handle_error(exception, message) - return decorator - return wrapper diff --git a/tgEasy/decorater/__init__.py b/tgEasy/decorater/__init__.py new file mode 100644 index 0000000..1e5580c --- /dev/null +++ b/tgEasy/decorater/__init__.py @@ -0,0 +1,3 @@ +from .adminsOnly import AdminsOnly +from .callback import Callback +from .command import Command diff --git a/tgEasy/decorater/adminsOnly.py b/tgEasy/decorater/adminsOnly.py new file mode 100644 index 0000000..c2eeaca --- /dev/null +++ b/tgEasy/decorater/adminsOnly.py @@ -0,0 +1,79 @@ +# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram +# Copyright (C) 2021 Jayant Hegde Kageri + +# This file is part of tgEasy. + +# tgEasy is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# tgEasy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with tgEasy. If not, see . + +import typing + +import pyrogram +from tgEasy.scaffold import Scaffold + +from ..helpers import check_rights, handle_error, is_admin + + +class AdminsOnly(Scaffold): + def adminsOnly(self, permission: typing.Union[str, list], TRUST_ANON_ADMINS: typing.Union[bool, bool] = False): + """ + ### `tgEasy.tgClient.adminsOnly` + - A decorater for running the function only if the admin have the specified Rights. + - We are still Working on this to make it to check Rights for Anonoymous Admins, Stay Tuned. + - Parameters: + - permission (str): + - Permission which the User must have to use the Functions + + - TRUST_ANON_ADMIN (bool) **optional**: + - If User is Anonymous Admin also, It Runs the Function, By Default False + + ### Example + .. code-block:: python + from tgEasy import tgClient + import pyrogram + + app = tgClient(pyrogram.Client()) + + @app.command("start") + @app.adminsOnly("can_change_info") + async def start(client, message): + await message.reply_text(f"Hello Admin {message.from_user.mention}") + """ + def wrapper(func): + async def decorator(client, message): + permissions = "" + if not message.chat.type == "supergroup": + return await message.reply_text("This command can be used in supergroups only.") + if message.sender_chat and not TRUST_ANON_ADMINS: + return await message.reply_text( + "The Right Check for Anonymous Admins is in Development. So you cannot perform this Action for Now, If you don't want this and want to Allow Anonymous Admins for performing Actions in this time Please Contact Bot Owner." + ) + if not await is_admin(message.chat.id, message.from_user.id, client=client): + return await message.reply_text("Only admins can execute this Command!") + if isinstance(permission, str): + if not await check_rights(message.chat.id, message.from_user.id, permission, client=client): + return await message.reply_text(f"You are Missing the following Rights to use this Command:\n{permission}") + if isinstance(permission, list): + for perm in permission: + if not await check_rights(message.chat.id, message.from_user.id, perm, client=client): + permissions += f"\n{perm}" + if not permissions == "": + return await message.reply_text(f"You are Missing the following Rights to use this Command:{permissions}") + try: + await func(client, message) + except pyrogram.errors.exceptions.forbidden_403.ChatWriteForbidden: + await client.leave_chat(message.chat.id) + except BaseException as exception: + await handle_error(exception, message) + return decorator + return wrapper diff --git a/tgEasy/decorater/callback.py b/tgEasy/decorater/callback.py new file mode 100644 index 0000000..e0c1f90 --- /dev/null +++ b/tgEasy/decorater/callback.py @@ -0,0 +1,87 @@ +# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram +# Copyright (C) 2021 Jayant Hegde Kageri + +# This file is part of tgEasy. + +# tgEasy is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# tgEasy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with tgEasy. If not, see . + +import typing + +import pyrogram +from tgEasy.scaffold import Scaffold + +from ..helpers import handle_error + + +class Callback(Scaffold): + def callback(self, data: typing.Union[str, list], self_admin: typing.Union[bool, bool] = False, filter: typing.Union[pyrogram.filters.Filter, pyrogram.filters.Filter] = None, *args, **kwargs): + """ + ### `tgEasy.tgClient.callback` + + - A decorater to Register Callback Quiries in simple way and manage errors in that Function itself, alternative for `@pyrogram.Client.on_callback_query(pyrogram.filters.regex('^data.*'))` + - Parameters: + - data (str || list): + - The callback query to be handled for a function + + - self_admin (bool) **optional**: + - If True, the command will only executeed if the Bot is Admin in the Chat, By Default False + + - filter (`~pyrogram.filters`) **optional**: + - Pyrogram Filters, hope you know about this, for Advaced usage. Use `and` for seaperating filters. + + #### Example + .. code-block:: python + import pyrogram + from tgEasy import tgClient + + app = tgClient(pyrogram.Client()) + + @app.command("start") + async def start(client, message): + await message.reply_text( + f"Hello {message.from_user.mention}", + reply_markup=pyrogram.types.InlineKeyboardMarkup([[ + pyrogram.types.InlineKeyboardButton( + "Click Here", + "data" + ) + ]]) + ) + + @app.callback("data") + async def data(client, CallbackQuery): + await CallbackQuery.answer("Hello :)", show_alert=True) + """ + if filter: + filter = pyrogram.filters.regex(f"^{data}.*") & args["filter"] + else: + filter = pyrogram.filters.regex(f"^{data}.*") + + def wrapper(func): + async def decorator(client, CallbackQuery: pyrogram.types.CallbackQuery): + if self_admin: + me = await client.get_chat_member(CallbackQuery.message.chat.id, (await client.get_me()).id) + if not me.status in ("creator", "administrator"): + return await CallbackQuery.message.edit_text("I must be admin to execute this Command") + pass + try: + await func(client, CallbackQuery) + except pyrogram.errors.exceptions.forbidden_403.ChatAdminRequired: + pass + except BaseException as e: + return await handle_error(e, CallbackQuery) + self.__client__.add_handler( + pyrogram.handlers.CallbackQueryHandler(decorator, filter)) + return decorator + return wrapper diff --git a/tgEasy/decorater/command.py b/tgEasy/decorater/command.py new file mode 100644 index 0000000..91eab49 --- /dev/null +++ b/tgEasy/decorater/command.py @@ -0,0 +1,100 @@ +# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram +# Copyright (C) 2021 Jayant Hegde Kageri + +# This file is part of tgEasy. + +# tgEasy is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# tgEasy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with tgEasy. If not, see . + +import typing + +import pyrogram +from tgEasy.scaffold import Scaffold + +from ..config import Config +from ..helpers import handle_error + + +class Command(Scaffold): + def command(self, command: typing.Union[str, list], pm_only: typing.Union[bool, bool] = False, group_only: typing.Union[bool, bool] = False, self_admin: typing.Union[bool, bool] = False, self_only: typing.Union[bool, bool] = False, filter: typing.Union[pyrogram.filters.Filter, pyrogram.filters.Filter] = None, *args, **kwargs): + """ + ### `tgEasy.tgClient.command` + - A decorater to Register Commands in simple way and manage errors in that Function itself, alternative for `@pyrogram.Client.on_message(pyrogram.filters.command('command'))` + - Parameters: + - command (str || list): + - The command to be handled for a function + + - group_only (bool) **optional**: + - If True, the command will only executed in Groups only, By Default False. + + - pm_only (bool) **optional**: + - If True, the command will only executed in Private Messages only, By Default False. + + - self_only (bool) **optional**: + - If True, the command will only excute if used by Self only, By Default False. + + - self_admin (bool) **optional**: + - If True, the command will only executeed if the Bot is Admin in the Chat, By Default False + + - filter (`~pyrogram.filters`) **optional**: + - Pyrogram Filters, hope you know about this, for Advaced usage. By Default `~pyrogram.filters.edited` and this can't be changed. Use `and` for seaperating filters. + + #### Example + .. code-block:: python + import pyrogram + from tgEasy import tgClient + + app = tgClient(pyrogram.Client()) + + @app.command("start", group_only=False, pm_only=False, self_admin=False, self_only=False, pyrogram.filters.chat("777000") and pyrogram.filters.text) + async def start(client, message): + await message.reply_text(f"Hello {message.from_user.mention}") + """ + if filter: + if self_only: + filter = pyrogram.filters.command( + command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited & filter & pyrogram.filters.me + else: + filter = pyrogram.filters.command( + command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited & filter & pyrogram.filters.me + else: + if self_only: + filter = pyrogram.filters.command( + command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited & pyrogram.filters.me + else: + filter = pyrogram.filters.command( + command, prefixes=Config.HANDLERS) & ~pyrogram.filters.edited + + def wrapper(func): + async def decorator(client, message: pyrogram.types.Message): + if self_admin and message.chat.type != "supergroup": + return await message.reply_text("This command can be used in supergroups only.") + if self_admin: + me = await client.get_chat_member(message.chat.id, (await client.get_me()).id) + if not me.status in ("creator", "administrator"): + return await message.reply_text("I must be admin to execute this Command") + pass + if group_only and message.chat.type != "supergroup": + return await message.reply_text("This command can be used in supergroups only.") + if pm_only and message.chat.type != "private": + return await message.reply_text("This command can be used in PMs only.") + try: + await func(client, message) + except pyrogram.errors.exceptions.forbidden_403.ChatWriteForbidden: + await client.leave_chat(message.chat.id) + except BaseException as exception: + return await handle_error(exception, message) + self.__client__.add_handler(pyrogram.handlers.MessageHandler( + callback=decorator, filters=filter)) + return decorator + return wrapper diff --git a/tgEasy/helpers.py b/tgEasy/helpers.py deleted file mode 100644 index b583795..0000000 --- a/tgEasy/helpers.py +++ /dev/null @@ -1,333 +0,0 @@ -# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram -# Copyright (C) 2021 Jayant Hegde Kageri - -# This file is part of tgEasy. - -# tgEasy is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# tgEasy is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public License -# along with tgEasy. If not, see . - -import os -import typing - -import pyrogram - -import tgEasy - -from .config import Config -from .scaffold import Scaffold - - -async def get_user(m: typing.Union[pyrogram.types.Message, pyrogram.types.CallbackQuery]): - """ -### `tgEasy.get_user` -- Gets a User from Message/RepliedMessage/CallbackQuery -- Parameters: - - m (`~pyrogram.types.Message` || `~pyrogram.types.CallbackQuery`) -- Returns: - - `pyrogram.types.User` on Success - - `False` on Error - -#### Example - .. code-block:: python - from tgEasy import get_user, command, adminsOnly - - @command("ban", group_only=True, self_admin=True) - @adminsOnly("can_restrict_members") - async def ban(client, message): - user = await get_user(message) - await message.chat.kick_member(user.id) - """ - if isinstance(m, pyrogram.types.Message): - message = m - client = m._client - if isinstance(m, pyrogram.types.CallbackQuery): - message = m.message - client = message._client - if message.reply_to_message: - if message.reply_to_message.sender_chat: - return False - return await client.get_users(message.reply_to_message.from_user.id) - - if len(message.command) > 1: - command = message.command[1] - else: - command = None - - if command: - if command.startswith("@") or command.isdigit(): - try: - return await client.get_users(message.command[1]) - except pyrogram.errors.exceptions.bad_request_400.UsernameNotOccupied: - pass - except pyrogram.errors.exceptions.bad_request_400.UsernameInvalid: - pass - except pyrogram.errors.exceptions.bad_request_400.PeerIdInvalid: - pass - except IndexError: - pass - else: - pass - - if message.entities: - for mention in message.entities: - if mention.type == "text_mention": - user = mention.user.id - break - try: - return await client.get_users(user) - except: - pass - return False - - -async def get_user_adv(m: typing.Union[pyrogram.types.Message, pyrogram.types.CallbackQuery]): - """ -### `tgEasy.get_user_adv` -- A Function to Get the User from the Message/CallbackQuery, If there is None arguments, returns the From User. -- Parameters: - - m (`pyrogram.types.Message` || `pyrogram.types.CallbackQuery`): - - Message or Callbackquery. -- Returns: - - `pyrogram.types.User` on Success - - `False` on Error - -#### Example - .. code-block:: python - from tgEasy import command, get_user_adv - - @command("id") - async def id(client, message): - user = await get_user_adv(message) - await message.reply_text(f"Your ID is `{user.id}`") - """ - if isinstance(m, pyrogram.types.Message): - message = m - if isinstance(m, pyrogram.types.CallbackQuery): - message = m.message - if message.sender_chat: - return False - try: - if len(message.command) > 1: - if message.command[1].startswith("@"): - return await get_user(message) - if message.command[1].isdigit(): - return await get_user(message) - if "text_mention" in message.entities: - return await get_user(message) - if "from_user" in str(message.reply_to_message): - return await get_user(message) - except IndexError: - pass - except AttributeError: - pass - - try: - if "sender_chat" in str(message.reply_to_message): - return False - if "from_user" in str(message.reply_to_message): - return await message._client.get_users(message.reply_to_message.from_user.id) - except AttributeError: - pass - except Exception as e: - pass - - return await message._client.get_users(message.from_user.id) - - -async def send_typing(m: typing.Union[pyrogram.types.Message, pyrogram.types.CallbackQuery]): - """ -### `tgEasy.send_typing` -- A Function to Send the Typing Status to the Chat. - -- Parameters: - - m (`pyrogram.types.Message` || `pyrogram.types.CallbackQuery`): - - Message or Callbackquery. - -#### Example - .. code-block:: python - from tgEasy import tgClinet, send_typing - import pyrogram - - app = tgClient(pyrogram.Client()) - - @app.command("start") - async def start(client, message): - await send_typing(message) - await message.reply_text("Hello") - """ - if isinstance(m, pyrogram.types.Message): - message = m - if isinstance(m, pyrogram.types.CallbackQuery): - message = m.message - for i in range(3): - return await message._client.send_chat_action(message.chat.id, "typing") - - -async def handle_error(error, m: typing.Union[pyrogram.types.Message, pyrogram.types.CallbackQuery]): - """ -### `tgEasy.handle_error` -- A Function to Handle the Errors in Functions. -- This Sends the Error Log to the Log Group and Replies Sorry Message for the Users. -- This is Helper for all of the functions for handling the Errors. - -- Parameters: - - error: - - The Exceptation. - - - m (`pyrogram.types.Message` or `pyrogram.types.CallbackQuery`): - - The Message or Callback Query where the Error occurred. - -#### Exapmle - .. code-block:: python - from tgEasy import tgClient, handle_error - import pyrogram - - app = tgClient(pyrogram.Client()) - - @app.command("start") - async def start(client, message): - try: - await message.reply_text("Hi :D') # I intentionally made an bug for Example :/ - except Exceptation as e: - return await handle_error(e, message) - """ - import traceback - - from . import logging - with open("crash.log", "w+", encoding="utf-8") as log: - log.write(traceback.format_exc()) - log.close() - if isinstance(m, pyrogram.types.Message): - try: - await m.reply_text("An Internal Error Occurred while Processing your Command, the Logs have been sent to the Owners of this Bot. Sorry for Inconvenience") - await m._client.send_document(Config.LOGS, "crash.log", caption="Crash Report of this Bot") - except: - pass - if isinstance(m, pyrogram.types.CallbackQuery): - try: - await m.message.delete() - await m.message.reply_text("An Internal Error Occurred while Processing your Command, the Logs have been sent to the Owners of this Bot. Sorry for Inconvenience") - await m.message._client.send_document(Config.LOGS, "crash.log", caption="Crash Report of this Bot") - except: - pass - logging.exception(traceback.format_exc()) - os.remove('crash.log') - - -async def check_rights(chat_id: typing.Union[int, int], user_id: typing.Union[int, int], rights: typing.Union[str, str], client) -> bool: - """ - ### `tgEasy.check_rights` - - Checks the Rights of an User - - This is an Helper Function for `adminsOnly` - - - Parameters: - - chat_id (int): - - The Chat ID of Which Chat have to check the Rights. - - - user_id (int): - - The User ID of Whose Rights have to Check. - - - rights (str): - - The Rights have to Check. - - - client (`pyrogram.Client`): - - From which Client to Check the Rights. - - - Returns: - - `True` if the User have the Right. - - `False` if the User don't have the Right. - - #### Example - .. code-block:: python - from tgEasy import tgClient, check_rights, get_user - import pyrogram - - app = tgClient(pyrogram.Client()) - - @app.command("ban", group_only=True, self_admin=True) - async def ban(client, message): - if not await check_rights(message.chat.id, message.from_user.id, "can_restrict_members"): - return await message.reply_text("You don't have necessary rights to use this Command.") - user = await get_user(message) - await message.chat.kick_member(user.id) - """ - try: - user = await client.get_chat_member(chat_id, user_id) - except: - return False - if user.status == "user": - return False - if user.status in ("administrator", "creator"): - permission = [] - if user.can_delete_messages: - permission.append("can_delete_messages") - if user.can_restrict_members: - permission.append("can_restrict_members") - if user.can_promote_members: - permission.append("can_promote_members") - if user.can_change_info: - permission.append("can_change_info") - if user.can_invite_users: - permission.append("can_invite_users") - if user.can_pin_messages: - permission.append("can_pin_messages") - if user.can_manage_voice_chats: - permission.append("can_manage_voice_chats") - if user.is_anonymous: - permission.append("is_anonymous") - if rights in permission: - return True - return False - return False - - -async def is_admin(chat_id: typing.Union[int, str], user_id: typing.Union[int, str], client) -> bool: - """ - ### `tgEasy.is_admin` - - A Functions to Check if the User is Admin or not - - - Parameters: - - chat_id (int): - - The Chat ID of Which Chat have to check the Admin Status. - - - user_id (int): - - The User ID of Whose Admin Status have to Check. - - - client (`pyrogram.Client`): - - From which Client to Check the Admin Status. - - - Returns: - - `True` if the User is Admin. - - `False` if the User is't Admin. - #### Example - .. code-block:: python - from tgEasy import tgClient, is_admin, adminsOnly - import pyrogram - - app = tgClient(pyrogram.Client()) - - @app.command("ban", group_only=True, self_admin=True) - @app.adminsOnly("can_restrict_members") - async def ban(client, message): - if await is_admin(message.chat.id, (await get_user(mesasge)).id): - return await message.reply_text("You can't Ban Admins.") - await message.chat.kick_member((await get_user(message)).id) - await message.reply_text("User has been Banned.") - """ - try: - user = await client.get_chat_member(chat_id, user_id) - except: - return False - if user.status in ("administrator", "creator"): - return True - return False diff --git a/tgEasy/helpers/__init__.py b/tgEasy/helpers/__init__.py new file mode 100644 index 0000000..35f5aa9 --- /dev/null +++ b/tgEasy/helpers/__init__.py @@ -0,0 +1,4 @@ +from .admin_utils import check_rights, is_admin +from .get_user import get_user, get_user_adv +from .handle_error import handle_error +from .send_typing import send_typing diff --git a/tgEasy/helpers/admin_utils.py b/tgEasy/helpers/admin_utils.py new file mode 100644 index 0000000..7f93f30 --- /dev/null +++ b/tgEasy/helpers/admin_utils.py @@ -0,0 +1,134 @@ +# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram +# Copyright (C) 2021 Jayant Hegde Kageri + +# This file is part of tgEasy. + +# tgEasy is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# tgEasy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with tgEasy. If not, see . + +import typing + + +async def check_rights(chat_id: typing.Union[int, int], user_id: typing.Union[int, int], rights: typing.Union[str, list], client) -> bool: + """ + ### `tgEasy.check_rights` + - Checks the Rights of an User + - This is an Helper Function for `adminsOnly` + + - Parameters: + - chat_id (int): + - The Chat ID of Which Chat have to check the Rights. + + - user_id (int): + - The User ID of Whose Rights have to Check. + + - rights (str): + - The Rights have to Check. + + - client (`pyrogram.Client`): + - From which Client to Check the Rights. + + - Returns: + - `True` if the User have the Right. + - `False` if the User don't have the Right. + + #### Example + .. code-block:: python + from tgEasy import tgClient, check_rights, get_user + import pyrogram + + app = tgClient(pyrogram.Client()) + + @app.command("ban", group_only=True, self_admin=True) + async def ban(client, message): + if not await check_rights(message.chat.id, message.from_user.id, "can_restrict_members"): + return await message.reply_text("You don't have necessary rights to use this Command.") + user = await get_user(message) + await message.chat.kick_member(user.id) + """ + try: + user = await client.get_chat_member(chat_id, user_id) + except: + return False + if user.status == "user": + return False + if user.status in ("administrator", "creator"): + permission = [] + if user.can_delete_messages: + permission.append("can_delete_messages") + if user.can_restrict_members: + permission.append("can_restrict_members") + if user.can_promote_members: + permission.append("can_promote_members") + if user.can_change_info: + permission.append("can_change_info") + if user.can_invite_users: + permission.append("can_invite_users") + if user.can_pin_messages: + permission.append("can_pin_messages") + if user.can_manage_voice_chats: + permission.append("can_manage_voice_chats") + if user.is_anonymous: + permission.append("is_anonymous") + if isinstance(rights, str): + if rights in permission: + return True + return False + if isinstance(rights, list): + for right in rights: + if not right in permission: + return False + return True + return False + + +async def is_admin(chat_id: typing.Union[int, str], user_id: typing.Union[int, str], client) -> bool: + """ + ### `tgEasy.is_admin` + - A Functions to Check if the User is Admin or not + + - Parameters: + - chat_id (int): + - The Chat ID of Which Chat have to check the Admin Status. + + - user_id (int): + - The User ID of Whose Admin Status have to Check. + + - client (`pyrogram.Client`): + - From which Client to Check the Admin Status. + + - Returns: + - `True` if the User is Admin. + - `False` if the User is't Admin. + #### Example + .. code-block:: python + from tgEasy import tgClient, is_admin, adminsOnly + import pyrogram + + app = tgClient(pyrogram.Client()) + + @app.command("ban", group_only=True, self_admin=True) + @app.adminsOnly("can_restrict_members") + async def ban(client, message): + if await is_admin(message.chat.id, (await get_user(mesasge)).id): + return await message.reply_text("You can't Ban Admins.") + await message.chat.kick_member((await get_user(message)).id) + await message.reply_text("User has been Banned.") + """ + try: + user = await client.get_chat_member(chat_id, user_id) + except: + return False + if user.status in ("administrator", "creator"): + return True + return False diff --git a/tgEasy/helpers/get_user.py b/tgEasy/helpers/get_user.py new file mode 100644 index 0000000..70c55bf --- /dev/null +++ b/tgEasy/helpers/get_user.py @@ -0,0 +1,138 @@ +# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram +# Copyright (C) 2021 Jayant Hegde Kageri + +# This file is part of tgEasy. + +# tgEasy is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# tgEasy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with tgEasy. If not, see . + +import typing + +import pyrogram + + +async def get_user(m: typing.Union[pyrogram.types.Message, pyrogram.types.CallbackQuery]): + """ +### `tgEasy.get_user` +- Gets a User from Message/RepliedMessage/CallbackQuery +- Parameters: + - m (`~pyrogram.types.Message` || `~pyrogram.types.CallbackQuery`) +- Returns: + - `pyrogram.types.User` on Success + - `False` on Error + +#### Example + .. code-block:: python + from tgEasy import get_user, command, adminsOnly + + @command("ban", group_only=True, self_admin=True) + @adminsOnly("can_restrict_members") + async def ban(client, message): + user = await get_user(message) + await message.chat.kick_member(user.id) + """ + if isinstance(m, pyrogram.types.Message): + message = m + client = m._client + if isinstance(m, pyrogram.types.CallbackQuery): + message = m.message + client = message._client + if message.reply_to_message: + if message.reply_to_message.sender_chat: + return False + return await client.get_users(message.reply_to_message.from_user.id) + + if len(message.command) > 1: + command = message.command[1] + else: + command = None + + if command: + if command.startswith("@") or command.isdigit(): + try: + return await client.get_users(message.command[1]) + except pyrogram.errors.exceptions.bad_request_400.UsernameNotOccupied: + pass + except pyrogram.errors.exceptions.bad_request_400.UsernameInvalid: + pass + except pyrogram.errors.exceptions.bad_request_400.PeerIdInvalid: + pass + except IndexError: + pass + else: + pass + + if message.entities: + for mention in message.entities: + if mention.type == "text_mention": + user = mention.user.id + break + try: + return await client.get_users(user) + except: + pass + return False + + +async def get_user_adv(m: typing.Union[pyrogram.types.Message, pyrogram.types.CallbackQuery]): + """ +### `tgEasy.get_user_adv` +- A Function to Get the User from the Message/CallbackQuery, If there is None arguments, returns the From User. +- Parameters: + - m (`pyrogram.types.Message` || `pyrogram.types.CallbackQuery`): + - Message or Callbackquery. +- Returns: + - `pyrogram.types.User` on Success + - `False` on Error + +#### Example + .. code-block:: python + from tgEasy import command, get_user_adv + + @command("id") + async def id(client, message): + user = await get_user_adv(message) + await message.reply_text(f"Your ID is `{user.id}`") + """ + if isinstance(m, pyrogram.types.Message): + message = m + if isinstance(m, pyrogram.types.CallbackQuery): + message = m.message + if message.sender_chat: + return False + try: + if len(message.command) > 1: + if message.command[1].startswith("@"): + return await get_user(message) + if message.command[1].isdigit(): + return await get_user(message) + if "text_mention" in message.entities: + return await get_user(message) + if "from_user" in str(message.reply_to_message): + return await get_user(message) + except IndexError: + pass + except AttributeError: + pass + + try: + if "sender_chat" in str(message.reply_to_message): + return False + if "from_user" in str(message.reply_to_message): + return await message._client.get_users(message.reply_to_message.from_user.id) + except AttributeError: + pass + except Exception as e: + pass + + return await message._client.get_users(message.from_user.id) diff --git a/tgEasy/helpers/handle_error.py b/tgEasy/helpers/handle_error.py new file mode 100644 index 0000000..df89268 --- /dev/null +++ b/tgEasy/helpers/handle_error.py @@ -0,0 +1,75 @@ +# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram +# Copyright (C) 2021 Jayant Hegde Kageri + +# This file is part of tgEasy. + +# tgEasy is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# tgEasy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with tgEasy. If not, see . + +import os +import typing + +import pyrogram + +from ..config import Config + + +async def handle_error(error, m: typing.Union[pyrogram.types.Message, pyrogram.types.CallbackQuery]): + """ +### `tgEasy.handle_error` +- A Function to Handle the Errors in Functions. +- This Sends the Error Log to the Log Group and Replies Sorry Message for the Users. +- This is Helper for all of the functions for handling the Errors. + +- Parameters: + - error: + - The Exceptation. + + - m (`pyrogram.types.Message` or `pyrogram.types.CallbackQuery`): + - The Message or Callback Query where the Error occurred. + +#### Exapmle + .. code-block:: python + from tgEasy import tgClient, handle_error + import pyrogram + + app = tgClient(pyrogram.Client()) + + @app.command("start") + async def start(client, message): + try: + await message.reply_text("Hi :D') # I intentionally made an bug for Example :/ + except Exceptation as e: + return await handle_error(e, message) + """ + import traceback + + from . import logging + with open("crash.log", "w+", encoding="utf-8") as log: + log.write(traceback.format_exc()) + log.close() + if isinstance(m, pyrogram.types.Message): + try: + await m.reply_text("An Internal Error Occurred while Processing your Command, the Logs have been sent to the Owners of this Bot. Sorry for Inconvenience") + await m._client.send_document(Config.LOGS, "crash.log", caption="Crash Report of this Bot") + except: + pass + if isinstance(m, pyrogram.types.CallbackQuery): + try: + await m.message.delete() + await m.message.reply_text("An Internal Error Occurred while Processing your Command, the Logs have been sent to the Owners of this Bot. Sorry for Inconvenience") + await m.message._client.send_document(Config.LOGS, "crash.log", caption="Crash Report of this Bot") + except: + pass + logging.exception(traceback.format_exc()) + os.remove('crash.log') diff --git a/tgEasy/helpers/send_typing.py b/tgEasy/helpers/send_typing.py new file mode 100644 index 0000000..636a456 --- /dev/null +++ b/tgEasy/helpers/send_typing.py @@ -0,0 +1,50 @@ +# tgEasy - Easy for a brighter Shine. A monkey pather add-on for Pyrogram +# Copyright (C) 2021 Jayant Hegde Kageri + +# This file is part of tgEasy. + +# tgEasy is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# tgEasy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with tgEasy. If not, see . + +import typing + +import pyrogram + + +async def send_typing(m: typing.Union[pyrogram.types.Message, pyrogram.types.CallbackQuery]): + """ +### `tgEasy.send_typing` +- A Function to Send the Typing Status to the Chat. + +- Parameters: + - m (`pyrogram.types.Message` || `pyrogram.types.CallbackQuery`): + - Message or Callbackquery. + +#### Example + .. code-block:: python + from tgEasy import tgClinet, send_typing + import pyrogram + + app = tgClient(pyrogram.Client()) + + @app.command("start") + async def start(client, message): + await send_typing(message) + await message.reply_text("Hello") + """ + if isinstance(m, pyrogram.types.Message): + message = m + if isinstance(m, pyrogram.types.CallbackQuery): + message = m.message + for i in range(3): + return await message._client.send_chat_action(message.chat.id, "typing") diff --git a/tgEasy/scaffold.py b/tgEasy/scaffold.py index d057778..9ad2aba 100644 --- a/tgEasy/scaffold.py +++ b/tgEasy/scaffold.py @@ -17,12 +17,6 @@ # along with tgEasy. If not, see . import asyncio -import os -import platform -import re -import sys - -import pyrogram import tgEasy