From c5f9b2abc4da844721dc967a21cf4003e71cb9bd Mon Sep 17 00:00:00 2001 From: rking32 Date: Thu, 9 Jul 2020 23:54:24 +0530 Subject: [PATCH] add buttons to notes --- app.json | 7 +- config.env.sample | 8 +- userge/config.py | 22 +- userge/core/client.py | 6 +- .../core/methods/decorators/raw_decorator.py | 2 +- userge/core/types/new/channel_logger.py | 189 ++++++++++-------- userge/plugins/misc/gdrive.py | 4 +- userge/plugins/misc/utube.py | 4 +- userge/plugins/tools/executor.py | 2 +- 9 files changed, 135 insertions(+), 109 deletions(-) diff --git a/app.json b/app.json index c7adf113f..aec0ddaaa 100644 --- a/app.json +++ b/app.json @@ -47,6 +47,9 @@ "description": "Set True if it is TeamDrive", "value": "True" }, + "LOG_CHANNEL_ID": { + "description": "Telegram Log Channel ID" + }, "G_DRIVE_INDEX_LINK": { "description": "Index link for gdrive", "required": false @@ -95,10 +98,6 @@ "description": "GDrive Folder ID", "required": false }, - "LOG_CHANNEL_ID": { - "description": "Telegram Log Channel ID", - "required": false - }, "HEROKU_APP_NAME": { "description": "given app name to the heroku app", "required": false diff --git a/config.env.sample b/config.env.sample index ab289d14d..282dd64fd 100644 --- a/config.env.sample +++ b/config.env.sample @@ -33,6 +33,10 @@ G_DRIVE_CLIENT_SECRET = "" G_DRIVE_IS_TD = False +# Telegram Log Channel ID +LOG_CHANNEL_ID = "" + + # Set True if your like to use unofficial plugins LOAD_UNOFFICIAL_PLUGINS = False @@ -96,10 +100,6 @@ REMOVE_BG_API_KEY = "" G_DRIVE_PARENT_ID = "" -# Telegram Log Channel ID -LOG_CHANNEL_ID = "" - - # set command prefix CMD_TRIGGER = "." diff --git a/userge/config.py b/userge/config.py index ef7c77345..4f5fd3efd 100644 --- a/userge/config.py +++ b/userge/config.py @@ -93,6 +93,10 @@ class Config: HEROKU_GIT_URL = None +if not Config.LOG_CHANNEL_ID: + _LOG.error("Need LOG_CHANNEL_ID !, Exiting ...") + sys.exit() + if Config.SUDO_TRIGGER == Config.CMD_TRIGGER: _LOG.info("Invalid SUDO_TRIGGER!, You can't use `%s` as SUDO_TRIGGER", Config.CMD_TRIGGER) sys.exit() @@ -150,15 +154,15 @@ class Config: if Config.LOAD_UNOFFICIAL_PLUGINS: _LOG.info("Loading UnOfficial Plugins...") - # pylint: disable=BAN-B607 - os.system("git clone --depth=1 https://github.com/UsergeTeam/Userge-Plugins.git") - os.system("pip3 install -U pip") - os.system("pip3 install -r Userge-Plugins/requirements.txt") - os.system("rm -rf userge/plugins/unofficial/") - os.system("mv Userge-Plugins/plugins/ userge/plugins/unofficial/") - os.system("cp -r Userge-Plugins/resources/* resources/") - os.system("rm -rf Userge-Plugins/") - _LOG.info("UnOfficial Plugins Loaded Successfully!") + _CMDS = ["git clone --depth=1 https://github.com/UsergeTeam/Userge-Plugins.git", + "pip3 install -U pip", + "pip3 install -r Userge-Plugins/requirements.txt", + "rm -rf userge/plugins/unofficial/", + "mv Userge-Plugins/plugins/ userge/plugins/unofficial/", + "cp -r Userge-Plugins/resources/* resources/", + "rm -rf Userge-Plugins/"] + os.system(" && ".join(_CMDS)) # nosec + _LOG.info("UnOfficial Plugins Loaded Successfully!") # nosec def get_version() -> str: diff --git a/userge/core/client.py b/userge/core/client.py index 6e2f8aa98..c2595afeb 100644 --- a/userge/core/client.py +++ b/userge/core/client.py @@ -109,10 +109,8 @@ async def restart(self, update_req: bool = False) -> None: # pylint: disable=ar _LOG.error(_LOG_STR, c_e) if update_req: _LOG.info(_LOG_STR, "Installing Requirements...") - # pylint: disable=BAN-B607 - os.system("pip3 install -U pip") - os.system("pip3 install -r requirements.txt") - os.execl(sys.executable, sys.executable, '-m', 'userge') # pylint: disable=BAN-B606 + os.system("pip3 install -U pip && pip3 install -r requirements.txt") # nosec + os.execl(sys.executable, sys.executable, '-m', 'userge') # nosec sys.exit() diff --git a/userge/core/methods/decorators/raw_decorator.py b/userge/core/methods/decorators/raw_decorator.py index 5b31690bf..a2e536731 100644 --- a/userge/core/methods/decorators/raw_decorator.py +++ b/userge/core/methods/decorators/raw_decorator.py @@ -102,7 +102,7 @@ async def template(r_c: Union['_client.Userge', '_client._UsergeBot'], else: try: await func(types.bound.Message(r_c, r_m, **kwargs)) - except (StopPropagation, ContinuePropagation): # pylint: disable=PYL-W0706 + except (StopPropagation, ContinuePropagation): # pylint: disable=W0706 raise except Exception as f_e: # pylint: disable=broad-except _LOG.exception(_LOG_STR, f_e) diff --git a/userge/core/types/new/channel_logger.py b/userge/core/types/new/channel_logger.py index b3743de08..5a4ad931e 100644 --- a/userge/core/types/new/channel_logger.py +++ b/userge/core/types/new/channel_logger.py @@ -10,11 +10,11 @@ __all__ = ['ChannelLogger'] +import re import asyncio -from typing import Optional, Tuple, Union +from typing import Optional, List, Tuple, Union -from pyrogram import Message as RawMessage -from pyrogram.errors.exceptions.bad_request_400 import ChannelInvalid +from pyrogram import Message as RawMessage, InlineKeyboardButton, InlineKeyboardMarkup from userge import logging, Config from userge.utils import SafeDict @@ -23,6 +23,7 @@ _LOG = logging.getLogger(__name__) _LOG_STR = "<<>>" +_BTN_URL_REGEX = re.compile(r"(\[([^\[]+?)\]\[buttonurl:(?:/{0,2})(.+?)(:same)?\])") def _gen_string(name: str) -> str: @@ -51,6 +52,41 @@ def _get_file_id_and_ref(message: '_message.Message') -> Tuple[Optional[str], Op return None, None +def _parse_buttons(markdown_note: str): + prev = 0 + note_data = "" + buttons: List[Tuple[str, str, str]] = [] + for match in _BTN_URL_REGEX.finditer(markdown_note): + # Check if btnurl is escaped + n_escapes = 0 + to_check = match.start(1) - 1 + while to_check > 0 and markdown_note[to_check] == "\\": + n_escapes += 1 + to_check -= 1 + # if even, not escaped -> create button + if n_escapes % 2 == 0: + # create a tuple with button label, url, and newline status + buttons.append((match.group(2), match.group(3), bool(match.group(4)))) + note_data += markdown_note[prev:match.start(1)] + prev = match.end(1) + # if odd, escaped -> move along + else: + note_data += markdown_note[prev:to_check] + prev = match.start(1) - 1 + note_data += markdown_note[prev:] + return note_data.strip(), _build_keyboard(buttons) + + +def _build_keyboard(buttons: List[Tuple[str, str, str]]): + keyb: List[List[InlineKeyboardButton]] = [] + for btn in buttons: + if btn[2] and keyb: + keyb[-1].append(InlineKeyboardButton(btn[0], url=btn[1])) + else: + keyb.append([InlineKeyboardButton(btn[0], url=btn[1])]) + return keyb + + class ChannelLogger: """ Channel logger for Userge """ def __init__(self, client: Union['_client.Userge', '_client._UsergeBot'], name: str) -> None: @@ -95,7 +131,7 @@ def update(self, name: str) -> None: """ self._string = _gen_string(name) - async def log(self, text: str) -> Optional[int]: + async def log(self, text: str) -> int: """\nsend text message to log channel. Parameters: @@ -106,13 +142,9 @@ async def log(self, text: str) -> Optional[int]: message_id on success or None """ _LOG.debug(_LOG_STR, f"logging text : {text} to channel : {Config.LOG_CHANNEL_ID}") - if Config.LOG_CHANNEL_ID: - try: - msg = await self._client.send_message(chat_id=Config.LOG_CHANNEL_ID, - text=self._string.format(text.strip())) - return msg.message_id - except ChannelInvalid: - pass + msg = await self._client.send_message(chat_id=Config.LOG_CHANNEL_ID, + text=self._string.format(text.strip())) + return msg.message_id async def fwd_msg(self, message: '_message.Message', @@ -141,24 +173,21 @@ async def fwd_msg(self, """ _LOG.debug( _LOG_STR, f"forwarding msg : {message} to channel : {Config.LOG_CHANNEL_ID}") - if Config.LOG_CHANNEL_ID and isinstance(message, RawMessage): - try: - if message.media: - asyncio.get_event_loop().create_task(self.log("**Forwarding Message...**")) - await self._client.forward_messages(chat_id=Config.LOG_CHANNEL_ID, - from_chat_id=message.chat.id, - message_ids=message.message_id, - as_copy=as_copy, - remove_caption=remove_caption) - else: - await self.log( - message.text.html if hasattr(message.text, 'html') else message.text) - except ChannelInvalid: - pass + if isinstance(message, RawMessage): + if message.media: + asyncio.get_event_loop().create_task(self.log("**Forwarding Message...**")) + await self._client.forward_messages(chat_id=Config.LOG_CHANNEL_ID, + from_chat_id=message.chat.id, + message_ids=message.message_id, + as_copy=as_copy, + remove_caption=remove_caption) + else: + await self.log( + message.text.html if hasattr(message.text, 'html') else message.text) async def store(self, message: Optional['_message.Message'], - caption: Optional[str] = '') -> Optional[int]: + caption: Optional[str] = '') -> int: """\nstore message to log channel. Parameters: @@ -171,27 +200,23 @@ async def store(self, Returns: message_id on success or None """ - if Config.LOG_CHANNEL_ID: - caption = caption or '' - file_id = file_ref = None - if message and message.caption: - caption = caption + message.caption.html - if message: - file_id, file_ref = _get_file_id_and_ref(message) - if message and message.media and file_id and file_ref: - if caption: - caption = self._string.format(caption.strip()) - try: - msg = await self._client.send_cached_media(chat_id=Config.LOG_CHANNEL_ID, - file_id=file_id, - file_ref=file_ref, - caption=caption) - message_id = msg.message_id - except ChannelInvalid: - message_id = None - else: - message_id = await self.log(caption) - return message_id + caption = caption or '' + file_id = file_ref = None + if message and message.caption: + caption = caption + message.caption.html + if message: + file_id, file_ref = _get_file_id_and_ref(message) + if message and message.media and file_id and file_ref: + if caption: + caption = self._string.format(caption.strip()) + msg = await self._client.send_cached_media(chat_id=Config.LOG_CHANNEL_ID, + file_id=file_id, + file_ref=file_ref, + caption=caption) + message_id = msg.message_id + else: + message_id = await self.log(caption) + return message_id async def forward_stored(self, client: Union['_client.Userge', '_client._UsergeBot'], @@ -224,38 +249,38 @@ async def forward_stored(self, Returns: None """ - if Config.LOG_CHANNEL_ID: - try: - message = await self._client.get_messages(chat_id=Config.LOG_CHANNEL_ID, - message_ids=message_id) - caption = '' - file_id = file_ref = None - if message.caption: - caption = message.caption.html.split('\n\n', maxsplit=1)[-1] - elif message.text: - caption = message.text.html.split('\n\n', maxsplit=1)[-1] - if caption: - u_dict = await self._client.get_user_dict(user_id) - chat = await self._client.get_chat(chat_id) - u_dict.update( - {'chat': chat.title if chat.title else "this group", - 'count': chat.members_count}) - caption = caption.format_map(SafeDict(**u_dict)) - file_id, file_ref = _get_file_id_and_ref(message) - if message.media and file_id and file_ref: - msg = await client.send_cached_media( - chat_id=chat_id, - file_id=file_id, - file_ref=file_ref, - caption=caption, - reply_to_message_id=reply_to_message_id) - else: - msg = await client.send_message( - chat_id=chat_id, - text=caption, - reply_to_message_id=reply_to_message_id) - if del_in and msg: - await asyncio.sleep(del_in) - await msg.delete() - except ChannelInvalid: - pass + message = await self._client.get_messages(chat_id=Config.LOG_CHANNEL_ID, + message_ids=message_id) + caption = '' + file_id = file_ref = None + if message.caption: + caption = message.caption.html.split('\n\n', maxsplit=1)[-1] + elif message.text: + caption = message.text.html.split('\n\n', maxsplit=1)[-1] + if caption: + u_dict = await self._client.get_user_dict(user_id) + chat = await self._client.get_chat(chat_id) + u_dict.update({ + 'chat': chat.title if chat.title else "this group", 'count': chat.members_count}) + caption = caption.format_map(SafeDict(**u_dict)) + file_id, file_ref = _get_file_id_and_ref(message) + caption, buttons = _parse_buttons(caption) + if message.media and file_id and file_ref: + msg = await client.send_cached_media( + chat_id=chat_id, + file_id=file_id, + file_ref=file_ref, + caption=caption, + reply_to_message_id=reply_to_message_id, + disable_web_page_preview=True, + reply_markup=InlineKeyboardMarkup(buttons) if hasattr(client, 'ubot') else None) + else: + msg = await client.send_message( + chat_id=chat_id, + text=caption, + reply_to_message_id=reply_to_message_id, + disable_web_page_preview=True, + reply_markup=InlineKeyboardMarkup(buttons) if hasattr(client, 'ubot') else None) + if del_in and msg: + await asyncio.sleep(del_in) + await msg.delete() diff --git a/userge/plugins/misc/gdrive.py b/userge/plugins/misc/gdrive.py index 76eed0878..e07a6ca63 100644 --- a/userge/plugins/misc/gdrive.py +++ b/userge/plugins/misc/gdrive.py @@ -13,7 +13,7 @@ import re import time import math -import pickle # pylint: disable=BAN-B403 +import pickle # nosec import asyncio from json import dumps from functools import wraps @@ -52,7 +52,7 @@ async def _init() -> None: global _CREDS # pylint: disable=global-statement _LOG.debug("Setting GDrive DBase...") result = await _SAVED_SETTINGS.find_one({'_id': 'GDRIVE'}, {'creds': 1}) - _CREDS = pickle.loads(result['creds']) if result else None # pylint: disable=BAN-B301 + _CREDS = pickle.loads(result['creds']) if result else None # nosec async def _set_creds(creds: object) -> str: diff --git a/userge/plugins/misc/utube.py b/userge/plugins/misc/utube.py index 86bbe1e28..a9cfcaaf2 100644 --- a/userge/plugins/misc/utube.py +++ b/userge/plugins/misc/utube.py @@ -38,10 +38,10 @@ async def ytinfo(message: Message): out = """ **Title** >> __{title}__ - + **Uploader** >> __{uploader}__ - + {table} """.format_map(_exracted) if _exracted['thumb']: diff --git a/userge/plugins/tools/executor.py b/userge/plugins/tools/executor.py index 15f1344ec..b1c7b70f5 100644 --- a/userge/plugins/tools/executor.py +++ b/userge/plugins/tools/executor.py @@ -37,7 +37,7 @@ async def eval_(message: Message): stdout, stderr, exc = None, None, None async def aexec(code): - exec("async def __aexec(userge, message):\n " + exec("async def __aexec(userge, message):\n " # nosec + '\n '.join(line for line in code.split('\n'))) return await locals()['__aexec'](userge, message) try: