async def test_result_missing_between_pages(mock_client): username = "******" image_id = 1560331512 post_id = 232347 event = MockTelegramEvent.with_message( text="http://d.furaffinity.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) with pytest.raises(StopPropagation): await neaten.call(event) event.reply.assert_called_with( f"Error finding submission: Could not locate the image by {username} with image id {image_id}.", )
async def test_result_last_on_page(mock_client): username = "******" image_id = 1560331512 post_id = 232347 event = MockTelegramEvent.with_message( text="http://d.furaffinity.net/art/{0}/{1}/{1}.pic_of_me.png".format( username, image_id), client=mock_client, ) submission = MockSubmission(post_id, image_id=image_id) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_user_folder(username, "gallery", [ MockSubmission(post_id + 4, image_id=image_id + 16), MockSubmission(post_id + 3, image_id=image_id + 2), MockSubmission(post_id + 2, image_id=image_id + 1), submission ]) with pytest.raises(StopPropagation): await neaten.call(event) submission._send_message.assert_called_once() args, kwargs = submission._send_message.call_args assert args[0] == mock_client assert args[1] == event.input_chat assert kwargs['reply_to'] == event.message.id
async def test_result_on_third_page(mock_client): username = "******" image_id = 1560331512 post_id = 232347 event = MockTelegramEvent.with_message( text="http://d.furaffinity.net/art/{0}/{1}/{1}.pic_of_me.png".format( username, image_id), client=mock_client, ) neaten = NeatenFunctionality(MockExportAPI()) for page in [1, 2, 3]: 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) submission = await neaten.api.get_full_submission(str(post_id)) with pytest.raises(StopPropagation): await neaten.call(event) submission._send_message.assert_called_once() args, kwargs = submission._send_message.call_args assert args[0] == mock_client assert args[1] == event.input_chat assert kwargs['reply_to'] == event.message.id
async def test_over_max_submissions_continue_end(mock_client): username = "******" posts = 72 post_ids = list(range(123456, 123456 + posts)) submissions = [MockSubmission(x) for x in post_ids] mock_api = MockExportAPI() mock_api.with_user_folder(username, "gallery", submissions) inline = InlineFunctionality(mock_api) skip = posts - inline.INLINE_MAX + 3 event = MockTelegramEvent.with_inline_query(query=f"gallery:{username}", offset=f"1:{skip}") with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args = event.answer.call_args[0] assert event.answer.call_args[1]['next_offset'] == "2" assert event.answer.call_args[1]['gallery'] is True assert isinstance(args[0], list) assert len(args[0]) == inline.INLINE_MAX - 3 assert isinstance(args[0][0], _MockInlineBuilder._MockInlinePhoto) assert isinstance(args[0][1], _MockInlineBuilder._MockInlinePhoto) for x in range(inline.INLINE_MAX - 3): assert args[0][x].kwargs['file'] == submissions[x + skip].thumbnail_url assert args[0][x].kwargs['id'] == str(post_ids[x + skip]) assert args[0][x].kwargs['text'] == submissions[x + skip].link assert len(args[0][x].kwargs['buttons']) == 1 assert args[0][x].kwargs['buttons'][ 0].data == f"neaten_me:{submissions[x + skip].submission_id}".encode( )
async def test_direct_link_and_matching_submission_link(mock_client): username = "******" image_id = 1560331512 post_id = 232347 event = MockTelegramEvent.with_message( text= "http://d.furaffinity.net/art/{0}/{1}/{1}.pic_of_me.png https://furaffinity.net/view/{2}/" .format(username, image_id, post_id), client=mock_client, ) submission = MockSubmission(post_id, image_id=image_id) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_user_folder( username, "gallery", [submission, MockSubmission(post_id - 1, image_id=image_id - 15)]) with pytest.raises(StopPropagation): await neaten.call(event) submission._send_message.assert_called_once() args, kwargs = submission._send_message.call_args assert args[0] == mock_client assert args[1] == event.input_chat assert kwargs['reply_to'] == event.message.id
async def test_search_with_spaces(mock_client): search_term = "deer YCH" event = MockTelegramEvent.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]) with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args = event.answer.call_args[0] assert event.answer.call_args[1]['next_offset'] == "2" assert event.answer.call_args[1]['gallery'] is True assert isinstance(args[0], list) assert len(args[0]) == 2 for result in args[0]: assert isinstance(result, _MockInlineBuilder._MockInlinePhoto) assert args[0][0].kwargs['file'] == submission1.thumbnail_url assert args[0][0].kwargs['id'] == str(post_id1) assert args[0][0].kwargs['text'] == submission1.link assert len(args[0][0].kwargs['buttons']) == 1 assert args[0][0].kwargs['buttons'][ 0].data == f"neaten_me:{submission1.submission_id}".encode() assert args[0][1].kwargs['file'] == submission2.thumbnail_url assert args[0][1].kwargs['id'] == str(post_id2) assert args[0][1].kwargs['text'] == submission2.link assert len(args[0][1].kwargs['buttons']) == 1 assert args[0][1].kwargs['buttons'][ 0].data == f"neaten_me:{submission2.submission_id}".encode()
async def test_over_max_favs(mock_client): 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) event = MockTelegramEvent.with_inline_query(query=f"favs:{username}") with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args = event.answer.call_args[0] assert event.answer.call_args[1]['next_offset'] == submissions[ inline.INLINE_MAX - 1].fav_id assert event.answer.call_args[1]['gallery'] is True assert isinstance(args[0], list) assert len(args[0]) == inline.INLINE_MAX assert isinstance(args[0][0], _MockInlineBuilder._MockInlinePhoto) assert isinstance(args[0][1], _MockInlineBuilder._MockInlinePhoto) for x in range(inline.INLINE_MAX): assert args[0][x].kwargs['file'] == submissions[x].thumbnail_url assert args[0][x].kwargs['id'] == str(post_ids[x]) assert args[0][x].kwargs['text'] == submissions[x].link assert len(args[0][x].kwargs['buttons']) == 1 assert args[0][x].kwargs['buttons'][ 0].data == f"neaten_me:{submissions[x].submission_id}".encode()
async def test_search_with_offset(mock_client): post_id = 234563 search_term = "YCH" offset = 2 event = MockTelegramEvent.with_inline_query(query=search_term, offset=offset) submission = MockSubmission(post_id) inline = InlineFunctionality(MockExportAPI()) inline.api.with_search_results(search_term, [submission], page=offset) with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args = event.answer.call_args[0] assert isinstance(args[0], list) assert len(args[0]) > 0 for result in args[0]: assert isinstance(result, _MockInlineBuilder._MockInlinePhoto) assert result.kwargs['file'] == submission.thumbnail_url assert result.kwargs['id'] == str(post_id) assert result.kwargs['text'] == submission.link assert len(result.kwargs['buttons']) == 1 assert result.kwargs['buttons'][ 0].data == f"neaten_me:{post_id}".encode()
async def test_submission_direct_link(): post_id = 12345 image_id = 98765434 username = "******" sub = MockSubmission(post_id, username=username, image_id=image_id) event = MockTelegramEvent.with_inline_query(query=sub.download_url) inline = InlineNeatenFunctionality(MockExportAPI().with_user_folder( username, "gallery", [ MockSubmission(12346, image_id=image_id + 50), sub, MockSubmission(12344, image_id=image_id - 50), ])) with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args, kwargs = event.answer.call_args assert isinstance(args[0], list) assert len(args[0]) == 1 assert kwargs['gallery'] is True result = args[0][0] assert isinstance(result, _MockInlineBuilder._MockInlinePhoto) assert result.kwargs['file'] == sub.thumbnail_url assert result.kwargs['id'] == str(post_id) assert result.kwargs['text'] == sub.link assert len(result.kwargs['buttons']) == 1 assert result.kwargs['buttons'][0].data == f"neaten_me:{post_id}".encode()
async def test_submission_link_and_different_direct_link(mock_client): username = "******" image_id1 = 1560331512 image_id2 = image_id1 + 300 post_id1 = 232347 post_id2 = 233447 event = MockTelegramEvent.with_message( text= "https://furaffinity.net/view/{2}/ http://d.furaffinity.net/art/{0}/{1}/{1}.pic_of_me.png" .format(username, image_id1, post_id2), client=mock_client) 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) ]) with pytest.raises(StopPropagation): await neaten.call(event) submission1._send_message.assert_called_once() args1, kwargs1 = submission1._send_message.call_args assert args1[0] == mock_client assert args1[1] == event.input_chat assert kwargs1['reply_to'] == event.message.id submission2._send_message.assert_called_once() args2, kwargs2 = submission2._send_message.call_args assert args2[0] == mock_client assert args2[1] == event.input_chat assert kwargs2['reply_to'] == event.message.id
async def test_second_page(mock_client): post_id = 234563 username = "******" event = MockTelegramEvent.with_inline_query(query=f"scraps:{username}", offset="2") submission = MockSubmission(post_id) inline = InlineFunctionality(MockExportAPI()) inline.api.with_user_folder(username, "scraps", [submission], page=2) with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args = event.answer.call_args[0] assert event.answer.call_args[1]['next_offset'] == "3" assert event.answer.call_args[1]['gallery'] is True assert isinstance(args[0], list) assert len(args[0]) == 1 assert isinstance(args[0][0], _MockInlineBuilder._MockInlinePhoto) assert args[0][0].kwargs['file'] == submission.thumbnail_url assert args[0][0].kwargs['id'] == str(post_id) assert args[0][0].kwargs['text'] == submission.link assert len(args[0][0].kwargs['buttons']) == 1 assert args[0][0].kwargs['buttons'][ 0].data == f"neaten_me:{submission.submission_id}".encode()
async def test_two_submission_links(mock_client): post_id1 = 23636984 post_id2 = 23636996 event = MockTelegramEvent.with_message( text="furaffinity.net/view/{}\nfuraffinity.net/view/{}".format( post_id1, post_id2), client=mock_client, ) submission1 = MockSubmission(post_id1) submission2 = MockSubmission(post_id2) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_submissions([submission1, submission2]) with pytest.raises(StopPropagation): await neaten.call(event) submission1._send_message.assert_called_once() args1, kwargs1 = submission1._send_message.call_args assert args1[0] == mock_client assert args1[1] == event.input_chat assert kwargs1['reply_to'] == event.message.id submission2._send_message.assert_called_once() args2, kwargs2 = submission2._send_message.call_args assert args2[0] == mock_client assert args2[1] == event.input_chat assert kwargs2['reply_to'] == event.message.id
async def test_ignore_link(mock_client): event = MockTelegramEvent.with_message(text="http://example.com") neaten = NeatenFunctionality(MockExportAPI()) await neaten.call(event) event.reply.assert_not_called()
async def test_no_username_set(requests_mock): username = "" event = MockTelegramEvent.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", ignore_status=True) requests_mock.get( f"http://example.com/user/{username}/gallery.json?page=1&full=1", json={ "id": None, "name": "gallery", "profile": "https://www.furaffinity.net/user/gallery/" }) with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args = event.answer.call_args[0] assert event.answer.call_args[1]['next_offset'] is None assert event.answer.call_args[1]['gallery'] is False assert isinstance(args[0], list) assert len(args[0]) == 1 assert isinstance(args[0][0], _MockInlineBuilder._MockInlineArticle) assert args[0][0].kwargs == { "title": "User does not exist.", "description": f"FurAffinity user does not exist by the name: \"{username}\".", "text": f"FurAffinity user does not exist by the name: \"{username}\".", }
async def test_ignore_message(mock_client): event = MockTelegramEvent.with_message(text="hello world") neaten = NeatenFunctionality(MockExportAPI()) await neaten.call(event) event.reply.assert_not_called()
async def test_thumb_and_different_submission_link(mock_client): post_id1 = 382632 post_id2 = 382672 event = MockTelegramEvent.with_message( text= f"https://t.furaffinity.net/{post_id1}@1600-1562445328.jpg\nhttps://furaffinity.net/view/{post_id2}", client=mock_client, ) submission1 = MockSubmission(post_id1) submission2 = MockSubmission(post_id2) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_submissions([submission1, submission2]) with pytest.raises(StopPropagation): await neaten.call(event) submission1._send_message.assert_called_once() args1, kwargs1 = submission1._send_message.call_args assert args1[0] == mock_client assert args1[1] == event.input_chat assert kwargs1['reply_to'] == event.message.id submission2._send_message.assert_called_once() args2, kwargs2 = submission2._send_message.call_args assert args2[0] == mock_client assert args2[1] == event.input_chat assert kwargs2['reply_to'] == event.message.id
async def test_username_with_colon(requests_mock): # FA doesn't allow usernames to have : in them username = "******" event = MockTelegramEvent.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", ignore_status=True) requests_mock.get(f"http://example.com/user/{username}/gallery.json", status_code=404) with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args = event.answer.call_args[0] assert event.answer.call_args[1]['next_offset'] is None assert event.answer.call_args[1]['gallery'] is False assert isinstance(args[0], list) assert len(args[0]) == 1 assert isinstance(args[0][0], _MockInlineBuilder._MockInlineArticle) assert args[0][0].kwargs == { "title": "User does not exist.", "description": f"FurAffinity user does not exist by the name: \"{username}\".", "text": f"FurAffinity user does not exist by the name: \"{username}\".", }
async def test_get_user_gallery(mock_client): post_id1 = 234563 post_id2 = 393282 username = "******" event = MockTelegramEvent.with_inline_query(query=f"gallery:{username}") submission1 = MockSubmission(post_id1) submission2 = MockSubmission(post_id2) inline = InlineFunctionality(MockExportAPI()) inline.api.with_user_folder(username, "gallery", [submission1, submission2]) with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_once() args = event.answer.call_args[0] assert event.answer.call_args[1]['next_offset'] == "2" assert event.answer.call_args[1]['gallery'] is True assert isinstance(args[0], list) assert len(args[0]) == 2 assert isinstance(args[0][0], _MockInlineBuilder._MockInlinePhoto) assert isinstance(args[0][1], _MockInlineBuilder._MockInlinePhoto) assert args[0][0].kwargs['file'] == submission1.thumbnail_url assert args[0][0].kwargs['id'] == str(post_id1) assert args[0][0].kwargs['text'] == submission1.link assert len(args[0][0].kwargs['buttons']) == 1 assert args[0][0].kwargs['buttons'][ 0].data == f"neaten_me:{submission1.submission_id}".encode() assert args[0][1].kwargs['file'] == submission2.thumbnail_url assert args[0][1].kwargs['id'] == str(post_id2) assert args[0][1].kwargs['text'] == submission2.link assert len(args[0][1].kwargs['buttons']) == 1 assert args[0][1].kwargs['buttons'][ 0].data == f"neaten_me:{submission2.submission_id}".encode()
async def test_unhandled_group_message(mock_client): event = MockTelegramEvent.with_message(text="Hey friendo, how are you?", chat_type=ChatType.GROUP) unhandled = UnhandledMessageFunctionality() await unhandled.call(event) event.reply.assert_not_called()
def test_can_create_message(self): event = MockTelegramEvent.with_message() assert event.callback_query is None assert event.message is not None assert event.message.message_id is not None assert event.message.chat_id is not None assert isinstance(event.message.photo, list) assert len(event.message.photo) == 0
async def test_ignore_journal_link(mock_client): event = MockTelegramEvent.with_message( text="https://www.furaffinity.net/journal/9150534/") neaten = NeatenFunctionality(MockExportAPI()) await neaten.call(event) event.reply.assert_not_called()
async def test_no_reply_in_group(mock_client): event = MockTelegramEvent.with_message( text=None, chat_type=ChatType.GROUP).with_photo() func = ImageHashRecommendFunctionality() await func.call(event) event.reply.assert_not_called()
async def test_empty_query_no_results(mock_client): event = MockTelegramEvent.with_inline_query(query="") inline = InlineFunctionality(MockExportAPI()) with pytest.raises(StopPropagation): await inline.call(event) event.answer.assert_called_with([])
async def test_unhandled_message(mock_client): event = MockTelegramEvent.with_message(text="Hello can I have a picture") unhandled = UnhandledMessageFunctionality() with pytest.raises(StopPropagation): await unhandled.call(event) event.reply.assert_called_with( "Sorry, I'm not sure how to handle that message", )
async def test_submission_id__no_result(): post_id = 12345 event = MockTelegramEvent.with_inline_query(query=str(post_id)) inline = InlineNeatenFunctionality(MockExportAPI().with_submissions( [MockSubmission(12344), MockSubmission(12346)])) await inline.call(event) event.answer.assert_not_called()
async def test_beep(mock_client): event = MockTelegramEvent.with_message(text="/beep") beep = BeepFunctionality() with pytest.raises(StopPropagation): await beep.call(event) event.respond.assert_called() assert event.respond.call_args[0][0] == "boop"
def test_can_create_callback_with_message(self): event = MockTelegramEvent.with_callback_query(b"data").with_inline_id( 5, 17, 123) assert event.data == b"data" assert event.original_update is not None assert event.original_update.msg_id is not None assert event.original_update.msg_id.dc_id == 5 assert event.original_update.msg_id.id == 17 assert event.original_update.msg_id.access_hash == 123
async def test_doesnt_fire_on_avatar(mock_client): event = MockTelegramEvent.with_message( text="https://a.furaffinity.net/1538326752/geordie79.gif", client=mock_client, ) neaten = NeatenFunctionality(MockExportAPI()) await neaten.call(event) event.reply.assert_not_called()
async def test_query_not_id_or_link(): post_id = 12345 sub = MockSubmission(post_id) event = MockTelegramEvent.with_inline_query(query="test") inline = InlineNeatenFunctionality(MockExportAPI().with_submissions( [MockSubmission(12344), sub, MockSubmission(12346)])) await inline.call(event) event.answer.assert_not_called()
async def test_ignore_channel_post(mock_client): post_id = 23636984 event = MockTelegramEvent.with_channel_post( text=f"https://www.furaffinity.net/view/{post_id}/") submission = MockSubmission(post_id) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_submission(submission) await neaten.call(event) submission._send_message.assert_not_called()