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
示例#5
0
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
示例#6
0
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)
示例#11
0
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"
示例#13
0
    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]
示例#19
0
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
示例#20
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
示例#21
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]
示例#22
0
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"}
示例#23
0
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
示例#24
0
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
示例#26
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"
示例#27
0
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"
示例#28
0
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"
示例#29
0
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"
示例#30
0
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