Esempio n. 1
0
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)
Esempio n. 2
0
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")
Esempio n. 3
0
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))
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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"))
Esempio n. 7
0
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
Esempio n. 8
0
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")
Esempio n. 9
0
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
Esempio n. 10
0
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")
Esempio n. 11
0
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)))
Esempio n. 12
0
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"))
Esempio n. 13
0
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
Esempio n. 14
0
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
    )
Esempio n. 15
0
def pmtest(bot, ctx: octobot.Context):
    ctx.reply("Check your PMs!")
    ctx.reply("Test", to_pm=True)
Esempio n. 16
0
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")
Esempio n. 17
0
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")
Esempio n. 18
0
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)
Esempio n. 19
0
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
    )
Esempio n. 20
0
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)
Esempio n. 21
0
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)
Esempio n. 22
0
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')
Esempio n. 23
0
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)
Esempio n. 24
0
def command_ban_cancel(bot: octobot.OctoBot, context: octobot.Context):
    execute_cancel(bot,
                   context,
                   reply_text=context.localize("Unbanned"),
                   func=bot.unban_chat_member)
Esempio n. 25
0
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")
                    )
Esempio n. 26
0
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)))
Esempio n. 27
0
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)