コード例 #1
0
async def open_posts(_, callback):
    username = callback.data.split(' ')[1]

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    key = f"{callback.message.chat.id}_{callback.message.message_id}"

    profile: Profile = cached_profiles.get(key)
    right_user_id = cached_ids.get(key)

    if profile is None or right_user_id is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await callback.edit_message_text("", reply_markup="")
        return

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    iterator: PostsIterator = cached_posts.get(key)

    if iterator is None:
        posts = get_user_posts(username)

        if posts == "Fail":
            await callback.answer(get_message(language, "errors/fail"),
                                  show_alert=True)
            return

        next_max_id = posts.get("next_max_id")

        iterator = PostsIterator(posts["post_list"], username, next_max_id)

        cached_posts[key] = iterator

    await callback.answer()

    post: Post = iterator.next(
    ) if iterator.index != -1 else iterator.collection[iterator.index]

    caption = create_caption_posts(post.caption, post.taken_at, post.views,
                                   post.is_video)

    keyboard = create_keyboard_posts(post.likes,
                                     post.comment_number,
                                     iterator.username,
                                     len(iterator.collection),
                                     language,
                                     callback.from_user.id,
                                     from_profile=True)

    media = InputMediaVideo(post.source) if post.is_video else InputMediaPhoto(
        post.source)
    media.caption = caption

    await callback.edit_message_media(media)
    await callback.edit_message_reply_markup(keyboard)
コード例 #2
0
async def open_stories_inline(client, callback):
    username = callback.data.split(' ')[1]

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    key = callback.inline_message_id

    iterator: InlineStoriesIterator = inline_cached_stories.get(key)

    profile_userid: List[Profile, int] = inline_cached_profiles.get(key)

    if profile_userid is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    right_user_id = profile_userid[1]

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    if iterator is None:
        user = get_user_id(username)

        if "username" not in user:
            await callback.answer(get_message(language, "errors/fail"),
                                  show_alert=True)
            return

        stories = _request_story(user["user_id"])

        if stories == "fail":
            await callback.answer(get_message(language, "errors/fail"),
                                  show_alert=True)
            return

        if stories == "no_stories":
            await callback.answer(get_message(language, "errors/no_stories"),
                                  show_alert=True)
            return

        iterator = InlineStoriesIterator(stories, username)

    await callback.answer()

    story = iterator.next() if iterator.index == -1 else iterator.collection[
        iterator.index]

    date = f"<a href='{story.url}'>{format_date(story.taken_at)}</a>"

    keyboard = create_keyboard_stories_from_inline(len(iterator.collection),
                                                   language)

    await client.edit_inline_text(key, date, reply_markup=keyboard)

    inline_cached_stories[key] = iterator
コード例 #3
0
async def back_to_profile(_, callback):
    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    key = f"{callback.message.chat.id}_{callback.message.message_id}"

    profile: Profile = cached_profiles.get(key)
    right_user_id = cached_ids.get(key)

    if profile is None or right_user_id is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await callback.edit_message_text("", reply_markup="")
        return

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, 'errors/wrong_id'),
                              show_alert=True)
        return

    await callback.answer()

    caption = create_caption_profile(profile, language)

    keyboard = create_keyboard_profile(profile.username, language,
                                       profile.is_private)

    await callback.edit_message_media(InputMediaPhoto(profile.profile_pic,
                                                      caption=caption),
                                      reply_markup=keyboard)
コード例 #4
0
async def open_posts_inline(client, callback):
    username = callback.data.split(' ')[1]

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    key = callback.inline_message_id

    iterator: InlinePostsIterator = inline_cached_posts.get(key)

    profile_userid: List[Profile, int] = inline_cached_profiles.get(key)

    if profile_userid is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    right_user_id = profile_userid[1]

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    if iterator is None:
        posts = get_user_posts(username)

        if posts == "Fail":
            await callback.answer(get_message(language, "errors/fail"),
                                  show_alert=True)
            return

        next_max_id = posts.get("next_max_id")

        iterator = InlinePostsIterator(posts["post_list"], username,
                                       next_max_id)

    await callback.answer()

    post = iterator.next() if iterator.index == -1 else iterator.collection[
        iterator.index]

    caption = create_caption_posts(post.caption,
                                   post.taken_at,
                                   post.views,
                                   post.is_video,
                                   link=post.source)

    keyboard = create_keyboard_posts_from_inline(post.likes,
                                                 post.comment_number,
                                                 len(iterator.collection),
                                                 language)

    await client.edit_inline_text(key,
                                  caption,
                                  disable_web_page_preview=False,
                                  reply_markup=keyboard)

    inline_cached_posts[key] = iterator
