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
Example #2
0
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
Example #4
0
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)
Example #5
0
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}\"."
Example #7
0
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
Example #8
0
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
    )
Example #9
0
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
Example #10
0
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()
Example #14
0
 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
Example #15
0
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()
Example #16
0
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()
Example #17
0
 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
Example #18
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")
Example #21
0
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,
                                                       [])
Example #22
0
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
Example #25
0
 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
Example #26
0
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
Example #27
0
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}/"
    )
Example #28
0
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])
Example #29
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)
Example #30
0
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"