def start(bot: octobot.OctoBot, ctx: octobot.Context): if ctx.query == "": kbd = telegram.InlineKeyboardMarkup( [[ telegram.InlineKeyboardButton( ctx.localize("Command list"), url=f"https://t.me/{bot.me.username}?start=help") ], [ telegram.InlineKeyboardButton(ctx.localize("Support chat"), url=Settings.support_url) ]]) ctx.reply(ctx.localize( "Hi! I am {bot.me.first_name}, a Telegram bot with features and bugs and blah blah, noone reads /start anyway." ).format(bot=bot), reply_markup=kbd) else: # Proxify to other command update = ctx.update if ctx.args[0].startswith("b64-"): b64data = ctx.args[0].replace("b64-", "", 1) data = base64.urlsafe_b64decode(b64data) logger.debug(f'proxying b64 command {data} ({b64data})') update.message.text = data.decode() else: update.message.text = "/" + ctx.args[0] logger.debug("proxying plaintext command", update.message.text) bot.handle_update(bot, update)
def toggle_pack_command(bot: octobot.OctoBot, context: octobot.Context): if octobot.Database.redis is None: raise octobot.DatabaseNotAvailable no_pack_msg = context.localize( "Reply to sticker from stickerpack which you want to ban or pass the pack name as argument" ) if context.update.message.reply_to_message is not None: if context.update.message.reply_to_message.sticker is not None: target_pack = str( context.update.message.reply_to_message.sticker.set_name) else: return context.reply(no_pack_msg) elif len(context.args) > 0: target_pack = context.args[0] else: return context.reply(no_pack_msg) if octobot.Database.redis.sadd(create_redis_set_name(context.chat), target_pack) == 1: context.reply(context.localize( 'Pack <a href="https://t.me/addstickers/{pack_id}">{pack_id}</a> banned successfully' .format(pack_id=target_pack)), parse_mode="HTML") else: octobot.Database.redis.srem(create_redis_set_name(context.chat), target_pack) context.reply(context.localize( 'Pack <a href="https://t.me/addstickers/{pack_id}">{pack_id}</a> unbanned successfully' .format(pack_id=target_pack)), parse_mode="HTML")
def warnlist(bot: octobot.OctoBot, context: octobot.Context): if octobot.Database.redis is None: raise octobot.DatabaseNotAvailable reply = context.update.message.reply_to_message if reply is not None: target = reply.from_user.id target_name = reply.from_user.first_name elif len(context.args) > 0: target = context.args[0] if target.isdigit(): target = int(target) target_name = f"ID:{target}" else: if target.startswith("@"): target = target[1:] target_name = target res, target = lookup_username(target) if not res: return context.reply( context.localize("Failed to find username {username}"). format(username=target_name)) else: target = context.user.id target_name = context.user.first_name message = [context.localize("Warns for {name}:").format(name=target_name)] warns = octobot.Database.redis.lrange( create_warn_db_id(context.chat.id, target), 0, -1) if len(warns) == 0: context.reply( context.localize("{name} has no warns!").format(name=target_name)) else: for warn_reason in warns: message.append(f"- {warn_reason.decode()}") context.reply("\n".join(message))
def format_media_description(description: Union[str, None], ctx: Context): if description is None: short = ctx.localize("no description") long = "<i>{}</i>".format(ctx.localize("No description provided.")) else: long = cleanse_html(description) replacement_text = ctx.localize("(spoilers redacted)") short = cleanse_spoilers(long, replacement_text, html=False) long = cleanse_spoilers(long, replacement_text, html=True) short = textwrap.shorten(short, width=70, placeholder="…") long = textwrap.shorten(long, width=1024, placeholder="…") return long, short
def help_extra(bot, ctx: octobot.Context): if ctx.query != "": cmd = ctx.query for handlers in bot.handlers.values(): for handler in handlers: if isinstance( handler, octobot.CommandHandler) and cmd in handler.command: message = "{helpfor} {command}.\n{description}\n\n{long_description}".format( helpfor=ctx.localize("Help for"), command=handler.prefix + ctx.query, description=html.escape(handler.description), long_description=html.escape(handler.long_description)) ctx.reply(message) return
def inline_undo_warn(bot: octobot.OctoBot, context: octobot.Context): if octobot.Database.redis is None: raise octobot.DatabaseNotAvailable execute_cancel(bot=bot, context=context, func=undo_warn, reply_text=context.localize("Warn removed"))
def urban_query(query, index, max_amount, bot: octobot.OctoBot, ctx: octobot.Context): index = int(index) if index == -1: return if index < 0: raise catalogs.CatalogCantGoBackwards r = requests.get(apiurl, params={"term": query}).json() if "list" in r and len(r["list"]) > 0: definitions = r["list"] if index > len(definitions): raise catalogs.CatalogCantGoDeeper res = [] base = ctx.localize(DEF_BASELINE) text_link = ctx.localize("Definition on Urban Dictionary") for definition in definitions[index:max_amount + index]: desc_inline = textwrap.shorten(definition["definition"], width=100, placeholder="...") definition["definition"] = add_links( html.escape(definition["definition"]), bot) definition["example"] = add_links( html.escape(definition["example"]), bot) definition["word"] = html.escape(definition["word"]) definition["author"] = html.escape(definition["author"]) res.append( catalogs.CatalogKeyArticle( title=ctx.localize("Definition for {}").format( definition["word"]), description=desc_inline, text=base.format(escape=html.escape, **definition), parse_mode="html", reply_markup=telegram.InlineKeyboardMarkup([[ telegram.InlineKeyboardButton( url=definition["permalink"], text=text_link) ]]))) if index + max_amount > len(definitions): next_offset = -1 else: next_offset = index + max_amount return catalogs.Catalog(res, max_count=len(definitions), current_index=index + 1, previous_offset=index - 1, next_offset=next_offset) else: raise catalogs.CatalogNotFound
def spamwatch_handle_user(bot: octobot.OctoBot, ctx: octobot.Context): if ctx.chat.type != "supergroup": return chat_action = ctx.chat_db.get(SPAMWATCH_DB_KEY, Settings.spamwatch.default_action) if chat_action == "nothing": return chat_action = VALID_ACTIONS[chat_action] banned = check_spamwatch_ban(ctx.user) if banned: chat_action[-1](bot, ctx.chat, ctx.user) bot.send_message( ctx.chat.id, ctx.localize( "{user} is banned in SpamWatch since {ban_date}. Reason: <code>{ban_reason}</code>" ).format(user=ctx.user.mention_html(ctx.localize("User")), ban_date=babel.dates.format_datetime(banned.date, locale=ctx.locale), ban_reason=html.escape(banned.reason)), parse_mode="HTML")
def help_command(query, idx, max_amount, bot: octobot.OctoBot, ctx: octobot.Context): del query, max_amount if ctx.chat.type == "supergroup": max_amount = 5 else: max_amount = 15 idx = int(idx) handlers = [] if idx < 0: raise catalogs.CatalogCantGoBackwards for handlers_prioritylist in list(bot.handlers.values()): for handler in handlers_prioritylist: if isinstance(handler, octobot.CommandHandler) and not handler.hidden: handlers.append(handler) handlers = [ handlers[x:x + max_amount] for x in range(0, len(handlers), max_amount) ] handlers_msg = "" if len(handlers) - 1 < idx: raise catalogs.CatalogCantGoDeeper last_plugin = "" for handler in handlers[idx]: if last_plugin != handler.plugin["plugin_info"].name: last_plugin = handler.plugin["plugin_info"].name handlers_msg += f"<b>{ctx.localize(handler.plugin['plugin_info'].name)}:</b>\n" handlers_msg += '{commands} – {description}. <i><a href="t.me/{bot.me.username}?start=b64-{command}">{learnmore}</a></i>\n'.format( commands=", ".join(handler.commandlist), description=html.escape(ctx.localize(handler.description)), bot=bot, command=base64.urlsafe_b64encode( ("/helpextra " + handler.command[0]).encode()).decode(), learnmore=ctx.localize("More…")) catalog = catalogs.Catalog( results=[catalogs.CatalogKeyArticle(handlers_msg, parse_mode="HTML")], current_index=idx + 1, next_offset=idx + 1, previous_offset=idx - 1, max_count=len(handlers)) return catalog
def gtl(bot: octobot.OctoBot, context: octobot.Context): if context.update.message is not None and context.update.message.reply_to_message is not None: reply = context.update.message.reply_to_message if reply.caption is not None: text = reply.caption else: text = reply.text text_type = "reply" else: text = str(context.query) text_type = "args" source_language = None destination_language = None default_language = octobot.localization.get_chat_locale(context.update) if len(context.args) > 0: arg_0 = context.args[0] if arg_0 in googletrans.LANGUAGES: destination_language = arg_0 destination_language.replace("_", "-") if text_type == "args": text = " ".join(context.args[1:]) elif arg_0.count("-") == 1: source_language, destination_language = arg_0.split("-") source_language.replace("_", "-") destination_language.replace("_", "-") if text_type == "args": text = " ".join(context.args[1:]) if source_language not in googletrans.LANGUAGES: source_language = "auto" if destination_language not in googletrans.LANGUAGES: destination_language = default_language translation = translator.translate(text, dest=destination_language, src=source_language) return context.reply(context.localize(TRANSLATION_TEMPLATE).format( source_language=googletrans.LANGUAGES[translation.src].title(), target_language=googletrans.LANGUAGES[translation.dest].title(), text=html.escape(translation.text)), parse_mode="HTML")
def button_pin(bot: octobot.OctoBot, context: octobot.Context): chat_id, message_id = context.text.split(":")[1:] perm_check, missing_perms = octobot.check_permissions( chat=chat_id, user=context.user.id, bot=bot, permissions_to_check={"can_pin_messages"}) if perm_check: bot.pin_chat_message(chat_id, message_id, disable_notification=True) context.reply(context.localize("Pinned back the old message")) msg = context.update.effective_message.text_html + "\n\n" + context.localize( 'This action was undone by <a href="tg://user?id={admin_id}">{admin}</a>' ).format(admin_id=context.user.id, admin=html.escape(context.user.first_name)) context.edit(msg, parse_mode="HTML") else: context.reply( context.localize( "Sorry, you can't execute this command cause you lack following permissions: {}" ).format(", ".join(missing_perms)))
def list_bannedpacks(bot: octobot.OctoBot, context: octobot.Context): if octobot.Database.redis is None: raise octobot.DatabaseNotAvailable if octobot.Database.redis.scard(create_redis_set_name(context.chat)) > 0: message = [ context.localize( "This stickerpacks are currently banned in <b>{chat_name}</b>:" ).format(chat_name=html.escape(context.chat.title)) ] for pack in octobot.Database.redis.smembers( create_redis_set_name(context.chat)): message.append( '- <a href="https://t.me/addstickers/{pack_id}">{pack_id}</a>'. format(pack_id=html.escape(pack.decode()))) context.reply("\n".join(message), parse_mode="HTML") else: context.reply( context.localize( "There are no stickerpacks that are banned in this chat"))
def get_media_metadata(media, ctx: Context): mtype = media["type"] metadata = [] if media["format"] is not None and media["format"] in MEDIA_FORMAT_STR: metadata.append(ctx.localize(MEDIA_FORMAT_STR[media["format"]])) if media["status"] is not None: if mtype == MEDIA_ANIME: status_str = ctx.localize(ANIME_MEDIA_STATUSES_STR.get(media["status"], media["status"])) elif mtype == MEDIA_MANGA: status_str = ctx.localize(MANGA_MEDIA_STATUSES_STR.get(media["status"], media["status"])) metadata.append(status_str) if mtype == MEDIA_ANIME and media["episodes"] is not None: episodes_str = ctx.localize("{} episodes").format(media["episodes"]) metadata.append(episodes_str) if mtype == MEDIA_MANGA: if media["volumes"] is not None: volumes_str = ctx.localize("{} volumes").format(media['volumes']) metadata.append(volumes_str) if media["chapters"] is not None: chapters_str = ctx.localize("{} chapters").format(media['chapters']) metadata.append(chapters_str) if media["averageScore"] is not None: score = media["averageScore"] / 10 score_str = ctx.localize("rating {:0.1f}/10").format(score) metadata.append(score_str) if media["startDate"] is not None: start_date_str = get_fuzzy_date_str(media["startDate"], ctx) if start_date_str is not None: metadata.append(start_date_str) return metadata
def anilist_search_character(query: str, offset: str, count: int, bot: OctoBot, ctx: Context) -> Catalog: res = [] try: offset = int(offset) except ValueError: raise CatalogNotFound if offset < 0: raise CatalogCantGoBackwards if count > MAX_RESULTS: count = MAX_RESULTS resp = graphql(GRAPHQL_QUERY, "Character", { "query": query, "page": ceil((offset + 1) / count), "perPage": count }) page_data = resp["data"]["Page"] page_info = page_data["pageInfo"] characters = page_data["characters"] total = page_info["total"] if total == 0: raise CatalogNotFound for item in characters: item["full_name"] = item["name"]["full"] if len(item["name"]["alternative"]) > 0 and item["name"]["alternative"][0] != "": item["alternative_names"] = "aka " + ", ".join(item["name"]["alternative"]) + "\n" else: item["alternative_names"] = "" item["description"], short_description = format_media_description(item["description"], ctx) item["present_in"] = "\n".join( [f"<a href=\"{media['siteUrl']}\">{get_media_title(media['title'])}</a>" for media in item["media"]["nodes"]]) text = ctx.localize(CHARACTER_TEMPLATE_STR).format(**item) photos = [ CatalogPhoto(url=item["image"]["large"], width=0, height=0), CatalogPhoto(url=item["image"]["medium"], width=0, height=0), ] print(item["full_name"], end=' ') res.append(CatalogKeyArticle(text=text, title=item["full_name"], description=short_description, photo=photos, parse_mode="HTML")) next_offset = offset + count if next_offset > total: next_offset = None return Catalog( results=res, max_count=total, previous_offset=offset - count, current_index=offset + 1, next_offset=next_offset )
def pmtest(bot, ctx: octobot.Context): ctx.reply("Check your PMs!") ctx.reply("Test", to_pm=True)
def set_spamwatch_action(bot: octobot.OctoBot, ctx: octobot.Context): if len(ctx.args) > 0: action = ctx.args[0] if action in VALID_ACTIONS: ctx.chat_db[SPAMWATCH_DB_KEY] = action ctx.reply( ctx.localize("Action {action} set. ").format(action=action) + ctx.localize(VALID_ACTIONS[action][0])) return else: msg = [ f'<code>{action}</code> ' + ctx.localize("is not a valid action.") ] else: msg = [ ctx.localize("You hadn't specified action to set!"), ] msg.append(ctx.localize("Available actions:")) cur_act = ctx.chat_db.get(SPAMWATCH_DB_KEY, Settings.spamwatch.default_action) is_default_str = f'<b>({ctx.localize("Default")})</b>' for action, (action_desc, _) in VALID_ACTIONS.items(): msg.append( f"<code>{action}</code> - {ctx.localize(action_desc)} " f"{is_default_str if action == Settings.spamwatch.default_action else ''}" ) msg.append( ctx.localize("Current action in this chat is") + f" <code>{cur_act}</code>") ctx.reply("\n".join(msg), parse_mode="HTML")
def command_ban(bot: octobot.OctoBot, context: octobot.Context): execute_command(bot.kick_chat_member, context, context.localize('🔨<a href="tg://user?id={admin_id}">{admin_name}</a> banned ' + \ '<a href="tg://user?id={target}">{target_name}</a>'), action=context.localize("ban"), cancel="ban_cancel")
def ping(bot: OctoBot, ctx: Context): time = (datetime.datetime.utcnow().replace(tzinfo=pytz.UTC) - ctx.update.message.date).total_seconds() ctx.reply(ctx.localize("🏓 Pong! Reply latency: %.2fs") % time)
def anilist_search_media(query: str, offset: str, count: int, bot: OctoBot, ctx: Context, media_type=MEDIA_ANIME): res = [] try: offset = int(offset) except ValueError: raise CatalogNotFound if offset < 0: raise CatalogCantGoBackwards if count > MAX_RESULTS: count = MAX_RESULTS resp = graphql(GRAPHQL_QUERY, "Media", { "query": query, "page": ceil((offset + 1) / count), "perPage": count, "type": media_type }) page_data = resp["data"]["Page"] page_info = page_data["pageInfo"] media = page_data["media"] total = page_info["total"] if total == 0: if offset == 0: raise CatalogNotFound() else: raise CatalogCantGoDeeper() for item in media: item["title"] = get_media_title(item["title"]) item["metadata"] = ", ".join(get_media_metadata(item, ctx)) item["description"], short_description = format_media_description(item["description"], ctx) item["genres"] = ", ".join(item["genres"]) text = ctx.localize(MEDIA_TEMPLATE_STR).format(**item) photos = [ CatalogPhoto(url=item["coverImage"]["large"], width=0, height=0), CatalogPhoto(url=item["coverImage"]["medium"], width=0, height=0), ] res.append(CatalogKeyArticle(text=text, title=item["title"], description=short_description, photo=photos, parse_mode="HTML")) next_offset = offset + count if next_offset > total: next_offset = None return Catalog( results=res, max_count=total, previous_offset=offset - count, current_index=offset, next_offset=next_offset )
def safebooru_search(query: str, offset: str, limit: int, bot: OctoBot, ctx: Context) -> Catalog: res = [] try: offset = int(offset) except ValueError: raise CatalogNotFound() if offset < 0: raise CatalogCantGoBackwards if offset // MAX_RESULTS > 0: iter_offset = offset % MAX_RESULTS page = offset // MAX_RESULTS else: page = 0 iter_offset = offset if limit > MAX_RESULTS: limit = MAX_RESULTS plugin.logger.debug("iter offset %s, page %s", iter_offset, page) image = octobot.Database.get_cache("https://safebooru.org/index.php", params={ "page": "dapi", "s": "post", "q": "index", "tags": query, "limit": MAX_RESULTS, "pid": page }, headers=HEADERS) api_q = bs4.BeautifulSoup(image.text, "html.parser").posts total = int(api_q.attrs["count"]) if total == 0: raise CatalogNotFound() posts = api_q.find_all("post") plugin.logger.debug(posts) for post in posts[iter_offset:]: tags_base = html.escape(post.attrs["tags"]).split() tags = [] tag_len = 0 for tag in tags_base: if tag_len < 800: tags.append( f'<a href="{bot.generate_startlink("/sb " + tag)}">{tag}</a>' ) tag_len += len(tag) else: tags.append("<code>...</code>") break item = SafebooruPost( id=post.attrs["id"], rating=post.attrs["rating"], tags=tags, tags_str=" ".join(tags), source=post.attrs["source"], file_url=post.attrs["file_url"], width=int(post.attrs["width"]), height=int(post.attrs["height"]), sample_url=post.attrs["sample_url"], sample_width=int(post.attrs["sample_width"]), sample_height=int(post.attrs["sample_height"]), preview_url=post.attrs["preview_url"], preview_width=int(post.attrs["preview_width"]), preview_height=int(post.attrs["preview_height"]), ) photos = [ CatalogPhoto(url=item.sample_url, width=item.sample_width, height=item.sample_height), CatalogPhoto(url=item.preview_url, width=item.preview_width, height=item.preview_height) ] reply_markup = [[ telegram.InlineKeyboardButton( url="https://safebooru.org/index.php?page=post&s=view&id={}". format(item.id), text=ctx.localize("View on safebooru")) ]] if item.source is not None: url = urlparse(item.source) if url.scheme in ["http", "https"]: reply_markup[0].append( telegram.InlineKeyboardButton(url=item.source, text=ctx.localize("Source"))) res.append( CatalogKeyPhoto( text=ctx.localize(MSG_TEMPLATE).format(**item.__dict__), title="", description="", photo=photos, reply_markup=telegram.InlineKeyboardMarkup(reply_markup), parse_mode="HTML")) next_offset = offset + limit if next_offset > total: next_offset = None return Catalog(results=res, max_count=total, previous_offset=offset - limit, current_index=offset + 1, next_offset=next_offset, photo_primary=True)
def imgur_search(query, index, max_count, bot: octobot.OctoBot, context: octobot.Context): index = int(index) page = index // 60 start_pos = index % 60 logger.debug("page %s, start pos %s", page, start_pos) if index < 0: raise octobot.catalogs.CatalogCantGoDeeper r = octobot.Database.get_cache( f"https://api.imgur.com/3/gallery/search/time/all/{page}", params={ "q": query }, headers={ "Authorization": f"Client-ID {Settings.imgur_clientid}" }).json() if len(r["data"]) == 0: if index > 0: raise octobot.CatalogCantGoDeeper else: raise octobot.CatalogNotFound res = [] for item in r["data"][start_pos:start_pos + max_count]: if "images" in item: photo = [ octobot.CatalogPhoto(url=item["images"][0]["link"], width=item["images"][0]["width"], height=item["images"][0]["height"]) ] elif "gifv" in item: photo = [ octobot.CatalogPhoto(url=item["gifv"], width=item["width"], height=item["height"]) ] elif "link" in item: photo = [ octobot.CatalogPhoto(url=item["link"], width=item["width"], height=item["height"]) ] else: raise ValueError(f"Cant find image: {item}") text = [f'<b>{html.escape(item["title"])}</b>'] if item["description"] is not None: text.append(context.localize("Description:")) text.append(f"<i>{html.escape(item['description'])}</i>") if "images_count" in item and item["images_count"] > 1: text.append( context.localize("Album with {count} images").format( count=item["images_count"])) res.append( octobot.CatalogKeyPhoto( item_id=item["id"], photo=photo, title=item["title"], text="\n".join(text), parse_mode="HTML", reply_markup=telegram.InlineKeyboardMarkup.from_button( telegram.InlineKeyboardButton( text=context.localize("View on Imgur"), url=item["link"])))) return octobot.Catalog(res, next_offset=index + max_count, current_index=index + 1, previous_offset=index - max_count, photo_primary=True)
def ping(bot: OctoBot, ctx: Context): user_id = ctx.user.id if ctx.update.message: chat_id = ctx.update.message.chat.id chat_type = ctx.update.message.chat.type elif ctx.update.inline_query: chat_id = "None" chat_type = "Inline Query" else: return ctx.reply("Cant understand what is going on in that update of yours") message = [ctx.localize("{} ID:<code>{}</code>").format(ctx.user.mention_html(ctx.localize("Your")), user_id), ctx.localize("Chat ID:<code>{}</code>").format(chat_id), ctx.localize("Chat type is <code>{}</code>").format(chat_type)] if ctx.update.message: msg = ctx.update.message message.append(ctx.localize("ID of your message: <code>{}</code>").format(ctx.update.message.message_id)) if msg.reply_to_message: reply = msg.reply_to_message message.append(ctx.localize("ID of replied message: <code>{}</code>").format(reply.message_id)) if reply.from_user.id: message.append(ctx.localize("ID of {} from replied message: {}").format((reply.from_user.mention_html("user")), reply.from_user.id)) if reply.forward_from: message.append(ctx.localize("Forward {} ID: {}").format((reply.forward_from.mention_html("user")), reply.forward_from.id)) if reply.forward_from_message_id: message.append(ctx.localize("Forwarded message ID in original chat: {}").format(reply.forward_from_message_id)) if reply.forward_from_chat: message.append(ctx.localize("Forwarded message original chat ({}) ID: {}").format(reply.forward_from_chat.title, reply.forward_from_chat.id)) ctx.reply("\n".join(message), parse_mode='html')
def warn(bot: octobot.OctoBot, context: octobot.Context): if octobot.Database.redis is None: raise octobot.DatabaseNotAvailable if context.update.message.reply_to_message is None: context.reply(context.localize("Reply to user to give them a warn")) return if octobot.check_permissions( chat=context.chat, user=context.update.message.reply_to_message.from_user, permissions_to_check={"is_admin"})[0]: context.reply(context.localize("Can't warn administrator")) return target_id = context.update.message.reply_to_message.from_user.id target_name = context.update.message.reply_to_message.from_user.first_name user_warns_db_id = create_warn_db_id(context.chat.id, target_id) max_warns = int(context.chat_db.get("max_warns", 3)) reason = context.query if reason == "": reason = context.localize("Warn reason not specified") octobot.Database.redis.lpush(user_warns_db_id, reason) user_warn_count = int(octobot.Database.redis.llen(user_warns_db_id)) action_taken = "" reply_markup = telegram.InlineKeyboardMarkup.from_button( telegram.InlineKeyboardButton( text="Remove last warn", callback_data=f"warn_cancel:{target_id}:{context.chat.id}")) if user_warn_count >= max_warns: action_taken = context.localize( "\n\n<i>User had reached maximum warnings in chat and was banned</i>" ) bot.kick_chat_member(chat_id=context.chat.id, user_id=target_id) octobot.Database.redis.delete(user_warns_db_id) reply_markup = telegram.InlineKeyboardMarkup.from_button( telegram.InlineKeyboardButton( callback_data=f"ban_cancel:{target_id}:{context.chat.id}", text=context.localize("Unban"))) context.reply(context.localize('⚠�<a href="tg://user?id={admin_id}">{admin}</a> warned ' + \ '<a href="tg://user?id={target_id}">{target_name}</a> ' + \ '({warn_count}/{max_warns})' + \ '\nReason: <i>{reason}</i>').format( admin_id=context.user.id, admin=html.escape(context.user.first_name), target_id=target_id, target_name=html.escape(target_name), reason=html.escape(reason), warn_count=user_warn_count, max_warns=max_warns ) + action_taken, parse_mode="HTML", reply_markup=reply_markup)
def command_ban_cancel(bot: octobot.OctoBot, context: octobot.Context): execute_cancel(bot, context, reply_text=context.localize("Unbanned"), func=bot.unban_chat_member)
def command_kick(bot: octobot.OctoBot, context: octobot.Context): execute_command(bot.unban_chat_member, context, context.localize('👞<a href="tg://user?id={admin_id}">{admin_name}</a> kicked ' + \ '<a href="tg://user?id={target}">{target_name}</a>'), action=context.localize("kick") )
def execute_cancel(bot: octobot.OctoBot, context: octobot.Context, func: typing.Callable, reply_text: str): tgt_id, chat_id = context.text.split(":")[1:] perm_check, missing_perms = octobot.check_permissions( chat=chat_id, user=context.user.id, bot=bot, permissions_to_check={"can_restrict_members"}) if perm_check: if tgt_id.isdigit(): func(chat_id=chat_id, user_id=tgt_id) context.reply(reply_text) msg = context.update.effective_message.text_html + "\n\n" + context.localize( 'This action was undone by <a href="tg://user?id={admin_id}">{admin}</a>' ).format(admin_id=context.user.id, admin=html.escape(context.user.first_name)) context.edit(msg, parse_mode="HTML") else: context.reply(context.localize("Invalid ID passed")) else: context.reply( context.localize( "Sorry, you can't execute this command cause you lack following permissions: {}" ).format(", ".join(missing_perms)))
def execute_command(func: typing.Callable, context: octobot.Context, success_message: str, action: str, cancel: str = None): reply = context.update.message.reply_to_message if reply is not None: target = reply.from_user.id target_name = reply.from_user.first_name elif len(context.args) > 0: target = context.args[0] target_name = f"ID:{target}" if not target.isdigit(): if target.startswith("@"): target = target[1:] target_name = f"@{target}" success, target = lookup_username(target) if not success: context.reply( context.localize( "I hadn't seen the person whose username is @{username}" ).format(target)) return else: target = int(target) else: context.reply( context.localize( "You hadn't specified the target!" + \ "Reply to message of person you want to {action} or specify their ID or username").format( action=action)) return if octobot.check_permissions(chat=context.chat, user=target, permissions_to_check={"is_admin"})[0]: context.reply( context.localize("I can't {action} administrators.").format( action=action)) return try: func(chat_id=context.chat.id, user_id=target) except telegram.error.BadRequest as e: context.reply(context.localize( 'Can\'t {action} <a href="tg://user?id={target}">{target_name}</a>.\nError: <code>{error}</code>.' ).format(action=action, target=html.escape(target_name), error=html.escape(e.message)), parse_mode="html") else: cancel_markup = None if cancel is not None: cancel_markup = telegram.InlineKeyboardMarkup.from_button( telegram.InlineKeyboardButton( text=context.localize("Cancel"), callback_data=f"{cancel}:{target}:{context.chat.id}")) context.reply(success_message.format( admin_name=html.escape(context.user.first_name), admin_id=context.user.id, target=target, target_name=html.escape(target_name)), parse_mode="html", reply_markup=cancel_markup)