コード例 #5
0
async def back_to_profile_inline(client, callback):
    key = callback.inline_message_id

    profile_userid: List[Profile, int] = inline_cached_profiles.get(key)

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    if profile_userid is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    profile = profile_userid[0]

    right_user_id = profile_userid[1]

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    await callback.answer()

    caption = create_caption_profile(profile, language, use_link=True)

    keyboard = create_keyboard_profile_from_inline(profile.username, language,
                                                   profile.is_private)

    await client.edit_inline_text(key, caption, reply_markup=keyboard)
コード例 #6
0
async def on_stories(_, message):
    username = '******'.join(message.command[1:])

    language = get_language(message.from_user.id,
                            message.from_user.language_code)

    if username == "":
        await message.reply_text(
            get_message(language, "errors/username_not_specified"))
        return

    user = get_user_id(username)

    if "username" not in user:
        await message.reply_text(get_message(language, "errors/fail"))
        return

    wait_message = await message.reply_text(get_message(language, "loading"))

    stories = _request_story(user["user_id"])

    if stories == "private_account":
        await message.reply_text(
            get_message(language, "errors/private_account"))
        return

    if stories == "no_stories":
        await message.reply_text(get_message(language, "errors/no_stories"))
        return

    iterator = StoriesIterator(stories, username, message.from_user.id)

    story = iterator.next()

    date = format_date(story.taken_at)

    keyboard = create_keyboard_stories(username,
                                       len(iterator.collection),
                                       language,
                                       from_profile=False)

    try:
        await wait_message.delete()
    except:
        pass

    if story.type_story == "mp4/video/boomerang":
        message = await message.reply_video(story.url,
                                            caption=date,
                                            reply_markup=keyboard)

    else:
        message = await message.reply_photo(story.url,
                                            caption=date,
                                            reply_markup=keyboard)

    key = f"{message.chat.id}_{message.message_id}"

    cached_stories[key] = iterator
コード例 #7
0
async def next_post(_, callback):
    message_id = callback.message.message_id
    chat_id = callback.message.chat.id

    key = f"{chat_id}_{message_id}"

    iterator: PostsIterator = cached_posts.get(key)

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    if iterator is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await callback.edit_message_text("", reply_markup="")
        return

    if iterator.right_user_id is None:
        iterator.right_user_id = cached_ids.get(key)

        if iterator.right_user_id is None:
            await callback.answer(get_message(language,
                                              "errors/not_cached_stories"),
                                  show_alert=True)
            await callback.edit_message_text("", reply_markup="")
            return

    if callback.from_user.id != iterator.right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    post = iterator.next()

    if post == "Fail":
        await callback.answer(get_message(language, "errors/fail"),
                              show_alert=True)
        return

    await callback.answer()

    caption = create_caption_posts(post.caption, post.taken_at, post.views,
                                   post.is_video)

    from_profile = len(callback.data.split(' ')) > 1

    keyboard = create_keyboard_posts(post.likes,
                                     post.comment_number,
                                     iterator.username,
                                     len(iterator.collection),
                                     callback.from_user.language_code,
                                     callback.from_user.id,
                                     from_profile=from_profile)

    media = InputMediaVideo(post.source) if post.is_video else InputMediaPhoto(
        post.source)
    media.caption = caption

    await callback.edit_message_media(media, reply_markup=keyboard)
コード例 #8
0
async def get_comments(_, callback):
    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    message_id = callback.message.message_id
    chat_id = callback.message.chat.id

    key = f"{chat_id}_{message_id}"

    iterator: PostsIterator = cached_posts.get(key)

    if iterator is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await callback.edit_message_text("", reply_markup="")

        return

    if iterator.right_user_id is None:
        iterator.right_user_id = cached_ids.get(key)

        if iterator.right_user_id is None:
            await callback.answer(get_message(language,
                                              "errors/not_cached_stories"),
                                  show_alert=True)
            await callback.edit_message_text("", reply_markup="")
            return

    if callback.from_user.id != iterator.right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    post = iterator.collection[iterator.index]

    response = get_post_details(post.shortcode)

    if response["status"] != "Success":
        await callback.answer(get_message(language, "errors/fail"),
                              show_alert=True)
        return

    await callback.answer()

    comments_json = response["body"]["edge_media_to_parent_comment"]["edges"]

    comments = create_caption_comments(comments_json, language)

    from_profile = len(callback.data.split(' ')) > 1

    keyboard = InlineKeyboardMarkup([[
        InlineKeyboardButton(
            f"{emoji.BACK_ARROW} {get_message(language, 'keyboards/back')}",
            callback_data="back" if not from_profile else "back profile")
    ]])

    await callback.edit_message_caption(comments)
    await callback.edit_message_reply_markup(keyboard)
