def test_get_new_results__goes_to_another_page(self, bot): api = MockExportAPI() api.with_browse_results([ MockSubmission("1227"), MockSubmission("1225"), MockSubmission("1224") ], page=1) api.with_browse_results([ MockSubmission("1223"), MockSubmission("1222"), MockSubmission("1220") ], page=2) watcher = SubscriptionWatcher(api, bot) watcher.latest_ids = collections.deque(maxlen=4) watcher.latest_ids.append("1220") watcher.running = True results = watcher._get_new_results() assert len(results) == 5 assert results[0].submission_id == "1222" assert results[1].submission_id == "1223" assert results[2].submission_id == "1224" assert results[3].submission_id == "1225" assert results[4].submission_id == "1227"
def test_add_to_blocklist__new_blocklist(self, bot): api = MockExportAPI() watcher = SubscriptionWatcher(api, bot) watcher.add_to_blocklist(18749, "test") assert len(watcher.blocklists[18749]) == 1 assert isinstance(watcher.blocklists[18749], set) assert watcher.blocklists[18749] == {"test"}
def test_send_update__updates_latest(self, bot): api = MockExportAPI() watcher = SubscriptionWatcher(api, bot) subscription = Subscription("test", 12345) submission = SubmissionBuilder().build_mock_submission() watcher._send_update(subscription, submission) assert subscription.latest_update is not None
def test_update_latest_ids(self, bot): api = MockExportAPI() watcher = SubscriptionWatcher(api, bot) 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
def test_remove_from_blocklist__tag_not_in_blocklist(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) 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(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) 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_run__is_stopped_by_running_false(self, bot): api = MockExportAPI() s = SubscriptionWatcher(api, bot) # Shorten the wait s.BACK_OFF = 1 thread = Thread(target=lambda: self.watcher_killer(s)) thread.start() # Run watcher s.run() assert True thread.join()
def test_run__passes_correct_blocklists_to_subscriptions(self, bot): submission = MockSubmission("12322") api = MockExportAPI().with_submission(submission) watcher = SubscriptionWatcher(api, bot) method_called = MockMethod([submission]) watcher._get_new_results = method_called.call watcher.BACK_OFF = 1 watcher.blocklists = {156: {"test", "ych"}, -200: {"example"}} sub1 = MockSubscription("deer", 156) sub2 = MockSubscription("dog", -232) watcher.subscriptions = [sub1, sub2] thread = Thread(target=lambda: self.watcher_killer(watcher)) thread.start() # Run watcher watcher.run() thread.join() assert submission in sub1.submissions_checked assert len(sub1.blocklists) == 1 assert len(sub1.blocklists[0]) == 2 assert "test" in sub1.blocklists[0] assert "ych" in sub1.blocklists[0] assert submission in sub2.submissions_checked assert len(sub2.blocklists) == 1 assert len(sub2.blocklists[0]) == 0 assert method_called.called
def test_to_json_and_back(self, bot): 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, bot) 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, bot) 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 == "query": assert list_subs[0].destination == 1234 assert list_subs[1].query == "example" assert list_subs[1].destination == 5678 else: assert list_subs[0].query == "example" assert list_subs[0].destination == 5678 assert list_subs[1].query == "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)
def test_save_to_json(self, bot): 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, bot) 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['subscriptions']) == 2 if data['subscriptions'][0]['query'] == "query": assert data['subscriptions'][0]['destination'] == 1234 assert data['subscriptions'][1]['query'] == "example" assert data['subscriptions'][1]['destination'] == 5678 else: assert data['subscriptions'][0]['query'] == "example" assert data['subscriptions'][0]['destination'] == 5678 assert data['subscriptions'][1]['query'] == "query" assert data['subscriptions'][1]['destination'] == 1234 assert len(data["blacklists"]) == 2 assert "3452" in data["blacklists"] assert len(data["blacklists"]["3452"]) == 2 assert isinstance(data["blacklists"]["3452"], list) assert "test" in data["blacklists"]["3452"] assert "example" in data["blacklists"]["3452"] assert "1453" in data["blacklists"] assert len(data["blacklists"]["1453"]) == 1 assert isinstance(data["blacklists"]["1453"], list) assert data["blacklists"]["1453"] == ["ych"] finally: os.remove(test_watcher_file)
def test_remove_sub__removes_subscription(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) watcher.subscriptions.add(Subscription("example", 18749)) watcher.subscriptions.add(Subscription("test", 18747)) new_sub = Subscription("test", 18749) new_sub.latest_update = datetime.datetime.now() watcher.subscriptions.add(new_sub) func = SubscriptionFunctionality(watcher) list_subs = MockMethod("Listing subscriptions") func._list_subs = list_subs.call resp = func._remove_sub(18749, "test") assert "Removed subscription: \"test\"." in resp assert list_subs.called assert list_subs.args[0] == 18749 assert "Listing subscriptions" in resp assert len(watcher.subscriptions) == 2 subscriptions = list(watcher.subscriptions) if subscriptions[0].query == "test": assert subscriptions[0].destination == 18747 assert subscriptions[1].query == "example" assert subscriptions[1].destination == 18749 else: assert subscriptions[0].query == "example" assert subscriptions[0].destination == 18749 assert subscriptions[1].query == "test" assert subscriptions[1].destination == 18747
def test_get_new_results__returns_new_results(self, bot): api = MockExportAPI() api.with_browse_results([ MockSubmission("1223"), MockSubmission("1222"), MockSubmission("1220") ]) watcher = SubscriptionWatcher(api, bot) watcher.latest_ids.append("1220") watcher.running = True results = watcher._get_new_results() assert len(results) == 2 assert results[0].submission_id == "1222" assert results[1].submission_id == "1223"
def start(self): request = Request(con_pool_size=8) self.bot = MQBot(token=self.bot_key, request=request) self.subscription_watcher = SubscriptionWatcher.load_from_json( self.api, self.bot) self.subscription_watcher_thread = Thread( target=self.subscription_watcher.run) updater = Updater(bot=self.bot, use_context=True) dispatcher = updater.dispatcher logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) self.functionalities = self.initialise_functionalities() for func in self.functionalities: func.register(dispatcher) updater.start_polling() self.alive = True # Start the sub watcher self.subscription_watcher_thread.start() while self.alive: print("Main thread alive") try: time.sleep(30) except KeyboardInterrupt: self.alive = False # Kill the sub watcher self.subscription_watcher.running = False self.subscription_watcher_thread.join()
def test_send_update__sends_message(self, bot): api = MockExportAPI() watcher = SubscriptionWatcher(api, bot) subscription = Subscription("test", 12345) submission = SubmissionBuilder().build_mock_submission() watcher._send_update(subscription, submission) bot.send_message.assert_not_called() bot.send_photo.assert_called_once() kwargs_photo = bot.send_photo.call_args[1] assert kwargs_photo['chat_id'] == 12345 assert kwargs_photo['photo'] == submission.download_url assert "update" in kwargs_photo['caption'].lower() assert "\"test\"" in kwargs_photo['caption'] assert "subscription" in kwargs_photo['caption'].lower() assert submission.link in kwargs_photo['caption']
def test_get_new_results__handles_empty_latest_ids(self, bot): api = MockExportAPI() api.with_browse_results([ MockSubmission("1223"), MockSubmission("1222"), MockSubmission("1220") ]) watcher = SubscriptionWatcher(api, bot) watcher.running = True results = watcher._get_new_results() assert len(results) == 0 assert len(watcher.latest_ids) == 3 assert watcher.latest_ids[0] == "1220" assert watcher.latest_ids[1] == "1222" assert watcher.latest_ids[2] == "1223"
def test_init(self, bot): api = MockExportAPI() s = SubscriptionWatcher(api, bot) assert s.api == api assert len(s.latest_ids) == 0 assert s.running is False assert len(s.subscriptions) == 0
def test_run__can_exit_fast(self, bot): api = MockExportAPI() watcher = SubscriptionWatcher(api, bot) # Shorten the wait watcher.BACK_OFF = 3 thread = Thread(target=lambda: self.watcher_killer(watcher)) thread.start() # Run watcher start_time = datetime.datetime.now() watcher.run() end_time = datetime.datetime.now() thread.join() time_waited = end_time - start_time assert time_waited.seconds <= 1
def test_get_new_results__respects_page_cap(self, bot): api = MockExportAPI() api.with_browse_results([MockSubmission("1300")], page=1) api.with_browse_results([MockSubmission("1298")], page=2) api.with_browse_results([MockSubmission("1297")], page=3) api.with_browse_results([MockSubmission("1295")], page=4) api.with_browse_results([MockSubmission("1280")], page=5) api.with_browse_results([MockSubmission("1272")], page=6) api.with_browse_results([MockSubmission("1250")], page=7) watcher = SubscriptionWatcher(api, bot) watcher.PAGE_CAP = 5 watcher.latest_ids.append("1250") watcher.running = True results = watcher._get_new_results() assert len(results) == 5 assert "1272" not in [x.submission_id for x in results]
def test_add_sub__no_add_blank(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) func = SubscriptionFunctionality(watcher) resp = func._add_sub(18749, "") assert resp == "Please specify the subscription query you wish to add." assert len(watcher.subscriptions) == 0
def test_add_to_blocklist__no_add_blank(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) func = BlocklistFunctionality(watcher) resp = func._add_to_blocklist(18749, "") assert resp == "Please specify the tag you wish to add to blocklist." assert len(watcher.blocklists) == 0
def test_add_to_blocklist__add_tag_to_blocklist(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) watcher.blocklists[18749] = {"example"} func = BlocklistFunctionality(watcher) list_tags = MockMethod("Listing blocklisted tags") func._list_blocklisted_tags = list_tags.call resp = func._add_to_blocklist(18749, "test") assert "Added tag to blocklist" in resp assert "\"test\"" in resp assert list_tags.called assert list_tags.args[0] == 18749 assert "Listing blocklisted tags" in resp assert len(watcher.blocklists[18749]) == 2 assert isinstance(watcher.blocklists[18749], set) assert "example" in watcher.blocklists[18749] assert "test" in watcher.blocklists[18749]
def test_remove_from_blocklist__removes_tag_from_blocklist(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) watcher.blocklists[18749] = {"example", "test"} watcher.blocklists[18747] = {"test"} func = BlocklistFunctionality(watcher) list_tags = MockMethod("Listing blocklisted tags") func._list_blocklisted_tags = list_tags.call resp = func._remove_from_blocklist(18749, "test") assert "Removed tag from blocklist: \"test\"." in resp assert list_tags.called assert list_tags.args[0] == 18749 assert "Listing blocklisted tags" in resp assert len(watcher.blocklists) == 2 assert len(watcher.blocklists[18749]) == 1 assert len(watcher.blocklists[18747]) == 1 assert watcher.blocklists[18749] == {"example"} assert watcher.blocklists[18747] == {"test"}
def test_remove_sub__non_existent_subscription(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) 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
def test_list_subs__alphabetical(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) 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 active subscriptions in this chat:" in resp assert "- deer\n- example\n- test" in resp
def test_run__failed_to_send_doesnt_kill_watcher(self, bot): submission = MockSubmission("12322") api = MockExportAPI().with_browse_results([submission], 1) watcher = SubscriptionWatcher(api, bot) watcher._send_update = lambda *args: (_ for _ in ()).throw(Exception) watcher.BACK_OFF = 3 sub1 = MockSubscription("deer", 0) watcher.subscriptions = [sub1] api.call_after_x_browse = (lambda: watcher.stop(), 2) # Run watcher start_time = datetime.datetime.now() watcher.run() end_time = datetime.datetime.now() time_waited = end_time - start_time assert 3 <= time_waited.seconds <= 5
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"
def test_call__route_remove_subscription(context): update = MockTelegramUpdate.with_message(chat_id=14358, text="/remove_subscription@FASearchBot example") api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) func = SubscriptionFunctionality(watcher) delete_sub = MockMethod("Removed subscription test") func._remove_sub = delete_sub.call func.call(update, context) assert delete_sub.called assert delete_sub.args is not None assert delete_sub.args[0] == 14358 assert delete_sub.args[1] == "example" 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'] == "Removed subscription test"
def test_call__route_add_subscription_with_username(context): update = MockTelegramUpdate.with_message(chat_id=14358, text="/add_subscription@FASearchBot test") api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) func = SubscriptionFunctionality(watcher) add_sub = MockMethod("Added subscription test") func._add_sub = add_sub.call func.call(update, context) assert add_sub.called assert add_sub.args is not None assert add_sub.args[0] == 14358 assert add_sub.args[1] == "test" 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'] == "Added subscription test"
def test_add_to_blocklist__creates_blocklist_for_channel(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) func = BlocklistFunctionality(watcher) list_tags = MockMethod("Listing blocklisted tags") func._list_blocklisted_tags = list_tags.call resp = func._add_to_blocklist(18749, "test") assert "Added tag to blocklist" in resp assert "\"test\"" in resp assert list_tags.called assert list_tags.args[0] == 18749 assert "Listing blocklisted tags" in resp assert len(watcher.blocklists[18749]) == 1 assert isinstance(watcher.blocklists[18749], set) tag = list(watcher.blocklists[18749])[0] assert tag == "test"
def test_add_sub__adds_subscription(context): api = MockExportAPI() watcher = SubscriptionWatcher(api, context.bot) func = SubscriptionFunctionality(watcher) list_subs = MockMethod("Listing subscriptions") func._list_subs = list_subs.call resp = func._add_sub(18749, "test") assert "Added subscription" in resp assert "\"test\"" in resp assert list_subs.called assert list_subs.args[0] == 18749 assert "Listing subscriptions" in resp assert len(watcher.subscriptions) == 1 subscription = list(watcher.subscriptions)[0] assert subscription.query == "test" assert subscription.destination == 18749 assert subscription.latest_update is None