async def demote(event: NewMessage.Event) -> None: """Demote a user in a group or channel.""" if not event.is_private and not await get_rights(event, ban_users=True): await event.answer("`You do not have rights to remove admins in here!`" ) return elif event.is_private: await event.answer("`You can't demote users in private chats.`") return user, reason, exception = await get_entity_from_msg(event) if user: if exception: await event.answer(f"`Demote machine broke!\n{user}`") return else: await event.answer("`At least specifiy a user, maybe?`") return entity = await event.get_chat() try: await client.edit_admin(entity=entity, user=user, is_admin=False) text = "`Successfully demoted `{}` (``{}``)!`" if reason: text += f"\n`Reason:` `{reason}`" e1 = await get_chat_link(user) e2 = await get_chat_link(entity, event.id) log_msg = f"Successfully demoted {e1} in {e2}" if reason: log_msg += f"\nReason: {reason}" await event.answer(text.format(e1, user.id), log=("demote", log_msg)) except Exception as e: await event.answer(f"`{e}`") LOGGER.exception(e)
async def unban(event): if ((event.is_channel or event.is_group) and not (event.chat.creator or event.chat.admin_rights.ban_users)): await event.edit("`You do not have rights to un-ban users in here!`") return user, reason, exception = await get_entity_from_msg(event) if user: if exception: await event.edit(f"`Un-ban machine broke!\n{user}`") return try: await client.edit_permissions(entity=await event.get_input_chat(), user=user, view_messages=True, send_messages=True, send_media=True, send_stickers=True, send_gifs=True, send_games=True, send_inline=True, send_polls=True) text = "`Successfully un-banned ``{}`` (``{}``)!`" if reason: text += f"\n`Reason:` `{reason}`" await event.edit(text.format(get_display_name(user), user.id)) except Exception as e: await event.edit(f"`{e}`") LOGGER.exception(e)
async def update_requirements(): reqs = os.path.join(basedir, "requirements.txt") try: await create_subprocess_shell(' '.join(sys.executable, "-m", "pip", "install", "-r", str(reqs))) except Exception as e: LOGGER.exception(e)
async def ban(event): if ((event.is_channel or event.is_group) and not (event.chat.creator or event.chat.admin_rights.ban_users)): await event.edit("`You do not have rights to ban users in here!`") return user, reason, exception = await get_entity_from_msg(event) if user: if exception: await event.edit(f"`Ban machine broke!\n{user}`") return try: await client.edit_permissions(entity=await event.get_input_chat(), user=user, view_messages=False) text = "`Successfully banned ``{}`` (``{}``)!`" if reason: text += f"\n`Reason:` `{reason}`" await event.edit(text.format(get_display_name(user), user.id)) except Exception as e: await event.edit("`An exception occured trying to ban. " " Make sure you have the correct rights! " "Check the logs for more information.`") LOGGER.exception(e)
async def promote(event): if ((event.is_channel or event.is_group) and not (event.chat.creator or event.chat.admin_rights.add_admins)): await event.edit("`You do not have rights to add admins in here!`") return user, extra, exception = await get_entity_from_msg(event) if user: if exception: await event.edit(f"`Promote machine broke!\n{user}`") return try: await client.edit_admin( entity=await event.get_input_chat(), post_messages=True if event.is_channel else False, edit_messages=True if event.is_channel else False, user=user, is_admin=True, title=extra) text = "`Successfully promoted ``{}`` (``{}``)!`" if extra: text += f"\n`Title:` `{extra}`" await event.edit(text.format(get_display_name(user), user.id)) except Exception as e: await event.edit("`An exception occured trying to promote. " " Make sure you have the correct rights! " "Check the logs for more information.`") LOGGER.exception(e)
async def bio_filter(event: ChatAction.Event) -> None: """Filter incoming messages for blacklisting.""" text = None broadcast = getattr(event.chat, 'broadcast', False) if not redis or event.is_private or broadcast: return if event.user_added or event.user_joined: try: sender = await event.get_input_user() chat = await event.get_chat() sender_id = await client.get_peer_id(sender) chat_id = await client.get_peer_id(chat) localbl = localBlacklists.get(chat_id, False) except (ValueError, TypeError): return if chat_id in whitelistedChats or sender_id in whitelistedUsers: return if await is_admin(chat_id, sender_id): return user = await client(functions.users.GetFullUserRequest(id=sender)) if GlobalBlacklist.bio: for value in GlobalBlacklist.bio: bio = await escape_string(value) if re.search(bio, user.about, flags=re.I): text = ("**Banned due to globally blacklisted bio match: " f"{value}**") elif localbl and getattr(localbl, 'bio', False): for value in localBlacklists[chat_id].bio: bio = await escape_string(value) if re.search(bio, user.about, flags=re.I): text = f"**Banned due to blacklisted bio match: {value}**" if text: ban_right = getattr(chat.admin_rights, 'ban_users', False) if ban_right or chat.creator: pass else: return try: await client.edit_permissions(entity=chat, user=sender_id, view_messages=False) await event.reply(text) if client.logger: logger_group = client.config['userbot'].getint( 'logger_group_id', 'me') log_text = ("**USERBOT LOG** #blacklist\n" f'Banned {sender_id} from {chat_id}.\n{text}.') await client.send_message(logger_group, log_text) except Exception as e: await event.reply(f"**Couldn't ban user due to {e}**") LOGGER.exception(e)
async def tban(event: NewMessage.Event) -> None: """Temporary ban a user in a group or channel.""" if not event.is_private and not await get_rights(event, ban_users=True): await event.answer("`You do not have rights to t-ban users in here!`") return elif event.is_private: await event.answer("`You can't t-ban users in private chats.`") return user, extra, exception = await get_entity_from_msg(event) if user: if exception: await event.answer(f"`T-ban machine broke!\n{user}`") return else: await event.answer("`At least specifiy a user, maybe?`") return entity = await event.get_chat() try: time = None reason = None seconds = None text = "`Successfully t-banned `{}` (``{}``)!`" e1 = await get_chat_link(user) e2 = await get_chat_link(entity, event.id) log_msg = f"Successfully t-banned {e1} in {e2}" if extra: reason, seconds = await split_extra_string(extra) if reason: text += f"\n`Reason:` `{reason}`" log_msg += f"\nReason: {reason}" if seconds: time = timedelta(seconds=seconds) text += f"\n`Time:` `{await _humanfriendly_seconds(seconds)}`" log_msg += f"Time: {await _humanfriendly_seconds(seconds)}" if not seconds: await event.answer("`Provide the total time limit for t-ban!`") return await client.edit_permissions( entity=entity, user=user, until_date=time, view_messages=False ) await event.answer( text.format(e1, user.id), log=("tban", log_msg) ) except Exception as e: await event.answer(f"`{e}`") LOGGER.exception(e)
async def update_requirements(): try: process = await asyncio.create_subprocess_shell( f'{sys.executable} -m pip install --user -r requirements.txt', stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) await process.communicate() return process.returncode except Exception as e: LOGGER.exception(e) return await client.get_traceback(e)
async def update_requirements(): reqs = str(requirements_path) try: process = await asyncio.create_subprocess_shell( ' '.join([sys.executable, "-m", "pip", "install", "-r", reqs]), stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) await process.communicate() return process.returncode except Exception as e: LOGGER.exception(e) return repr(e)
async def update_requirements(): args = ['-m', 'pip', 'install', '--user', '-r', 'requirements.txt'] try: process = await asyncio.create_subprocess_exec( sys.executable.replace(' ', '\\ '), *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) await process.communicate() return process.returncode except Exception as e: LOGGER.exception(e) return await client.get_traceback(e)
async def update_requirements(): reqs = ' '.join( [sys.executable, "-m", "pip", "install", "-r", 'requirements.txt']) try: process = await asyncio.create_subprocess_shell( reqs, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) await process.communicate() return process.returncode except Exception as e: LOGGER.exception(e) return await client.get_traceback(e)
async def update_requirements(): args = ["-m", "pip", "install", "--user", "-r", "requirements.txt"] try: process = await asyncio.create_subprocess_exec( sys.executable.replace(" ", "\\ "), *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) await process.communicate() return process.returncode except Exception as e: LOGGER.exception(e) return await client.get_traceback(e)
async def unban(event: NewMessage.Event) -> None: """Un-ban a user in a group or channel.""" if not event.is_private and not await get_rights(event, ban_users=True): await event.answer("`You do not have rights to un-ban users in here!`") return elif event.is_private: await event.answer("`You can't un-ban users in private chats.`") return user, reason, exception = await get_entity_from_msg(event) if user: if exception: await event.answer(f"`Un-ban machine broke!\n{user}`") return else: await event.answer("`At least specifiy a user, maybe?`") return entity = await event.get_chat() try: await client.edit_permissions( entity=entity, user=user, view_messages=True, send_messages=True, send_media=True, send_stickers=True, send_gifs=True, send_games=True, send_inline=True, send_polls=True ) text = "`Successfully un-banned `{}` (``{}``)!`" if reason: text += f"\n`Reason:` `{reason}`" e1 = await get_chat_link(user) e2 = await get_chat_link(entity, event.id) log_msg = f"Successfully unbanned {e1} in {e2}" if reason: log_msg += f"\nReason: {reason}" await event.answer( text.format(e1, user.id), log=("unban", log_msg) ) except Exception as e: await event.answer(f"`{e}`") LOGGER.exception(e)
async def ban_user(event: NewMessage.Event or ChatAction.Event, text: str, bl_type: str = None, match: Union[str, int] = None, globally: bool = False) -> bool: if isinstance(event, NewMessage.Event): sender = await event.get_input_sender() else: sender = await event.get_input_user() temp_banlist.append(sender) chat = await event.get_chat() ban_right = getattr(chat.admin_rights, 'ban_users', False) delete_messages = getattr(chat.admin_rights, 'delete_messages', False) if not (ban_right or chat.creator): return False user_href = "[{0}](tg://user?id={0})".format(sender.user_id) try: await client.edit_permissions(entity=chat.id, user=sender, view_messages=False) if delete_messages: await event.delete() text = text.format(user_href, ' globally ' if globally else ' ') await event.respond(text) if client.logger: logger_group = client.config['userbot'].getint( 'logger_group_id', 'me') if chat.username: chat_href = (f"[{chat.title}]" f"(tg://resolve?domain={chat.username})") else: chat_href = f"[{chat.title}] `{chat.id}`" log_text = ("**USERBOT LOG** #blacklist\n" f"Banned {user_href} from {chat_href}.\n") if bl_type and match: log_text += f"Blacklist type: `{bl_type}`.\nMatch: `{match}`" await client.send_message(logger_group, log_text) if bl_type and match and sender.user_id not in blacklistedUsers: blacklistedUsers.update({sender.user_id: (bl_type, match)}) redis.set('blacklist:users', dill.dumps(blacklistedUsers)) return True except Exception as e: exc = await client.get_traceback(e) await event.respond(f"**Couldn't ban user. Exception:\n**```{exc}```") LOGGER.exception(e) return False finally: temp_banlist.remove(sender)
async def ban_user(event: NewMessage.Event, text: str) -> bool: chat = await event.get_chat() ban_right = getattr(chat.admin_rights, 'ban_user', False) if not (chat.creator or ban_right): return False try: await client.edit_permissions(entity=event.chat_id, user=event.from_id, view_messages=False) await event.answer( text, log=('blacklist', f'Banned {event.from_id} from {event.chat_id}.\n{text}.')) return True except Exception as e: await event.answer(f"**Couldn't ban user due to {e}**", reply=True) LOGGER.exception(e) return False
async def sed(e): sed_result = separate_sed(e.text) L = await e.get_reply_message() if sed_result: if L: to_fix = L.text else: await e.edit( "`Master, I don't have brains. Well you too don't I guess.`" ) return repl, repl_with, flags = sed_result if not repl: await e.edit( "`Master, I don't have brains. Well you too don't I guess.`" ) return try: check = re.match(repl, to_fix, flags=re.IGNORECASE) if check and check.group(0).lower() == to_fix.lower(): await e.edit( "`Boi!, that's a reply. Don't use sed`" ) return if "i" in flags and "g" in flags: text = re.sub(repl, repl_with, to_fix, flags=re.I).strip() elif "i" in flags: text = re.sub(repl, repl_with, to_fix, count=1, flags=re.I).strip() elif "g" in flags: text = re.sub(repl, repl_with, to_fix).strip() else: text = re.sub(repl, repl_with, to_fix, count=1).strip() except sre_constants.error: LOGGER.warning(e.text) LOGGER.exception("SRE constant error") await e.edit("B O I! [Learn Regex](https://regexone.com)") return if text: await e.edit("Did you mean? \n\n`" + text + "`")
async def promote(event: NewMessage.Event) -> None: """Promote a user in a group or channel.""" if not event.is_private and not await get_rights(event, add_admins=True): await event.answer("`You do not have rights to add admins in here!`") return elif event.is_private: await event.answer("`You can't promote users in private chats.`") return user, extra, exception = await get_entity_from_msg(event) if user: if exception: await event.answer(f"`Promote machine broke!\n{user}`") return else: await event.answer("`At least specifiy a user, maybe?`") return entity = await event.get_chat() try: await client.edit_admin( entity=entity, user=user, is_admin=True, title=extra ) text = "`Successfully promoted `{}` (``{}``)!`" if extra: text += f"\n`Title:` `{extra}`" e1 = await get_chat_link(user) e2 = await get_chat_link(entity, event.id) log_msg = f"Successfully promoted {e1} in {e2}" if extra: log_msg += f"\nTitle: {extra}" await event.answer( text.format(e1, user.id), log=("promote", log_msg) ) except Exception as e: await event.answer(f"`{e}`") LOGGER.exception(e)
async def tmute(event): if ((event.is_channel or event.is_group) and not (event.chat.creator or event.chat.ban_users)): await event.edit("`You do not have rights to mute users in here!`") return user, extra, exception = await get_entity_from_msg(event) if user: if exception: await event.edit(f"`T-mute machine broke!\n{user}`") return try: time = None reason = None seconds = None text = "`Successfully t-muted ``{}`` (``{}``)!`" if extra: reason, seconds = await split_extra_string(extra) if reason: text += f"\n`Reason:` `{reason}`" if seconds: time = timedelta(seconds=seconds) text += f"\n`Time:` `{time}`" if not seconds: await event.edit("`Provide the total time limit for t-mute!`") return await client.edit_permissions(entity=await event.get_input_chat(), user=user, until_date=time, send_messages=False) await event.edit(text.format(get_display_name(user), user.id)) except Exception as e: await event.edit("`An exception occured trying to t-mute. " " Make sure you have the correct rights! " "Check the logs for more information.`") LOGGER.exception(e)
async def kick(event): if ((event.is_channel or event.is_group) and not (event.chat.creator or event.chat.admin_rights.ban_users)): await event.edit("`You do not have rights to kick users in here!`") return user, reason, exception = await get_entity_from_msg(event) if user: if exception: await event.edit(f"`Kick machine broke!\n{user}`") return try: await client.kick_participant(entity=await event.get_input_chat(), user=user) text = "`Successfully kicked ``{}`` (``{}``)!`" if reason: text += f"\n`Reason:` `{reason}`" await event.edit(text.format(get_display_name(user), user.id)) except Exception as e: await event.edit(f"`{e}`") LOGGER.exception(e)
async def mute(event): if ((event.is_channel or event.is_group) and not (event.chat.creator or event.chat.ban_users)): await event.edit("`You do not have rights to mute users in here!`") return user, reason, exception = await get_entity_from_msg(event) if user: if exception: await event.edit(f"`Mute machine broke!\n{user}`") return try: await client.edit_permissions(entity=await event.get_input_chat(), user=user, send_messages=False) text = "`Successfully muted ``{}`` (``{}``)!`" if reason: text += f"\n`Reason:` `{reason}`" await event.edit(text.format(get_display_name(user), user.id)) except Exception as e: await event.edit(f"`{e}`") LOGGER.exception(e)
async def ban_user(event: NewMessage.Event or ChatAction.Event, text: str, bl_type: str = None, match: Union[str, int] = None) -> bool: if isinstance(event, NewMessage.Event): sender = await event.get_input_sender() else: sender = await event.get_input_user() temp_banlist.append(sender) chat = await event.get_chat() ban_right = getattr(chat.admin_rights, 'ban_users', False) delete_messages = getattr(chat.admin_rights, 'delete_messages', False) if not (ban_right or chat.creator): return False try: await client.edit_permissions(entity=chat.id, user=sender, view_messages=False) if delete_messages: await event.delete() await event.respond(text) if client.logger: logger_group = client.config['userbot'].getint( 'logger_group_id', 'me') log_text = ("**USERBOT LOG** #blacklist\n" f"Banned {sender.user_id} from {chat.id}.\n{text}.") await client.send_message(logger_group, log_text) if bl_type and match: blacklistedUsers.update({sender.user_id: (bl_type, match)}) redis.set('blacklist:users', dill.dumps(blacklistedUsers)) return True except Exception as e: await event.respond(f"**Couldn't ban user due to {e}**") LOGGER.exception(e) return False finally: temp_banlist.remove(sender)
async def promote(event): if ((event.is_channel or event.is_group) and not (event.chat.creator or event.chat.admin_rights.add_admins)): await event.edit("`You do not have rights to add admins in here!`") return user, extra, exception = await get_entity_from_msg(event) if user: if exception: await event.edit(f"`Promote machine broke!\n{user}`") return try: await client.edit_admin(entity=await event.get_input_chat(), user=user, is_admin=True, title=extra) text = "`Successfully promoted ``{}`` (``{}``)!`" if extra: text += f"\n`Title:` `{extra}`" await event.edit(text.format(get_display_name(user), user.id)) except Exception as e: await event.edit(f"`{e}`") LOGGER.exception(e)
async def updater(event: NewMessage.Event) -> None: """Pull newest changes from the official repo and update the script/app.""" arg = event.matches[0].group(1) await event.answer("`Checking for updates!`") try: repo = git.Repo(basedir) fetched_items = repo.remotes.origin.fetch() except git.exc.NoSuchPathError as path: await event.answer(f"`Couldn't find {path}!`") repo.__del__() return except git.exc.GitCommandError as command: await event.answer( f"`An error occured trying to get the Git Repo.`\n`{command}`") repo.__del__() return except git.exc.InvalidGitRepositoryError: repo = git.Repo.init(basedir) origin = repo.create_remote('origin', main_repo) if not origin.exists(): await event.answer( "`The main repository does not exist. Remote is invalid!`") repo.__del__() return fetched_items = origin.fetch() repo.create_head('master', origin.refs.master).set_tracking_branch( origin.refs.master).checkout() fetched_commits = repo.iter_commits(f"HEAD..{fetched_items[0].ref.name}") untracked_files = repo.untracked_files old_commit = repo.head.commit for diff_added in old_commit.diff('FETCH_HEAD').iter_change_type('M'): if "requirements.txt" in diff_added.b_path: await event.answer("`Updating the pip requirements!`") updated = await update_requirements() if updated == 0: await event.answer("`Successfully updated the requirements.`") else: if isinstance(updated, int): await event.answer( "`Failed trying to install requirements." " Install them manually and run the command again.`") else: await event.answer(f'```{updated}```') return break if arg == "add": repo.index.add(untracked_files, force=True) repo.index.commit("[PaperplaneRemix] Updater: Untracked files") elif arg == "reset": repo.head.reset('--hard') try: repo.remotes.origin.pull() except git.exc.GitCommandError as command: text = ("`An error occured trying to Git pull:`\n`{0}`\n\n" "`You may use` **{1}update reset** `or` **{1}update add** " "`to reset your repo or add and commit your changes as well.`") prefix = client.prefix if client.prefix is not None else '.' await event.answer(text.format(command, prefix)) repo.__del__() return new_commit = repo.head.commit if old_commit == new_commit: await event.answer("`Already up-to-date!`") repo.__del__() return remote_url = repo.remote().url.replace(".git", '/') if remote_url[-1] != '/': remote_url = remote_url + '/' now = datetime.datetime.now(datetime.timezone.utc) def_changelog = changelog = "**PaperplaneRemix changelog:**" for commit in fetched_commits: changelog += summary.format(rev=repo.git.rev_parse(commit.hexsha, short=7), summary=commit.summary, url=remote_url, sha=commit.hexsha) ago = (now - commit.committed_datetime).total_seconds() elspased = (await _humanfriendly_seconds(ago)).split(',')[0] committers_link = author_link.format(author=commit.committer, url=remote_url) authors_link = author_link.format(author=commit.author, url=remote_url) if commit.author == commit.committer: committed = commited.format(committer=committers_link, elapsed=elspased) else: committed = authored.format(author=authors_link, committer=committers_link, elapsed=elspased) changelog += f"{committed:>{len(committed) + 8}}" if changelog == def_changelog: changelog = "`No changelog for you! IDK what happened.`" toast = await event.answer( "`Successfully pulled the new commits. Updating the bot!`", log=("update", changelog.strip())) if not client.logger: await event.answer(changelog.strip(), reply_to=toast.id, link_preview=False) os.environ['userbot_update'] = "True" heroku_api_key = client.config['api_keys'].get('api_key_heroku', False) if os.getenv("DYNO", False) and heroku_api_key: heroku_conn = heroku3.from_key(heroku_api_key) app = None for heroku_app in heroku_conn.apps(): if "api_key_heroku" in heroku_app.config(): app = heroku_app break if app is None: await event.answer( "`You seem to be running on Heroku " "with an invalid environment. Couldn't update the app.`\n" "`The changes will be reverted upon dyno restart.`") await asyncio.sleep(2) repo.__del__() await restart(event) else: for build in app.builds(): if build.status == "pending": await event.answer( "`There seems to be an ongoing build in your app.`" " `Try again after it's finished.`") return # Don't update the telethon environment varaibles userbot_config = client.config['userbot'] app.config().update(dict(userbot_config)) app.config().update({ "userbot_restarted": f"{event.chat_id}/{event.message.id}", "userbot_update": "True" }) if event.client.disabled_commands: disabled_list = ", ".join(client.disabled_commands.keys()) app.config().update( {"userbot_disabled_commands": disabled_list}) url = f"https://*****:*****@git.heroku.com/{app.name}.git" if "heroku" in repo.remotes: repo.remotes['heroku'].set_url(url) else: repo.create_remote('heroku', url) if repo.untracked_files: repo.index.add(untracked_files, force=True) repo.index.commit("[PaperplaneRemix] Updater: Untracked files") app.enable_feature('runtime-dyno-metadata') await event.answer( "`Pushing all the changes to Heroku. Might take a while.`") remote = repo.remotes['heroku'] try: remote.push(refspec=f'{repo.active_branch.name}:master', force=True) await event.answer("`There was nothing to push to Heroku?`") except git.exc.GitCommandError as command: await event.answer( "`An error occured trying to pull and push to Heorku`" f"\n`{command}`") LOGGER.exception(command) repo.__del__() else: repo.__del__() await restart(event)
async def update(event): arg = event.matches[0].group(1) main_repo = "https://github.com/kandnub/TG-UserBot.git" try: repo = git.Repo(basedir) except git.exc.NoSuchPathError as path: await event.edit(f"`Couldn't find {path}!`") return except git.exc.GitCommandError as command: await event.edit( f"`An error occured trying to get the Git Repo.`\n`{command}`") return except git.exc.InvalidGitRepositoryError: repo = git.Repo.init(basedir) origin = repo.create_remote('origin', main_repo) if not origin.exists(): await event.edit( "`The main repository does not exist. Remote is invalid!`") return origin.fetch() repo.create_head('master', origin.refs.master).set_tracking_branch( origin.refs.master).checkout() await event.edit("`Checking for updates!`") untracked_files = repo.untracked_files old_commit = repo.head.commit if arg == "add": repo.index.add(untracked_files, force=True) repo.index.commit("[TG-UserBot] Updater: Untracked files") elif arg == "reset": repo.head.reset('--hard') try: pull = repo.remotes.origin.pull() except git.exc.GitCommandError as command: text = ("`An error occured trying to Git pull:`\n`{0}`\n\n" "`You may use` **{1}update reset** `or` **{1}update add** " "`to reset your repo or add and commit your changes as well.`") prefix = client.prefix if client.prefix is not None else '.' await event.edit(text.format(command, prefix)) return new_commit = repo.head.commit if old_commit == new_commit: await event.edit("`Already up-to-date!`") return heroku_api_key = client.config['userbot'].get('api_key_heroku', False) if os.getenv("DYNO", False) and heroku_api_key: heroku_conn = heroku3.from_key(heroku_api_key) heroku_app = None for app in heroku_conn.apps(): if app.name == os.getenv('HEROKU_APP_NAME', ''): heroku_app = app break if heroku_app is None: await event.edit( "`You seem to be running on Heroku " "with an invalid environment. Couldn't update the app.`\n" "`The changes will be reverted upon dyno restart.`") await sleep(2) await updated_pip_modules(event, pull, repo, new_commit) await restart(event) else: # Don't update the telethon environment varaibles userbot_config = client.config['userbot'] app.config().update(dict(userbot_config)) app.config().update( {'userbot_restarted': f"{event.chat_id}/{event.message.id}"}) url = f"https://*****:*****@git.heroku.com/{app.name}.git" if "heroku" in repo.remotes: repo.remotes['heroku'].set_url(url) else: repo.create_remote('heroku', url) if repo.untracked_files: repo.index.add(untracked_files, force=True) repo.index.commit("[TG-UserBot] Updater: Untracked files") app.enable_feature('runtime-dyno-metadata') await event.edit("`Pushing all the changes to the Heroku.`") remote = repo.remotes['heroku'] try: remote.push(refspec=f'{str(repo.active_branch)}:master', force=True) await event.edit("`There was nothing to push to Heroku?`") except git.exc.GitCommandError as command: await event.edit( "`An error occured trying to pull and push to Heorku`" f"\n`{command}`") LOGGER.exception(command) else: await updated_pip_modules(event, pull, repo, new_commit) await restart(event)
async def wrapper(check): if check.edit_date and check.is_channel and not check.is_group: # Messages sent in channels can be edited by other users. # Ignore edits that take place in channels. return if group_only and not check.is_group: await check.respond("`Are you sure this is a group?`") return if check.via_bot_id and not insecure and check.out: # Ignore outgoing messages via inline bots for security reasons return if pattern.startswith( "^.") and not check.message.message.startswith("."): return try: await func(check) # # HACK HACK HACK # Raise StopPropagation to Raise StopPropagation # This needed for AFK to working properly # TODO # Rewrite events to not passing all exceptions # except events.StopPropagation: raise events.StopPropagation # This is a gay exception and must be passed out. So that it doesnt spam chats except KeyboardInterrupt: pass except BaseException as e: LOGGER.exception(e) # Log the error in console # Check if we have to disable error logging message. if not disable_errors: date = strftime("%Y-%m-%d %H:%M:%S", gmtime()) text = "**Sorry, I encountered a error!**\n" link = "[https://t.me/tgpaperplane](Userbot Support Chat)" text += "If you wanna you can report it" text += f"- just forward this message to {link}.\n" text += "I won't log anything except the fact of error and date\n" ftext = "\nDisclaimer:\nThis file uploaded ONLY here, " ftext += "we logged only fact of error and date, " ftext += "we respect your privacy, " ftext += "you may not report this error if you've " ftext += "any confidential data here, no one will see your data " ftext += "if you choose not to do so.\n\n" ftext += "--------BEGIN USERBOT TRACEBACK LOG--------" ftext += "\nDate: " + date ftext += "\nGroup ID: " + str(check.chat_id) ftext += "\nSender ID: " + str(check.sender_id) ftext += "\n\nEvent Trigger:\n" ftext += str(check.text) ftext += "\n\nTraceback info:\n" ftext += str(format_exc()) ftext += "\n\nError text:\n" ftext += str(sys.exc_info()[1]) ftext += "\n\n--------END USERBOT TRACEBACK LOG--------" #command = "git log --pretty=format:\"%an: %s\" -5" #ftext += "\n\n\nLast 5 commits:\n" #process = await asyncsubshell(command, # stdout=asyncsub.PIPE, # stderr=asyncsub.PIPE) #stdout, stderr = await process.communicate() #result = str(stdout.decode().strip()) \ # + str(stderr.decode().strip()) #ftext += result file = open("error.log", "w+") file.write(ftext) file.close() remove("error.log") else: pass
async def updater(event: NewMessage.Event) -> None: """ Pull newest changes from the official repo and update the script/app. `{prefix}update` or `{prefix}update reset` or `{prefix}update add` Reset will reset the repository and add will commit your changes. """ arg = event.matches[0].group(1) await event.answer("`Checking for updates!`") try: repo = git.Repo(basedir) fetched_items = repo.remotes.origin.fetch() except git.exc.NoSuchPathError as path: await event.answer(f"`Couldn't find {path}!`") repo.__del__() return except git.exc.GitCommandError as command: await event.answer( f"`An error occured trying to get the Git Repo.`\n`{command}`") repo.__del__() return except git.exc.InvalidGitRepositoryError: repo = git.Repo.init(basedir) origin = repo.create_remote("origin", main_repo) if not origin.exists(): await event.answer( "`The main repository does not exist. Remote is invalid!`") repo.__del__() return fetched_items = origin.fetch() repo.create_head("master", origin.refs.master).set_tracking_branch( origin.refs.master).checkout(force=True) fetched_commits = repo.iter_commits(f"HEAD..{fetched_items[0].ref.name}") untracked_files = repo.untracked_files old_commit = repo.head.commit for diff_added in old_commit.diff("FETCH_HEAD").iter_change_type("M"): if "requirements.txt" in diff_added.b_path: await event.answer("`Updating the pip requirements!`") updated = await update_requirements() if updated == 0: await event.answer("`Successfully updated the requirements.`") else: if isinstance(updated, int): await event.answer( "`Failed trying to install requirements." " Install them manually and run the command again.`") else: await event.answer(f"```{updated}```") return break if arg == "add": repo.index.add(untracked_files, force=True) repo.index.commit("[PaperplaneRemix] Updater: Untracked files") elif arg == "reset": repo.head.reset("--hard") try: config = repo.config_reader() try: if config.get_value("user", "name") and config.get_value( "user", "email"): pass except (NoSectionError, NoOptionError): LOGGER.warning( "No 'git' credentials found, falling back to generic data for the git pull." ) repo.config_writer().set_value( "user", "name", "PaperplaneRemix Updater").release() repo.config_writer().set_value("user", "email", "<>").release() repo.remotes.origin.pull() except git.exc.GitCommandError as command: text = ("`An error occured trying to Git pull:`\n`{0}`\n\n" "`You may use` **{1}update reset** `or` **{1}update add** " "`to reset your repo or add and commit your changes as well.`") prefix = client.prefix if client.prefix is not None else "." await event.answer(text.format(command, prefix)) repo.__del__() return new_commit = repo.head.commit if old_commit == new_commit: await event.answer("`Already up-to-date!`") repo.__del__() return remote_url = repo.remote().url.replace(".git", "/") if remote_url[-1] != "/": remote_url = remote_url + "/" now = datetime.datetime.now(datetime.timezone.utc) def_changelog = changelog = "**PaperplaneRemix changelog:**" for commit in reversed(list(fetched_commits)): changelog += summary.format( rev=repo.git.rev_parse(commit.hexsha, short=7), summary=commit.summary, url=remote_url, sha=commit.hexsha, ) ago = (now - commit.committed_datetime).total_seconds() elspased = (await _humanfriendly_seconds(ago)).split(",")[0] committers_link = author_link.format(author=commit.committer, url=remote_url) authors_link = author_link.format(author=commit.author, url=remote_url) if commit.author == commit.committer: committed = commited.format(committer=committers_link, elapsed=elspased) else: committed = authored.format(author=authors_link, committer=committers_link, elapsed=elspased) changelog += f"{committed:>{len(committed) + 8}}" if changelog == def_changelog: changelog = "`No changelog for you! IDK what happened.`" toast = await event.answer( "`Successfully pulled the new commits. Updating the userbot!`", log=("update", changelog.strip()), ) if not client.logger: await event.answer(changelog.strip(), reply_to=toast.id, link_preview=False) os.environ["userbot_update"] = "True" heroku_api_key = client.config["api_keys"].get("api_key_heroku", False) if os.getenv("DYNO", False) and heroku_api_key: heroku_conn = heroku3.from_key(heroku_api_key) app = None for heroku_app in heroku_conn.apps(): if "api_key_heroku" in heroku_app.config(): app = heroku_app break if app is None: await event.answer( "`You seem to be running on Heroku " "with an invalid environment. Couldn't update the app.`\n" "`The changes will be reverted upon dyno restart.`") repo.__del__() await restart(event) else: for build in app.builds(): if build.status == "pending": await event.answer( "`There seems to be an ongoing build in your app.`" " `Try again after it's finished.`") return # Don't update the telethon environment varaibles userbot_config = dict(client.config["userbot"]) app.config().update(userbot_config) # "Dirty Fix" for Heroku Dynos to update proper environment # variables for external plugin flags. heroku_ext_flags = { x[12:]: os.getenv(x, None) for x in list(os.environ) if x.startswith("ext_userbot_") } for flag in userbot_config: if flag in heroku_ext_flags: app.config().update( {f"ext_userbot_{flag}": userbot_config[flag]}) app.config().update({flag: None}) app.config().update({ "userbot_restarted": f"{event.chat_id}/{event.message.id}", "userbot_update": "True", }) if event.client.disabled_commands: disabled_list = ", ".join(client.disabled_commands.keys()) app.config().update( {"userbot_disabled_commands": disabled_list}) url = f"https://*****:*****@git.heroku.com/{app.name}.git" if "heroku" in repo.remotes: repo.remotes["heroku"].set_url(url) else: repo.create_remote("heroku", url) if repo.untracked_files: repo.index.add(untracked_files, force=True) repo.index.commit("[PaperplaneRemix] Updater: Untracked files") app.enable_feature("runtime-dyno-metadata") await event.answer( f"`Pushing all the changes to Heroku. This might take a while.`" ) remote = repo.remotes["heroku"] try: remote.push(refspec=f"{repo.active_branch.name}:master", force=True) await event.answer("`There was nothing to push to Heroku?`") except git.exc.GitCommandError as command: await event.answer( "`An error occured trying to pull and push to Heorku`" f"\n`{command}`") LOGGER.exception(command) repo.__del__() else: repo.__del__() await restart(event)
async def ban_user( event: NewMessage.Event or ChatAction.Event, bl_type: str = None, match: Union[str, int] = None, index: int = None, globally: bool = False, ) -> bool: if isinstance(event, NewMessage.Event): sender = await event.get_input_sender() else: sender = await event.get_input_user() temp_banlist.append(sender) chat = await event.get_chat() ban_right = getattr(chat.admin_rights, "ban_users", False) delete_messages = getattr(chat.admin_rights, "delete_messages", False) exc_logger = client.logger if client.logger else "self" if not (ban_right or chat.creator): return False user_href = "[{0}](tg://user?id={0})".format(sender.user_id) try: await client.edit_permissions(entity=chat.id, user=sender, view_messages=False) if bl_type and match and sender.user_id not in blacklistedUsers: blacklistedUsers.update({sender.user_id: (bl_type, match)}) redis.set("blacklist:users", dill.dumps(blacklistedUsers)) except Exception as e: exc = await client.get_traceback(e) await client.send_message(exc_logger, exc) LOGGER.exception(e) return False try: if delete_messages: await event.delete() except Exception: pass try: key = "g" + bl_type if globally else bl_type text, var = full_key_strings.get(key) formats = { "match": match, "type": bl_type, "index": index, "chat": chat.id, "user": sender.user_id, "user_link": user_href, } await client.resanswer( await event.get_input_chat(), text, plugin="blacklist", name=var, formats=formats, reply_to=event, ) if client.logger: logger_group = client.config["userbot"].getint( "logger_group_id", "me") if chat.username: chat_href = f"[{chat.title}]" f"(tg://resolve?domain={chat.username})" else: chat_href = f"[{chat.title}] `{chat.id}`" log_text = ("**USERBOT LOG** #blacklist\n" f"Banned {user_href} from {chat_href}.\n") if bl_type and match: log_text += f"Blacklist type: `{bl_type}`.\nMatch: `{match}`" await client.send_message(logger_group, log_text) return True except Exception as e: exc = await client.get_traceback(e) await client.send_message(exc_logger, exc) LOGGER.exception(e) return False finally: temp_banlist.remove(sender)
async def ban_user(event: NewMessage.Event or ChatAction.Event, bl_type: str = None, match: Union[str, int] = None, index: int = None, globally: bool = False) -> bool: if isinstance(event, NewMessage.Event): sender = await event.get_input_sender() else: sender = await event.get_input_user() temp_banlist.append(sender) chat = await event.get_chat() ban_right = getattr(chat.admin_rights, 'ban_users', False) delete_messages = getattr(chat.admin_rights, 'delete_messages', False) if not (ban_right or chat.creator): return False user_href = "[{0}](tg://user?id={0})".format(sender.user_id) try: await client.edit_permissions(entity=chat.id, user=sender, view_messages=False) except Exception as e: exc = await client.get_traceback(e) await event.respond(f"**Couldn't ban user. Exception:\n**```{exc}```") LOGGER.exception(e) return False try: if delete_messages: await event.delete() except Exception: pass try: key = 'g' + bl_type if globally else bl_type text, var = full_key_strings.get(key) formats = { 'match': match, 'type': bl_type, 'index': index, 'chat': chat.id, 'user': sender.user_id, 'user_link': user_href } await client.resanswer(event, text, plugin='blacklist', name=var, formats=formats, chat_override=True, reply_to=event) if client.logger: logger_group = client.config['userbot'].getint( 'logger_group_id', 'me') if chat.username: chat_href = (f"[{chat.title}]" f"(tg://resolve?domain={chat.username})") else: chat_href = f"[{chat.title}] `{chat.id}`" log_text = ("**USERBOT LOG** #blacklist\n" f"Banned {user_href} from {chat_href}.\n") if bl_type and match: log_text += f"Blacklist type: `{bl_type}`.\nMatch: `{match}`" await client.send_message(logger_group, log_text) if bl_type and match and sender.user_id not in blacklistedUsers: blacklistedUsers.update({sender.user_id: (bl_type, match)}) redis.set('blacklist:users', dill.dumps(blacklistedUsers)) return True except Exception as e: exc = await client.get_traceback(e) await event.respond( f"**Something went wrong. Exception:\n**```{exc}```") LOGGER.exception(e) return False finally: temp_banlist.remove(sender)