コード例 #9
0
async def on_posts(_, message):
    username = '******'.join(message.command[1:])

    language = get_language(message.from_user.id,
                            message.from_user.language_code)

    if username == "":
        await message.reply_text(
            get_message(language, "errors/username_not_specified"))
        return

    wait_message = await message.reply_text(get_message(language, "loading"))

    posts = get_user_posts(username)

    if posts == "Fail":
        await message.reply_text(get_message(language, "errors/fail"))
        return

    next_max_id = posts.get("next_max_id")

    iterator = PostsIterator(posts["post_list"], username, next_max_id,
                             message.from_user.id)

    post = iterator.next()

    caption = create_caption_posts(post.caption, post.taken_at, post.views,
                                   post.is_video)

    keyboard = create_keyboard_posts(post.likes,
                                     post.comment_number, iterator.username,
                                     len(iterator.collection),
                                     message.from_user.language_code,
                                     message.from_user.id)

    try:
        await wait_message.delete()
    except:
        pass

    if post.is_video:
        message = await message.reply_video(post.source,
                                            caption=caption,
                                            reply_markup=keyboard)

    else:
        message = await message.reply_photo(post.source,
                                            caption=caption,
                                            reply_markup=keyboard)

    key = f"{message.chat.id}_{message.message_id}"

    cached_posts[key] = iterator
コード例 #10
0
async def comments_inline(client, callback):
    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    key = callback.inline_message_id

    iterator: InlinePostsIterator = inline_cached_posts.get(key)

    profile_userid: List[Profile, int] = inline_cached_profiles.get(key)

    if profile_userid is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    right_user_id = profile_userid[1]

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    if iterator is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    await callback.answer()

    post = iterator.collection[iterator.index]

    response = get_post_details(post.shortcode)

    if response["status"] != "Success":
        await callback.answer(get_message(language, "errors/fail"),
                              show_alert=True)
        return

    comments_json = response["body"]["edge_media_to_parent_comment"]["edges"]

    comments = create_caption_comments(comments_json, language)

    keyboard = InlineKeyboardMarkup([[
        InlineKeyboardButton(
            f"{emoji.BACK_ARROW} {get_message(language, 'keyboards/back')}",
            callback_data="inline_back")
    ]])

    await client.edit_inline_text(key, comments, reply_markup=keyboard)
コード例 #11
0
async def change_language_callback(_, callback):
    new_language = (callback.data.split('_'))[1]

    change_language(callback.from_user.id, new_language)

    keyboard = create_languages_keyboard(new_language)

    await callback.answer(get_message(new_language,
                                      "languages/changed_language"),
                          show_alert=True)

    await callback.edit_message_text(get_message(new_language,
                                                 "languages/choose_language"),
                                     reply_markup=keyboard)
コード例 #12
0
async def next_post_inline(client, callback):
    key = callback.inline_message_id
    iterator: InlinePostsIterator = inline_cached_posts.get(key)

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    profile_userid: List[Profile, int] = inline_cached_profiles.get(key)

    if profile_userid is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    right_user_id = profile_userid[1]

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    if iterator is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    post = iterator.next()

    if post == "Fail":
        await callback.answer(get_message(language, "errors/fail"),
                              show_alert=True)
        return

    await callback.answer()

    caption = create_caption_posts(post.caption,
                                   post.taken_at,
                                   post.views,
                                   post.is_video,
                                   link=post.source)

    keyboard = create_keyboard_posts_from_inline(post.likes,
                                                 post.comment_number,
                                                 len(iterator.collection),
                                                 language)

    await client.edit_inline_text(key, caption, reply_markup=keyboard)
コード例 #13
0
def create_keyboard_profile(username: str, language: str, is_private: bool = False) -> InlineKeyboardMarkup:
    keyboard = []

    if not is_private:
        keyboard.append([
            InlineKeyboardButton(get_message(language, "posts/view"), callback_data=f"open-posts {username}"),
            InlineKeyboardButton(get_message(language, "stories/view"),
                                 callback_data=f"open-stories {username}")
        ])

    keyboard.append([
        InlineKeyboardButton(get_message(language, "keyboards/view_online"),
                             url=f"https://www.instagram.com/{username}")
    ])

    return InlineKeyboardMarkup(keyboard)
