diff --git a/init/init.sh b/init/init.sh index 5f6a0d3a7..f2789e7df 100644 --- a/init/init.sh +++ b/init/init.sh @@ -12,6 +12,9 @@ . init/utils.sh . init/checks.sh +trap handleSigTerm TERM +trap handleSigInt INT + initUserge() { printLogo assertPrerequisites @@ -27,12 +30,22 @@ startUserge() { stopUserge() { sendMessage "Exiting Userge ..." - stopBGProcesses exit 0 } -trap quit TERM -trap stopUserge INT +handleSigTerm() { + log "Exiting With SIGTERM (143) ..." + stopUserge + endLogBotPolling + exit 143 +} + +handleSigInt() { + log "Exiting With SIGINT (130) ..." + stopUserge + endLogBotPolling + exit 130 +} runUserge() { initUserge diff --git a/init/logbot/methods/methods.sh b/init/logbot/methods/methods.sh index c6c8a9629..87fe757c7 100644 --- a/init/logbot/methods/methods.sh +++ b/init/logbot/methods/methods.sh @@ -42,6 +42,10 @@ startLogBotPolling() { test -z $BOT_TOKEN || _polling & } +endLogBotPolling() { + test -z $BOT_TOKEN || echo quit >> logs/logbot.stdin +} + _polling() { local cmd func args input=logs/logbot.stdin rm -f $input diff --git a/init/utils.sh b/init/utils.sh index 366429ec1..ff55d9566 100644 --- a/init/utils.sh +++ b/init/utils.sh @@ -17,20 +17,13 @@ log() { } quit() { - local err="\t:: ERROR :: $1\nExiting With SIGTERM ..." + local err="\t:: ERROR :: $1\nExiting With SIGTERM (143) ..." if (( getMessageCount )); then replyLastMessage "$err" else log "$err" fi - exit 1 -} - -stopBGProcesses() { - log "Exiting With SIGINT ..." - echo quit >> logs/logbot.stdin - log "Cleaning BG Processes ..." - sleep 3 + exit 143 } runPythonCode() { diff --git a/userge/plugins/misc/upload.py b/userge/plugins/misc/upload.py index f784be4b4..5f73a7154 100644 --- a/userge/plugins/misc/upload.py +++ b/userge/plugins/misc/upload.py @@ -152,7 +152,7 @@ async def uploadtotg(message: Message): count = 0 await message.try_to_edit(progress_str, disable_web_page_preview=True) await asyncio.sleep(1) - except Exception as d_e: + except Exception as d_e: # pylint: disable=broad-except await message.err(d_e) return if "|" in path_: @@ -193,25 +193,14 @@ def explorer(path: Path) -> None: async def upload(message: Message, path: Path, del_path: bool = False, extra: str = ''): - if path.name.lower().endswith(( - ".mkv", - ".mp4", - ".webm" - )) and ('d' not in message.flags): + if path.name.lower().endswith( + (".mkv", ".mp4", ".webm")) and ('d' not in message.flags): await vid_upload(message, path, del_path, extra) - elif path.name.lower().endswith(( - ".mp3", - ".flac", - ".wav", - ".m4a" - )) and ('d' not in message.flags): + elif path.name.lower().endswith( + (".mp3", ".flac", ".wav", ".m4a")) and ('d' not in message.flags): await audio_upload(message, path, del_path, extra) - elif path.name.lower().endswith(( - ".jpg", - ".jpeg", - ".png", - ".bmp" - )) and ('d' not in message.flags): + elif path.name.lower().endswith( + (".jpg", ".jpeg", ".png", ".bmp")) and ('d' not in message.flags): await photo_upload(message, path, del_path, extra) else: await doc_upload(message, path, del_path, extra) diff --git a/userge/plugins/tools/executor.py b/userge/plugins/tools/executor.py index 2bdb68c7d..614f9a1e3 100644 --- a/userge/plugins/tools/executor.py +++ b/userge/plugins/tools/executor.py @@ -1,4 +1,4 @@ -""" run shell or python command """ +""" run shell or python command(s) """ # Copyright (C) 2020 by UsergeTeam@Github, < https://github.com/UsergeTeam >. # @@ -17,65 +17,97 @@ from pyrogram.errors.exceptions.bad_request_400 import MessageNotModified -from userge import userge, Message +from userge import userge, Message, Config from userge.utils import runcmd @userge.on_cmd("eval", about={ 'header': "run python code line | lines", - 'usage': "{tr}eval [code lines]", - 'examples': "{tr}eval print('Userge')"}, allow_channels=False) + 'flags': { + '-d': "debug mode (increase sensitivity)", + '-s': "silent mode (hide STDIN)"}, + 'usage': "{tr}eval [flag(s)] [code lines]", + 'examples': [ + "{tr}eval print('Userge')", "{tr}eval -s print('Userge')", + "{tr}eval -d 5 + 6", "{tr}eval -s -d 5 + 6"]}, allow_channels=False) async def eval_(message: Message): """ run python code """ cmd = await init_func(message) if cmd is None: return + flags = [] + for flag in ('-s', '-d', '-s'): + if cmd.startswith(flag): + flags.append(flag) + cmd = cmd[2:].strip() + if not cmd: + await message.err("Unable to Parse Input!") + return + silent_mode, debug_mode, mode = False, False, "" + if '-s' in flags: + silent_mode = True + mode += " " + if '-d' in flags: + debug_mode = True + mode += " " + await message.edit(f"`Executing eval in {mode or ' '}mode ...`", parse_mode='md') old_stderr = sys.stderr old_stdout = sys.stdout redirected_output = sys.stdout = io.StringIO() redirected_error = sys.stderr = io.StringIO() - stdout, stderr, exc = None, None, None + ret_val, stdout, stderr, exc = None, None, None, None async def aexec(code): - exec("async def __aexec(userge, message):\n " # nosec pylint: disable=W0122 - + '\n '.join(line for line in code.split('\n'))) + head = "async def __aexec(userge, message):\n " + if '\n' in code: + lines = code.split('\n') + body = '\n '.join(line for line in lines[:-1]) + tail = lines[-1] + else: + body = "" + tail = code + tail = f"\n {tail}" if "return " in tail else f"\n return {tail}" + exec(head + body + tail) # nosec pylint: disable=W0122 return await locals()['__aexec'](userge, message) try: - await aexec(cmd) - except Exception: - exc = traceback.format_exc() - stdout = redirected_output.getvalue() - stderr = redirected_error.getvalue() + ret_val = await aexec(cmd) + except Exception: # pylint: disable=broad-except + exc = traceback.format_exc().strip() + stdout = redirected_output.getvalue().strip() + stderr = redirected_error.getvalue().strip() sys.stdout = old_stdout sys.stderr = old_stderr - if exc: - evaluation = exc - elif stderr: - evaluation = stderr - elif stdout: - evaluation = stdout + evaluation = exc or stderr or stdout + output = "" + if debug_mode: + evaluation = ret_val or evaluation + if not silent_mode: + output += f"**>>>** ```{cmd}```\n\n" + if evaluation: + output += f"**>>>** ```{evaluation}```" + await asyncio.sleep(1) + if output: + await message.edit_or_send_as_file(text=output, + parse_mode='md', + filename="eval.txt", + caption=cmd) else: - evaluation = "Success" - output = "**EVAL**:\n```{}```\n\n\ -**OUTPUT**:\n```{}```".format(cmd, evaluation.strip()) - await message.edit_or_send_as_file(text=output, - parse_mode='md', - filename="eval.txt", - caption=cmd) + await message.delete() @userge.on_cmd("exec", about={ - 'header': "run shell commands", + 'header': "rrun commands in exec", 'usage': "{tr}exec [commands]", 'examples': "{tr}exec echo \"Userge\""}, allow_channels=False) async def exec_(message: Message): - """ run shell command """ + """ run commands in exec """ cmd = await init_func(message) if cmd is None: return + await message.edit("`Executing exec ...`") try: out, err, ret, pid = await runcmd(cmd) - except Exception as t_e: + except Exception as t_e: # pylint: disable=broad-except await message.err(t_e) return out = out or "no output" @@ -91,14 +123,15 @@ async def exec_(message: Message): @userge.on_cmd("term", about={ - 'header': "run terminal commands", + 'header': "run commands in shell (terminl)", 'usage': "{tr}term [commands]", 'examples': "{tr}term echo \"Userge\""}, allow_channels=False) async def term_(message: Message): - """ run shell command (live update) """ + """ run commands in shell (terminl with live update) """ cmd = await init_func(message) if cmd is None: return + await message.edit("`Executing terminal ...`") try: t_obj = await Term.execute(cmd) # type: Term except Exception as t_e: @@ -121,7 +154,7 @@ async def term_(message: Message): await message.reply("`process canceled!`") return await asyncio.sleep(0.5) - if count >= 10: + if count >= Config.EDIT_SLEEP_TIMEOUT * 2: count = 0 out_data = f"
{output}{t_obj.read_line}
" await message.try_to_edit(out_data, parse_mode='html') @@ -134,7 +167,6 @@ async def term_(message: Message): async def init_func(message: Message): - await message.edit("`Processing ...`") cmd = message.input_str if not cmd: await message.err("No Command Found!") diff --git a/userge/plugins/tools/updater.py b/userge/plugins/tools/updater.py index 0ac41b7da..f48842c6d 100644 --- a/userge/plugins/tools/updater.py +++ b/userge/plugins/tools/updater.py @@ -7,11 +7,12 @@ # All rights reserved. import asyncio +from time import time -from git import Repo +from git import Repo, Remote from git.exc import GitCommandError -from userge import userge, Message, Config +from userge import userge, Message, Config, pool LOG = userge.getLogger(__name__) CHANNEL = userge.getCLogger(__name__) @@ -85,7 +86,7 @@ async def check_update(message: Message): if not Config.HEROKU_GIT_URL: await message.err("please set heroku things...") return - await message.edit( + sent = await message.edit( f'`Now pushing updates from [{branch}] to heroku...\n' 'this will take upto 5 min`\n\n' f'* **Restart** after 5 min using `{Config.CMD_TRIGGER}restart -h`\n\n' @@ -95,5 +96,36 @@ async def check_update(message: Message): remote.set_url(Config.HEROKU_GIT_URL) else: remote = repo.create_remote("heroku", Config.HEROKU_GIT_URL) - remote.push(refspec=f'{branch}:master', force=True) - await message.edit(f"**HEROKU APP : {Config.HEROKU_APP.name} is up-to-date with [{branch}]**") + await _push_to_heroku(sent, remote, branch) + await sent.edit(f"**HEROKU APP : {Config.HEROKU_APP.name} is up-to-date with [{branch}]**") + + +@pool.run_in_thread +def _push_to_heroku(sent: Message, remote: Remote, branch: str) -> None: + start_time = time() + + def progress(op_code, cur_count, max_count=100, message=''): + nonlocal start_time + cur_prog = round(cur_count * 100 / max_count, 2) + prog = f"**code** : `{op_code}` **prog** : `{cur_prog}`" + if message: + prog += f" || `{message}`" + LOG.debug(prog) + now = time() + if (now - start_time) > 3 or message: + start_time = now + try: + run(sent.try_to_edit(f"{cur_msg}\n\n{prog}")) + except TypeError: + pass + cur_msg = sent.text.html + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + run = loop.run_until_complete + try: + remote.push(refspec=f'{branch}:master', progress=progress, force=True) + except GitCommandError as g_e: + LOG.exception(g_e) + run(sent.err(f"{g_e}, {Config.CMD_TRIGGER}restart -h and try again!")) + finally: + loop.close() diff --git a/userge/plugins/utils/ud.py b/userge/plugins/utils/ud.py index c65fce490..31ef66eb2 100644 --- a/userge/plugins/utils/ud.py +++ b/userge/plugins/utils/ud.py @@ -15,11 +15,12 @@ @userge.on_cmd("ud", about={ 'header': "Searches Urban Dictionary for the query", - 'usage': "{tr}ud [query]", - 'examples': "{tr}ud userge"}) + 'flags': {'-l': "limit : defaults to 1"}, + 'usage': "{tr}ud [flag] [query]", + 'examples': ["{tr}ud userge", "{tr}ud -l3 userge"]}) async def urban_dict(message: Message): await message.edit("Processing...") - query = message.input_str + query = message.filtered_input_str if not query: await message.err(text="No found any query!") return @@ -29,11 +30,14 @@ async def urban_dict(message: Message): await message.err(text=f"Sorry, couldn't find any results for: `{query}``") return output = '' + limit = int(message.flags.get('-l', 1)) for i, mean_ in enumerate(mean, start=1): output += f"{i}. **{mean_['def']}**\n" + \ f" Examples:\n * `{mean_['example'] or 'not found'}`\n\n" + if limit <= i: + break if not output: await message.err(text=f"No result found for **{query}**") return - output = f"**Query:** `{query}`\n\n{output}" + output = f"**Query:** `{query}`\n**Limit:** `{limit}`\n\n{output}" await message.edit_or_send_as_file(text=output, caption=query)