def test_user_favourites(context): post_id1 = 234563 post_id2 = 393282 username = "******" update = MockTelegramUpdate.with_inline_query( query=f"favourites:{username}") submission1 = MockSubmission(post_id1) submission2 = MockSubmission(post_id2) inline = InlineFunctionality(MockExportAPI()) inline.api.with_user_favs(username, [submission1, submission2]) inline.call(update, context) context.bot.answer_inline_query.assert_called_once() args = context.bot.answer_inline_query.call_args[0] assert context.bot.answer_inline_query.call_args[1][ 'next_offset'] == submission2.fav_id assert args[0] == update.inline_query.id assert isinstance(args[1], list) assert len(args[1]) == 2 assert isinstance(args[1][0], InlineQueryResultPhoto) assert isinstance(args[1][1], InlineQueryResultPhoto) assert args[1][0].id == str(post_id1) assert args[1][1].id == str(post_id2) assert args[1][0].photo_url == submission1.thumbnail_url assert args[1][1].photo_url == submission2.thumbnail_url assert args[1][0].thumb_url == FASubmission.make_thumbnail_smaller( submission1.thumbnail_url) assert args[1][1].thumb_url == FASubmission.make_thumbnail_smaller( submission2.thumbnail_url) assert args[1][0].caption == submission1.link assert args[1][1].caption == submission2.link
def test_search_with_spaces(context): search_term = "deer YCH" update = MockTelegramUpdate.with_inline_query(query=search_term) post_id1 = 213231 post_id2 = 84331 submission1 = MockSubmission(post_id1) submission2 = MockSubmission(post_id2) inline = InlineFunctionality(MockExportAPI()) inline.api.with_search_results(search_term, [submission1, submission2]) inline.call(update, context) context.bot.answer_inline_query.assert_called_once() args = context.bot.answer_inline_query.call_args[0] assert context.bot.answer_inline_query.call_args[1]['next_offset'] == 2 assert args[0] == update.inline_query.id assert isinstance(args[1], list) assert len(args[1]) == 2 for result in args[1]: assert isinstance(result, InlineQueryResultPhoto) assert args[1][0].id == str(post_id1) assert args[1][1].id == str(post_id2) assert args[1][0].photo_url == submission1.thumbnail_url assert args[1][1].photo_url == submission2.thumbnail_url assert args[1][0].thumb_url == FASubmission.make_thumbnail_smaller( submission1.thumbnail_url) assert args[1][1].thumb_url == FASubmission.make_thumbnail_smaller( submission2.thumbnail_url) assert args[1][0].caption == submission1.link assert args[1][1].caption == submission2.link
def test_continue_from_fav_id(context): post_id = 234563 fav_id = "354233" username = "******" update = MockTelegramUpdate.with_inline_query(query=f"favs:{username}", offset=fav_id) submission = MockSubmission(post_id) inline = InlineFunctionality(MockExportAPI()) inline.api.with_user_favs(username, [submission], next_id=fav_id) inline.call(update, context) context.bot.answer_inline_query.assert_called_once() args = context.bot.answer_inline_query.call_args[0] assert context.bot.answer_inline_query.call_args[1][ 'next_offset'] == submission.fav_id assert args[0] == update.inline_query.id assert isinstance(args[1], list) assert len(args[1]) == 1 assert isinstance(args[1][0], InlineQueryResultPhoto) assert args[1][0].id == str(post_id) assert args[1][0].photo_url == submission.thumbnail_url assert args[1][0].thumb_url == FASubmission.make_thumbnail_smaller( submission.thumbnail_url) assert args[1][0].caption == submission.link
def test_submission_link_and_different_direct_link(context): username = "******" image_id1 = 1560331512 image_id2 = image_id1 + 300 post_id1 = 232347 post_id2 = 233447 update = MockTelegramUpdate.with_message( text="https://furaffinity.net/view/{2}/ http://d.facdn.net/art/{0}/{1}/{1}.pic_of_me.png".format( username, image_id1, post_id2 ) ) submission1 = MockSubmission(post_id1, image_id=image_id1) submission2 = MockSubmission(post_id2, image_id=image_id2) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_user_folder(username, "gallery", [ submission2, submission1, MockSubmission(post_id1 - 1, image_id=image_id1 - 15) ]) neaten.call(update, context) context.bot.send_photo.assert_called() calls = [call( chat_id=update.message.chat_id, photo=submission.download_url, caption=submission.link, reply_to_message_id=update.message.message_id ) for submission in [submission2, submission1]] context.bot.send_photo.assert_has_calls(calls)
def test_direct_no_match_groupchat(context): username = "******" image_id = 1560331512 post_id = 232347 update = MockTelegramUpdate.with_message( text="http://d.facdn.net/art/{0}/{1}/{1}.pic_of_me.png".format(username, image_id), chat_type=Chat.GROUP ) neaten = NeatenFunctionality(MockExportAPI()) for folder in ['gallery', 'scraps']: neaten.api.with_user_folder(username, folder, [ MockSubmission(post_id, image_id=image_id + 4), MockSubmission(post_id - 1, image_id=image_id - 15) ]) neaten.call(update, context) context.bot.send_photo.assert_not_called() context.bot.send_message.assert_called_with( chat_id=update.message.chat_id, text="⏳ Neatening image link", reply_to_message_id=update.message.message_id ) context.bot.delete_message.assert_called_with( update.message.chat_id, context._sent_message_ids[0] )
def test_username_with_colon(context, requests_mock): # FA doesn't allow usernames to have : in them username = "******" update = MockTelegramUpdate.with_inline_query(query=f"gallery:{username}") inline = InlineFunctionality(MockExportAPI()) # mock export api doesn't do non-existent users, so mocking with requests inline.api = FAExportAPI("http://example.com") requests_mock.get( f"http://example.com/user/{username}/gallery.json", status_code=404 ) inline.call(update, context) context.bot.answer_inline_query.assert_called_once() args = context.bot.answer_inline_query.call_args[0] assert context.bot.answer_inline_query.call_args[1]['next_offset'] == "" assert args[0] == update.inline_query.id assert isinstance(args[1], list) assert len(args[1]) == 1 assert isinstance(args[1][0], InlineQueryResultArticle) assert args[1][0].title == "User does not exist." assert isinstance(args[1][0].input_message_content, InputMessageContent) assert args[1][0].input_message_content.message_text == \ f"FurAffinity user does not exist by the name: \"{username}\"."
def test_result_first_on_page(context): username = "******" image_id = 1560331512 post_id = 232347 update = MockTelegramUpdate.with_message( text="http://d.facdn.net/art/{0}/{1}/{1}.pic_of_me.png".format(username, image_id) ) submission = MockSubmission(post_id, image_id=image_id) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_user_folder(username, "gallery", [ MockSubmission(post_id + 3, image_id=image_id + 16), MockSubmission(post_id + 2, image_id=image_id + 8) ], page=1) neaten.api.with_user_folder(username, "gallery", [ submission, MockSubmission(post_id - 2, image_id=image_id - 2), MockSubmission(post_id - 7, image_id=image_id - 4), MockSubmission(post_id - 9, image_id=image_id - 10) ], page=2) neaten.call(update, context) context.bot.send_photo.assert_called_once() assert context.bot.send_photo.call_args[1]['chat_id'] == update.message.chat_id assert context.bot.send_photo.call_args[1]['photo'] == submission.download_url assert context.bot.send_photo.call_args[1]['caption'] == submission.link assert context.bot.send_photo.call_args[1]['reply_to_message_id'] == update.message.message_id
def test_result_missing_between_pages(context): username = "******" image_id = 1560331512 post_id = 232347 update = MockTelegramUpdate.with_message( text="http://d.facdn.net/art/{0}/{1}/{1}.pic_of_me.png".format(username, image_id) ) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_user_folder(username, "gallery", [ MockSubmission(post_id + 1, image_id=image_id + 16), MockSubmission(post_id, image_id=image_id + 3) ], page=1) neaten.api.with_user_folder(username, "gallery", [ MockSubmission(post_id - 2, image_id=image_id - 27), MockSubmission(post_id - 3, image_id=image_id - 34) ], page=2) neaten.call(update, context) context.bot.send_photo.assert_not_called() context.bot.send_message.assert_called_with( chat_id=update.message.chat_id, text="Could not locate the image by {} with image id {}.".format(username, image_id), reply_to_message_id=update.message.message_id )
def test_result_in_scraps(context): username = "******" image_id = 1560331512 post_id = 232347 update = MockTelegramUpdate.with_message( text="http://d.facdn.net/art/{0}/{1}/{1}.pic_of_me.png".format(username, image_id) ) submission = MockSubmission(post_id, image_id=image_id) neaten = NeatenFunctionality(MockExportAPI()) for page in [1, 2]: neaten.api.with_user_folder(username, "gallery", [ MockSubmission(post_id + 1 + (3 - page) * 5, image_id=image_id + 16 + (3 - page) * 56), MockSubmission(post_id + (3 - page) * 5, image_id=image_id + (3 - page) * 56), MockSubmission(post_id - 2 + (3 - page) * 5, image_id=image_id - 27 + (3 - page) * 56), MockSubmission(post_id - 3 + (3 - page) * 5, image_id=image_id - 34 + (3 - page) * 56) ], page=page) neaten.api.with_user_folder(username, "gallery", [], page=3) neaten.api.with_user_folder(username, "scraps", [ MockSubmission(post_id + 1, image_id=image_id + 16), submission, MockSubmission(post_id - 2, image_id=image_id - 27), MockSubmission(post_id - 3, image_id=image_id - 34) ], page=1) neaten.call(update, context) context.bot.send_photo.assert_called_once() assert context.bot.send_photo.call_args[1]['chat_id'] == update.message.chat_id assert context.bot.send_photo.call_args[1]['photo'] == submission.download_url assert context.bot.send_photo.call_args[1]['caption'] == submission.link assert context.bot.send_photo.call_args[1]['reply_to_message_id'] == update.message.message_id
def test_direct_in_progress_message(context): username = "******" image_id = 1560331512 post_id = 232347 update = MockTelegramUpdate.with_message( text="http://d.facdn.net/art/{0}/{1}/{1}.pic_of_me.png".format(username, image_id) ) goal_submission = MockSubmission(post_id, image_id=image_id) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_user_folder(username, "gallery", [ goal_submission, MockSubmission(post_id - 1, image_id=image_id - 15) ]) neaten.call(update, context) context.bot.send_message.assert_called_with( chat_id=update.message.chat_id, text="⏳ Neatening image link", reply_to_message_id=update.message.message_id ) context.bot.delete_message.assert_called_with( update.message.chat_id, context._sent_message_ids[0] )
def test_over_48_favs(context): username = "******" post_ids = list(range(123456, 123456 + 72)) submissions = [MockSubmission(x) for x in post_ids] inline = InlineFunctionality(MockExportAPI()) inline.api.with_user_favs(username, submissions) update = MockTelegramUpdate.with_inline_query(query=f"favs:{username}") inline.call(update, context) context.bot.answer_inline_query.assert_called_once() args = context.bot.answer_inline_query.call_args[0] assert context.bot.answer_inline_query.call_args[1][ 'next_offset'] == submissions[47].fav_id assert args[0] == update.inline_query.id assert isinstance(args[1], list) assert len(args[1]) == 48 assert isinstance(args[1][0], InlineQueryResultPhoto) assert isinstance(args[1][1], InlineQueryResultPhoto) for x in range(48): assert args[1][x].id == str(post_ids[x]) assert args[1][x].photo_url == submissions[x].thumbnail_url assert args[1][x].thumb_url == FASubmission.make_thumbnail_smaller( submissions[x].thumbnail_url) assert args[1][x].caption == submissions[x].link
def test_no_username_set(context, requests_mock): username = "" update = MockTelegramUpdate.with_inline_query(query=f"favs:{username}") inline = InlineFunctionality(MockExportAPI()) # mock export api doesn't do non-existent users, so mocking with requests inline.api = FAExportAPI("http://example.com") requests_mock.get( f"http://example.com/user/{username}/favorites.json?page=1&full=1", json={ "id": None, "name": "favorites", "profile": "https://www.furaffinity.net/user/favorites/" }) inline.call(update, context) context.bot.answer_inline_query.assert_called_once() args = context.bot.answer_inline_query.call_args[0] assert context.bot.answer_inline_query.call_args[1]['next_offset'] == "" assert args[0] == update.inline_query.id assert isinstance(args[1], list) assert len(args[1]) == 1 assert isinstance(args[1][0], InlineQueryResultArticle) assert args[1][0].title == "User does not exist." assert isinstance(args[1][0].input_message_content, InputMessageContent) assert args[1][0].input_message_content.message_text == \ f"FurAffinity user does not exist by the name: \"{username}\"."
def test_no_reply_in_group(context): update = MockTelegramUpdate.with_message( text=None, chat_type=Chat.GROUP).with_photo() func = ImageHashRecommendFunctionality() func.call(update, context) context.bot.send_message.assert_not_called()
def test_can_create_callback_with_message(self): update = MockTelegramUpdate.with_callback_query( ).with_originating_message() assert update.message is None assert update.callback_query is not None assert update.callback_query.message is not None assert update.callback_query.message.message_id is not None assert update.callback_query.message.chat_id is not None
def test_ignore_message(context): update = MockTelegramUpdate.with_message(text="hello world") neaten = NeatenFunctionality(MockExportAPI()) neaten.call(update, context) context.bot.send_message.assert_not_called() context.bot.send_photo.assert_not_called()
def test_ignore_journal_link(context): update = MockTelegramUpdate.with_message(text="https://www.furaffinity.net/journal/9150534/") neaten = NeatenFunctionality(MockExportAPI()) neaten.call(update, context) context.bot.send_message.assert_not_called() context.bot.send_photo.assert_not_called()
def test_can_create_message(self): update = MockTelegramUpdate.with_message() assert update.callback_query is None assert update.message is not None assert update.message.message_id is not None assert update.message.chat_id is not None assert isinstance(update.message.photo, list) assert len(update.message.photo) == 0
def test_ignore_link(context): update = MockTelegramUpdate.with_message(text="http://example.com") neaten = NeatenFunctionality(MockExportAPI()) neaten.call(update, context) context.bot.send_message.assert_not_called() context.bot.send_photo.assert_not_called()
def test_unhandled_group_message(context): update = MockTelegramUpdate.with_message(text="Hey friendo, how are you?", chat_type=Chat.GROUP) unhandled = UnhandledMessageFunctionality() unhandled.call(update, context) context.bot.send_message.assert_not_called()
def test_unhandled_message(context): update = MockTelegramUpdate.with_message(text="Hello can I have a picture") unhandled = UnhandledMessageFunctionality() unhandled.call(update, context) context.bot.send_message.assert_called_with( chat_id=update.message.chat_id, text="Sorry, I'm not sure how to handle that message")
def test_empty_query_no_results(context): update = MockTelegramUpdate.with_inline_query(query="") inline = InlineFunctionality(MockExportAPI()) inline.call(update, context) context.bot.send_message.assert_not_called() context.bot.send_photo.assert_not_called() context.bot.answer_inline_query.assert_called_with(update.inline_query.id, [])
def test_beep(context): update = MockTelegramUpdate.with_command() beep = BeepFunctionality() beep.call(update, context) context.bot.send_message.assert_called() assert context.bot.send_message.call_args[1][ 'chat_id'] == update.message.chat_id assert context.bot.send_message.call_args[1]['text'] == "boop"
def test_doesnt_fire_on_avatar(context): update = MockTelegramUpdate.with_message( text="https://a.facdn.net/1538326752/geordie79.gif") neaten = NeatenFunctionality(MockExportAPI()) neaten.call(update, context) context.bot.send_photo.assert_not_called() context.bot.send_document.assert_not_called() context.bot.send_message.assert_not_called() context.bot.send_audio.assert_not_called()
def test_sends_recommendation(context): update = MockTelegramUpdate.with_message(text=None).with_photo() func = ImageHashRecommendFunctionality() func.call(update, context) context.bot.send_message.assert_called() assert context.bot.send_message.call_args[1][ 'chat_id'] == update.message.chat_id message_text = context.bot.send_message.call_args[1]['text'] assert "@FindFurryPicBot" in message_text
def test_can_create_message_with_document(self): update = MockTelegramUpdate.with_message().with_document() assert update.callback_query is None assert update.message is not None assert update.message.message_id is not None assert update.message.chat_id is not None assert isinstance(update.message.photo, list) assert len(update.message.photo) == 0 assert update.message.document is not None assert isinstance(update.message.document, _MockDocument) assert update.message.document.file_id is not None assert update.message.document.mime_type is None
def test_welcome_message(context): update = MockTelegramUpdate.with_command() func = WelcomeFunctionality() func.call(update, context) context.bot.send_message.assert_called() assert context.bot.send_message.call_args[1][ 'chat_id'] == update.message.chat_id message_text = context.bot.send_message.call_args[1]['text'] assert "@deerspangle" in message_text assert "https://github.com/Deer-Spangle/FA-search-bot" in message_text assert FASearchBot.VERSION in message_text
def test_deleted_submission(context): post_id = 23636984 update = MockTelegramUpdate.with_message( text="furaffinity.net/view/{}".format(post_id)) neaten = NeatenFunctionality(MockExportAPI()) neaten.call(update, context) context.bot.send_photo.assert_not_called() context.bot.send_message.assert_called_with( chat_id=update.message.chat_id, reply_to_message_id=update.message.message_id, text= f"This doesn't seem to be a valid FA submission: https://www.furaffinity.net/view/{post_id}/" )
def test_deleted_submission_group_chat(context): post_id = 23636984 update = MockTelegramUpdate.with_message( text="furaffinity.net/view/{}".format(post_id), chat_type=Chat.GROUP) neaten = NeatenFunctionality(MockExportAPI()) neaten.call(update, context) context.bot.send_photo.assert_not_called() context.bot.send_message.assert_called_with( chat_id=update.message.chat_id, text="⏳ Neatening image link", reply_to_message_id=update.message.message_id) context.bot.delete_message.assert_called_with(update.message.chat_id, context._sent_message_ids[0])
def test_mp3_submission(context): post_id = 23636984 update = MockTelegramUpdate.with_message( text="https://www.furaffinity.net/view/{}/".format(post_id)) submission = MockSubmission(post_id, file_ext="mp3") neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_submission(submission) neaten.call(update, context) context.bot.send_audio.assert_called_with( chat_id=update.message.chat_id, audio=submission.download_url, caption=submission.link, reply_to_message_id=update.message.message_id)
def test_call__route_list_subscriptions(context): update = MockTelegramUpdate.with_message(chat_id=14358, text="/list_subscriptions") api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) func = SubscriptionFunctionality(watcher) list_subs = MockMethod("Listing subscriptions") func._list_subs = list_subs.call func.call(update, context) assert list_subs.called assert list_subs.args is not None assert list_subs.args[0] == 14358 context.bot.send_message.assert_called() assert context.bot.send_message.call_args[1]['chat_id'] == update.message.chat_id assert context.bot.send_message.call_args[1]['text'] == "Listing subscriptions"