コード例 #14
0
def profiles_not_found(language: str) -> InlineQueryResultArticle:
    return InlineQueryResultArticle(
        title=
        f'{emoji.CROSS_MARK} {get_message(language, "inline/no_profiles_found")}!',
        description=get_message(language, "inline/change_query"),
        input_message_content=InputTextMessageContent(
            message_text=
            f'{emoji.CROSS_MARK} <b>{get_message(language, "inline/no_profiles_found")}</b>'
        ))
コード例 #15
0
async def on_profile(_, message, username: str = None):
    if username is None:
        username = '******'.join(message.command[1:])

    language = get_language(message.from_user.id,
                            message.from_user.language_code)

    user = get_user_id(username)

    wait_message = await message.reply_text(get_message(language, "loading"))

    if "user_id" not in user:
        await message.reply_text(
            get_message(language, "errors/non_existent_profile"))
        return

    profile = get_email_and_details(user["user_id"])

    if profile == "error":
        await message.reply_text(
            get_message(language, "errors/non_existent_profile"))
        return

    right_user_id = message.from_user.id

    caption = create_caption_profile(profile, language)

    keyboard = create_keyboard_profile(profile.username, language,
                                       profile.is_private)

    try:
        await wait_message.delete()
    except:
        pass

    message = await message.reply_photo(profile.profile_pic,
                                        caption=caption,
                                        reply_markup=keyboard)

    key = f"{message.chat.id}_{message.message_id}"

    cached_profiles[key] = profile
    cached_ids[key] = right_user_id
コード例 #16
0
async def select_language(_, callback):
    await callback.answer()

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    keyboard = create_languages_keyboard(language)

    await callback.edit_message_text(get_message(language,
                                                 "languages/choose_language"),
                                     reply_markup=keyboard)
コード例 #17
0
async def on_inline_query(_, query: InlineQuery):
    to_search = query.query

    profile_list = search(to_search)

    inline_query_results = []

    language = get_language(query.from_user.id)

    if profile_list != "nothing_found":
        if len(profile_list) > 30:
            profile_list = profile_list[:30]

        for profile in profile_list:
            id = str(uuid4())
            title = profile.username
            if profile.is_verified:
                title += f" {emoji.CHECK_MARK_BUTTON}"

            new_result = InlineQueryResultArticle(
                title=title,
                id=id,
                thumb_url=profile.profile_pic,
                description=profile.full_name or None,
                input_message_content=InputTextMessageContent(
                    message_text=get_message(language, "loading")),
                reply_markup=InlineKeyboardMarkup([[
                    InlineKeyboardButton(
                        get_message(language, "loading"),
                        url=f"https://www.instagram.com/{profile.username}")
                ]]))

            CACHE[id] = [profile.username, language]

            inline_query_results.append(new_result)

    else:
        inline_query_results.append(profiles_not_found(language))

    await query.answer(inline_query_results, cache_time=0)
コード例 #18
0
async def random_story_inline(client, callback):
    key = callback.inline_message_id

    iterator: InlineStoriesIterator = inline_cached_stories.get(key)

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    profile_userid: List[Profile, int] = inline_cached_profiles.get(key)

    if profile_userid is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    right_user_id = profile_userid[1]

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, "errors/wrong_id"),
                              show_alert=True)
        return

    if iterator is None:
        await callback.answer(get_message(language, "errors/not_cached_post"),
                              show_alert=True)
        await client.edit_inline_text(key, "@instaStalkieBot", reply_markup="")
        return

    await callback.answer()

    story = iterator.random()

    caption = f"<a href='{story.url}'>{format_date(story.taken_at)}</a>"

    keyboard = create_keyboard_stories_from_inline(len(iterator.collection),
                                                   language)

    await client.edit_inline_text(key, caption, reply_markup=keyboard)
コード例 #19
0
async def on_languages(_, message):
    language = get_language(message.from_user.id,
                            message.from_user.language_code)

    if message.chat.type == "private":
        text = get_message(language, 'languages/click_to_choose')

        keyboard = InlineKeyboardMarkup([[
            InlineKeyboardButton(
                f"{get_flag(language)} {get_message(language, 'languages/language')}",
                callback_data="open_languages_menu")
        ]])

    else:
        text = get_message(language, 'languages/redirect_text')

        keyboard = InlineKeyboardMarkup([[
            InlineKeyboardButton(
                emoji.LOCKED,
                url="https://t.me/instaStalkieBot?start=languages")
        ]])

    await message.reply_text(text, reply_markup=keyboard)
