def test_to_json_and_back(mock_client): test_watcher_file = "./test_subscription_watcher.json" if os.path.exists(test_watcher_file): os.remove(test_watcher_file) old_filename = SubscriptionWatcher.FILENAME SubscriptionWatcher.FILENAME = test_watcher_file api = MockExportAPI() latest_submissions = [ SubmissionBuilder(submission_id="123243").build_short_submission(), SubmissionBuilder(submission_id="123242").build_short_submission(), SubmissionBuilder(submission_id="123240").build_short_submission() ] subscription1 = Subscription("query", 1234) subscription2 = Subscription("example", 5678) watcher = SubscriptionWatcher(api, mock_client) watcher._update_latest_ids(latest_submissions) watcher.subscriptions.add(subscription1) watcher.subscriptions.add(subscription2) watcher.blocklists[3452] = {"test", "example"} watcher.blocklists[1453] = {"ych"} try: watcher.save_to_json() new_watcher = SubscriptionWatcher.load_from_json(api, mock_client) assert len(new_watcher.latest_ids) == 3 assert "123243" in new_watcher.latest_ids assert "123242" in new_watcher.latest_ids assert "123240" in new_watcher.latest_ids assert list(watcher.latest_ids) == list(new_watcher.latest_ids) assert len(new_watcher.subscriptions) == 2 list_subs = list(new_watcher.subscriptions) if list_subs[0].query_str == "query": assert list_subs[0].destination == 1234 assert list_subs[1].query_str == "example" assert list_subs[1].destination == 5678 else: assert list_subs[0].query_str == "example" assert list_subs[0].destination == 5678 assert list_subs[1].query_str == "query" assert list_subs[1].destination == 1234 assert len(new_watcher.blocklists) == 2 assert 3452 in new_watcher.blocklists assert len(new_watcher.blocklists[3452]) == 2 assert isinstance(new_watcher.blocklists[3452], set) assert "test" in new_watcher.blocklists[3452] assert "example" in new_watcher.blocklists[3452] assert 1453 in new_watcher.blocklists assert len(new_watcher.blocklists[1453]) == 1 assert isinstance(new_watcher.blocklists[1453], set) assert "ych" in new_watcher.blocklists[1453] finally: SubscriptionWatcher.FILENAME = old_filename os.remove(test_watcher_file)
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()
def test_remove_sub__non_existent_subscription(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) watcher.subscriptions.add(Subscription("example", 18749)) watcher.subscriptions.add(Subscription("test", 18747)) func = SubscriptionFunctionality(watcher) resp = func._remove_sub(18749, "test") assert resp == "There is not a subscription for \"test\" in this chat." assert len(watcher.subscriptions) == 2
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_deleted_submission_group_chat(mock_client): post_id = 23636984 event = MockTelegramEvent.with_message( text="furaffinity.net/view/{}".format(post_id), chat_type=ChatType.GROUP) neaten = NeatenFunctionality(MockExportAPI()) with pytest.raises(StopPropagation): await neaten.call(event) event.reply.assert_called_with("⏳ Neatening image link") event.reply.return_value.delete.assert_called_once()
async def test_send_updates__deleted_pauses_subs(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) subscription = Subscription("test", 12345) watcher.subscriptions.add(subscription) submission = SubmissionBuilder().build_mock_submission() submission.send_message = lambda *args, **kwargs: (_ for _ in ()).throw( InputUserDeactivatedError(None)) await watcher._send_updates([subscription], submission) assert subscription.paused
def test_update_latest_ids(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) id_list = ["1234", "1233", "1230", "1229"] submissions = [MockSubmission(x) for x in id_list] mock_save_json = MockMethod() watcher.save_to_json = mock_save_json.call watcher._update_latest_ids(submissions) assert list(watcher.latest_ids) == id_list assert mock_save_json.called
async def test_submission_link_in_group_caption(mock_client): post_id = 23636984 event = MockTelegramEvent.with_message( chat_type=ChatType.GROUP, text=f"https://www.furaffinity.net/view/{post_id}/").with_document() submission = MockSubmission(post_id) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_submission(submission) await neaten.call(event) submission._send_message.assert_not_called()
async def test_deleted_submission(mock_client): post_id = 23636984 event = MockTelegramEvent.with_message( text="furaffinity.net/view/{}".format(post_id)) neaten = NeatenFunctionality(MockExportAPI()) with pytest.raises(StopPropagation): await neaten.call(event) event.reply.assert_called_with( f"This doesn't seem to be a valid FA submission: https://www.furaffinity.net/view/{post_id}/" )
async def test_submission_direct_link__not_found(): post_id = 12345 username = "******" sub = MockSubmission(post_id, username=username) event = MockTelegramEvent.with_inline_query(query=sub.download_url) inline = InlineNeatenFunctionality(MockExportAPI().with_user_folder( username, "gallery", [MockSubmission(12344), MockSubmission(12346)])) await inline.call(event) event.answer.assert_not_called()
def test_save_to_json(mock_client): test_watcher_file = "./test_subscription_watcher.json" if os.path.exists(test_watcher_file): os.remove(test_watcher_file) api = MockExportAPI() latest_submissions = [ SubmissionBuilder(submission_id="123243").build_short_submission(), SubmissionBuilder(submission_id="123242").build_short_submission(), SubmissionBuilder(submission_id="123240").build_short_submission() ] subscription1 = Subscription("query", 1234) subscription2 = Subscription("example", 5678) watcher = SubscriptionWatcher(api, mock_client) watcher._update_latest_ids(latest_submissions) watcher.subscriptions.add(subscription1) watcher.subscriptions.add(subscription2) watcher.blocklists[3452] = {"test", "example"} watcher.blocklists[1453] = {"ych"} watcher.FILENAME = test_watcher_file try: watcher.save_to_json() assert os.path.exists(test_watcher_file) with open(test_watcher_file, "r") as f: data = json.load(f) assert data is not None assert len(data['latest_ids']) == 3 assert "123240" in data['latest_ids'] assert "123242" in data['latest_ids'] assert "123243" in data['latest_ids'] assert len(data["destinations"]) == 4 assert len(data["destinations"]["1234"]["subscriptions"]) == 1 assert data["destinations"]["1234"]["subscriptions"][0][ "query"] == "query" assert len(data["destinations"]["1234"]["blocks"]) == 0 assert len(data["destinations"]["5678"]["subscriptions"]) == 1 assert data["destinations"]["5678"]["subscriptions"][0][ "query"] == "example" assert len(data["destinations"]["5678"]["blocks"]) == 0 assert len(data["destinations"]["3452"]["subscriptions"]) == 0 assert len(data["destinations"]["3452"]["blocks"]) == 2 assert set([ block["query"] for block in data["destinations"]["3452"]["blocks"] ]) == {"test", "example"} assert len(data["destinations"]["1453"]["subscriptions"]) == 0 assert len(data["destinations"]["1453"]["blocks"]) == 1 assert data["destinations"]["1453"]["blocks"][0]["query"] == "ych" finally: os.remove(test_watcher_file)
def test_list_subs__alphabetical_case_insensitive(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) watcher.subscriptions.add(Subscription("Example", 18749)) watcher.subscriptions.add(Subscription("test", 18749)) watcher.subscriptions.add(Subscription("deer", 18749)) func = SubscriptionFunctionality(watcher) resp = func._list_subs(18749) assert "Current subscriptions in this chat:" in resp assert "- deer\n- Example\n- test" in resp
def test_migrate_no_block_queries(mock_client): old_chat_id = 12345 new_chat_id = 54321 api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) watcher.subscriptions.add(MockSubscription("ych", old_chat_id)) watcher.migrate_chat(old_chat_id, new_chat_id) assert len(watcher.subscriptions) == 1 sub = list(watcher.subscriptions)[0] assert sub.query_str == "ych" assert sub.destination == new_chat_id
def test_remove_from_blocklist__tag_not_in_blocklist(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) watcher.blocklists[18749] = {"example"} watcher.blocklists[18747] = {"test"} func = BlocklistFunctionality(watcher) resp = func._remove_from_blocklist(18749, "test") assert resp == "The tag \"test\" is not on the blocklist for this chat." assert len(watcher.blocklists) == 2 assert len(watcher.blocklists[18749]) == 1 assert len(watcher.blocklists[18747]) == 1
def test_list_blocklisted_tags(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) watcher.blocklists[18749] = {"example", "deer"} watcher.blocklists[18747] = {"test"} func = BlocklistFunctionality(watcher) resp = func._list_blocklisted_tags(18749) assert "Current blocklist for this chat:" in resp assert "- deer" in resp assert "- example" in resp assert "- test" not in resp
def test_pause_subscription__one_matching_in_wrong_destination(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) watcher.subscriptions.add(Subscription("example", 18749)) watcher.subscriptions.add(Subscription("test", 12345)) func = SubscriptionFunctionality(watcher) resp = func._pause_subscription(18749, "test") assert resp == "There is not a subscription for \"test\" in this chat." assert len(watcher.subscriptions) == 2 for subscription in watcher.subscriptions: assert subscription.paused is False
async def test_run__is_stopped_by_running_false(mock_client): api = MockExportAPI() s = SubscriptionWatcher(api, mock_client) # Shorten the wait s.BACK_OFF = 1 task = asyncio.get_event_loop().create_task(watcher_killer(s)) # Run watcher await s.run() assert True await task
def test_list_subs__some_paused(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) watcher.subscriptions.add(Subscription("example", 18749)) sub_paused = Subscription("test", 18749) sub_paused.paused = True watcher.subscriptions.add(sub_paused) watcher.subscriptions.add(Subscription("deer", 18749)) func = SubscriptionFunctionality(watcher) resp = func._list_subs(18749) assert "Current subscriptions in this chat:" in resp assert "- deer\n- example\n- ⏸<s>test</s>" in resp
async def test_run__calls_get_new_results(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) method_called = MockMethod([]) watcher._get_new_results = method_called.async_call # Shorten the wait watcher.BACK_OFF = 1 task = asyncio.get_event_loop().create_task(watcher_killer(watcher)) # Run watcher await watcher.run() await task assert method_called.called
def test_list_subs(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) watcher.subscriptions.add(Subscription("example", 18749)) watcher.subscriptions.add(Subscription("test", 18747)) watcher.subscriptions.add(Subscription("deer", 18749)) func = SubscriptionFunctionality(watcher) resp = func._list_subs(18749) assert "Current subscriptions in this chat:" in resp assert "- deer" in resp assert "- example" in resp assert "- test" not in resp
async def test_unknown_type_submission_groupchat(mock_client): post_id = 23636984 event = MockTelegramEvent.with_message( text="https://www.furaffinity.net/view/{}/".format(post_id), chat_type=ChatType.GROUP) submission = MockSubmission(post_id, file_ext="zzz") neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_submission(submission) with pytest.raises(StopPropagation): await neaten.call(event) event.reply.assert_called_with("⏳ Neatening image link", ) event.reply.return_value.delete.assert_called_once()
async def test_inline_edit_functionality(mock_client): post_id = 1234 event = MockTelegramEvent.with_inline_send(result_id=str(post_id)) sub = MockSubmission(1234) api = MockExportAPI().with_submission(sub) func = InlineEditFunctionality(api, mock_client) await func.call(event) sub._send_message.assert_called_once() args, kwargs = sub._send_message.call_args assert args[0] == mock_client assert args[1] == event.msg_id assert kwargs['reply_to'] is None assert kwargs['edit'] is True
async def test_send_updates__sends_message(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) subscription = Subscription("test", 12345) submission = SubmissionBuilder().build_mock_submission() await watcher._send_updates([subscription], submission) assert submission._send_message.asset_called_once() args, kwargs = submission._send_message.call_args assert args[0] == mock_client assert args[1] == 12345 assert "update" in kwargs['prefix'].lower() assert "\"test\"" in kwargs['prefix'] assert "subscription" in kwargs['prefix'].lower()
async def test_inline_button_press(mock_client): callback = MockTelegramEvent.with_callback_query( data=b"neaten_me:1234", client=mock_client).with_inline_id(12345, 5431) sub = MockSubmission(1234) api = MockExportAPI().with_submission(sub) func = InlineEditButtonPress(api) await func.call(callback) sub._send_message.assert_called_once() args, kwargs = sub._send_message.call_args assert args[0] == mock_client assert args[1] == callback.original_update.msg_id assert kwargs['reply_to'] is None assert kwargs['edit'] is True
async def test_call__route_pause_destination_with_handle(mock_client): event = MockTelegramEvent.with_message(chat_id=14358, text="/pause@FASearchBot") api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) func = SubscriptionFunctionality(watcher) pause_dest = MockMethod("Paused all subscriptions") func._pause_destination = pause_dest.call with pytest.raises(StopPropagation): await func.call(event) assert pause_dest.called assert pause_dest.args is not None assert pause_dest.args[0] == event.chat_id event.reply.assert_called() assert event.reply.call_args[0][0] == "Paused all subscriptions"
async def test_run__can_exit_fast(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) # Shorten the wait watcher.BACK_OFF = 3 task = asyncio.get_event_loop().create_task(watcher_killer(watcher)) # Run watcher start_time = datetime.datetime.now() await watcher.run() end_time = datetime.datetime.now() await task time_waited = end_time - start_time assert time_waited.seconds <= 1
async def test_submission_link_in_caption(mock_client): post_id = 23636984 event = MockTelegramEvent.with_message(client=mock_client).with_photo( caption=f"https://www.furaffinity.net/view/{post_id}/") submission = MockSubmission(post_id) neaten = NeatenFunctionality(MockExportAPI()) neaten.api.with_submission(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_send_updates__blocked_pauses_other_subs(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) subscription1 = Subscription("test", 12345) subscription2 = Subscription("other", 12345) subscription3 = Subscription("not me", 54321) watcher.subscriptions = {subscription1, subscription2, subscription3} submission = SubmissionBuilder().build_mock_submission() submission.send_message = lambda *args, **kwargs: (_ for _ in ()).throw( UserIsBlockedError(None)) await watcher._send_updates([subscription1], submission) assert subscription1.paused assert subscription2.paused assert not subscription3.paused
async def test_call__route_resume_destination(mock_client): event = MockTelegramEvent.with_message(chat_id=14358, text="/resume") api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) func = SubscriptionFunctionality(watcher) resume_dest = MockMethod("Resumed all subscriptions") func._resume_destination = resume_dest.call with pytest.raises(StopPropagation): await func.call(event) assert resume_dest.called assert resume_dest.args is not None assert resume_dest.args[0] == event.chat_id event.reply.assert_called() assert event.reply.call_args[0][0] == "Resumed all subscriptions"
def test_resume_subscription__no_matching(mock_client): api = MockExportAPI() watcher = SubscriptionWatcher(api, mock_client) sub1 = Subscription("example", 18749) sub1.paused = True watcher.subscriptions.add(sub1) sub2 = Subscription("deer", 18749) sub2.paused = True watcher.subscriptions.add(sub2) func = SubscriptionFunctionality(watcher) resp = func._resume_subscription(18749, "test") assert resp == "There is not a subscription for \"test\" in this chat." assert len(watcher.subscriptions) == 2 for subscription in watcher.subscriptions: assert subscription.paused is True