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)
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
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)
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
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)
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
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)
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)
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
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)
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)
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)
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)
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>' ))
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
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)
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)
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)
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)
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)
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]
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))
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
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)