コード例 #20
0
async def languages_back(_, callback):
    await callback.answer()

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    keyboard = InlineKeyboardMarkup([[
        InlineKeyboardButton(
            f"{get_flag(language)} {get_message(language, 'languages/language')}",
            callback_data="open_languages_menu")
    ]])

    await callback.edit_message_text(get_message(language,
                                                 'languages/click_to_choose'),
                                     reply_markup=keyboard)
コード例 #21
0
async def on_chosen_inline_result(client, chosen_result: ChosenInlineResult):
    id = chosen_result.result_id
    message_id = chosen_result.inline_message_id

    cached = CACHE.get(str(id))

    username = cached[0]
    language = cached[1]

    profile_id = get_user_id(username)

    if "username" not in profile_id:
        await client.edit_inline_text(message_id,
                                      get_message(language, "errors/fail"))
        return

    profile: Profile = get_email_and_details(profile_id["user_id"])

    if profile == "error":
        await client.edit_inline_text(message_id,
                                      get_message(language, "errors/fail"))
        return

    caption = create_caption_profile(profile, language, use_link=True)

    keyboard = create_keyboard_profile_from_inline(profile.username, language,
                                                   profile.is_private)

    await client.edit_inline_text(message_id,
                                  caption,
                                  disable_web_page_preview=False,
                                  reply_markup=keyboard)

    key = chosen_result.inline_message_id

    inline_cached_profiles[key] = [profile, chosen_result.from_user.id]
コード例 #22
0
async def on_start(_, message):
    argument = " ".join(
        message.command[1:]) if len(message.command) > 1 else ""

    if "profile" in argument:
        username = argument[len("profile"):]

        await on_profile(_, message, username)
        return

    if argument == "languages":
        await on_languages(_, message)

    elif message.chat.type == "private":
        language = get_language(message.from_user.id,
                                message.from_user.language_code)

        text = get_message(language, "menu")

        await message.reply_text('\n'.join(text))
コード例 #23
0
def create_caption_likes(likes_json: List[dict], language: str) -> str:
    if len(likes_json) <= 0:
        like_string = f"{get_message(language, 'keyboards/no_likes')} {emoji.CRYING_FACE}"

    else:
        like_string = get_message(language, "profile/liked_from") + ":\n"
        len_comment = len(like_string)
        first_iteration = True

        for like_json in likes_json:
            user = like_json["node"]["username"]
            new_like = f'<b><a href="https://t.me/instaStalkieBot?start=profile{user}">@{user}</a></b>'

            if not first_iteration:
                new_like = f'\n{new_like}'
            else:
                first_iteration = False

            len_comment += len(new_like)

            if len_comment <= 1000:
                like_string += new_like

    return like_string
コード例 #24
0
async def open_stories(_, callback):
    username = callback.data.split(' ')[1]

    language = get_language(callback.from_user.id,
                            callback.from_user.language_code)

    key = f"{callback.message.chat.id}_{callback.message.message_id}"

    profile: Profile = cached_profiles.get(key)
    right_user_id = cached_ids.get(key)

    if profile is None or right_user_id is None:
        await callback.answer(get_message(language, "errors/no_cached_post"),
                              show_alert=True)
        await callback.edit_message_text("", reply_markup="")
        return

    if callback.from_user.id != right_user_id:
        await callback.answer(get_message(language, 'errors/wrong_id'),
                              show_alert=True)
        return

    iterator: StoriesIterator = cached_stories.get(key)

    if iterator is None:
        user = get_user_id(username)

        if "username" not in user:
            await callback.answer(get_message(language, "errors/fail"))
            return

        stories = _request_story(user["user_id"])

        if stories == "private_account":
            await callback.answer(
                get_message(language, "errors/private_account"))
            return

        if stories == "no_stories":
            await callback.answer(get_message(language, "errors/no_stories"))
            return

        iterator = StoriesIterator(stories, username)

        cached_stories[key] = iterator

    await callback.answer()

    story: Story = iterator.next(
    ) if iterator.index != -1 else iterator.collection[iterator.index]

    caption = format_date(story.taken_at)

    keyboard = create_keyboard_stories(iterator.username,
                                       len(iterator.collection),
                                       language,
                                       from_profile=True)

    media = InputMediaVideo(
        story.url
    ) if story.type_story == "mp4/video/boomerang" else InputMediaPhoto(
        story.url)
    media.caption = caption

    await callback.edit_message_media(media, reply_markup=keyboard)