def run(self, line, user_obj, destination_obj): # See if last argument is check period. try: try_period = line.split()[-1] search_delta = Commons.load_time_delta(try_period) search = line[:-len(try_period)] except ISO8601ParseError: search = line search_delta = Commons.load_time_delta("PT300S") search = search.strip() # Get current RSS feed list function_dispatcher = user_obj.server.hallo.function_dispatcher sub_check_class = function_dispatcher.get_function_by_name("e621 sub check") sub_check_obj = function_dispatcher.get_function_object(sub_check_class) # type: SubE621Check e621_sub_list = sub_check_obj.e621_sub_list # type: E621SubList # Create new e621 search subscription e621_sub = E621Sub() e621_sub.server_name = user_obj.server.name e621_sub.search = search e621_sub.update_frequency = search_delta if destination_obj.is_channel(): e621_sub.channel_name = destination_obj.name else: e621_sub.user_name = destination_obj.name # Update feed first_results = e621_sub.check_subscription() # If no results, this is an invalid search subscription if len(first_results) == 0: return "Error, this does not appear to be a valid search, or does not have results." # Add new rss feed to list e621_sub_list.add_sub(e621_sub) # Save list e621_sub_list.to_xml() # Return output return "I have added new e621 subscription for the search \"" + e621_sub.search + "\""
def test_remove_no_match(self): # Get subscription list e621_check_class = self.function_dispatcher.get_function_by_name("e621 sub check") e621_check_obj = self.function_dispatcher.get_function_object(e621_check_class) # type: SubE621Check rfl = e621_check_obj.e621_sub_list # Add E621 searches to subscription list rf1 = E621Sub() rf1.search = "butt" rf1.server_name = self.server.name rf1.channel_name = self.test_chan.name rf1.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf1) rf2 = E621Sub() rf2.search = "deer" rf2.server_name = self.server.name rf2.channel_name = "another_channel" rf2.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf2) rf3 = E621Sub() rf3.search = "dragon" rf3.server_name = self.server.name rf3.channel_name = self.test_chan.name rf3.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf3) # Try to remove invalid search self.function_dispatcher.dispatch("e621 sub remove not_a_search", self.test_user, self.test_chan) data = self.server.get_send_data(1, self.test_chan, Server.MSG_MSG) assert "error" in data[0][0].lower() assert rf1 in rfl.sub_list assert rf2 in rfl.sub_list assert rf3 in rfl.sub_list
def create_from_input(input_evt, sub_repo): # Get event data server = input_evt.server destination = input_evt.channel if input_evt.channel is not None else input_evt.user clean_text = input_evt.command_args.strip().lower() text_split = clean_text.split() # Subreddit regex sub_regex = re.compile(r"r/([^\s]*)/?") if len(text_split) == 1: sub_name = clean_text if sub_regex.search(clean_text) is None else sub_regex.search(clean_text).group(1) reddit_sub = RedditSub(server, destination, sub_name) reddit_sub.check() return reddit_sub if len(text_split) > 2: raise SubscriptionException("Too many arguments. Please give a subreddit, and optionally, a check period.") try: search_delta = Commons.load_time_delta(text_split[0]) subreddit = text_split[1] except ISO8601ParseError: subreddit = text_split[0] search_delta = Commons.load_time_delta(text_split[1]) sub_name = clean_text if sub_regex.search(subreddit) is None else sub_regex.search(subreddit).group(1) reddit_sub = RedditSub(server, destination, sub_name, update_frequency=search_delta) reddit_sub.check() return reddit_sub
def test_run_by_title(self): # Set up test servers and channels serv1 = ServerMock(self.hallo) serv1.name = "test_serv1" chan1 = serv1.get_channel_by_name("test_chan1") chan2 = serv1.get_channel_by_name("test_chan2") serv2 = ServerMock(self.hallo) serv2.name = "test_serv2" chan3 = serv2.get_channel_by_name("test_chan1") try: self.hallo.add_server(serv1) self.hallo.add_server(serv2) # Set up rss feeds rfl = RssFeedList() rf1 = RssFeed() rf1.url = "http://spangle.org.uk/hallo/test_rss.xml?1" rf1.title = "test_feed1" rf1.server_name = chan1.server.name rf1.channel_name = chan1.name rf1.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf1) rf2 = RssFeed() rf2.url = "http://spangle.org.uk/hallo/test_rss.xml?2" rf2.title = "test_feed2" rf2.server_name = chan2.server.name rf2.channel_name = chan2.name rf2.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf2) rf3 = RssFeed() rf3.url = "http://spangle.org.uk/hallo/test_rss.xml?3" rf3.title = "test_feed1" rf3.server_name = chan3.server.name rf3.channel_name = chan3.name rf3.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf3) # Splice this rss feed list into the function dispatcher's rss check object rss_check_class = self.function_dispatcher.get_function_by_name("rss check") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: FeedCheck rss_check_obj.rss_feed_list = rfl # Invalid title self.function_dispatcher.dispatch("rss check Not a valid feed", self.test_user, self.test_chan) data = self.server.get_send_data(1, self.test_chan, Server.MSG_MSG) assert "error" in data[0][0].lower() # Correct title but wrong channel self.function_dispatcher.dispatch("rss check test_feed2", self.test_user, chan1) data = serv1.get_send_data(1, chan1, Server.MSG_MSG) assert "error" in data[0][0].lower() # Correct title check update self.function_dispatcher.dispatch("rss check test_feed2", self.test_user, chan2) data = serv1.get_send_data(1, chan2, Server.MSG_MSG) assert "feed updates were found" in data[0][0].lower() assert len(data[0][0].lower().split("\n")) == 4 # No updates rf2.title = "test_feed2" self.function_dispatcher.dispatch("rss check test_feed2", self.test_user, chan2) data = serv1.get_send_data(1, chan2, Server.MSG_MSG) assert "no updates" in data[0][0], "No further updates should be found." finally: self.hallo.remove_server(serv2) self.hallo.remove_server(serv1)
def test_remove_by_title(self): another_chan = self.server.get_channel_by_address("another_channel") # Get feed list rss_check_class = self.function_dispatcher.get_function_by_name("check subscription") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: SubscriptionCheck rfl = rss_check_obj.get_sub_repo(self.hallo) # Add RSS feeds to feed list rf1 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml?1", title="test_feed1", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf1) rf2 = RssSub(self.server, another_chan, "http://spangle.org.uk/hallo/test_rss.xml?2", title="test_feed1", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf2) rf3 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml?3", title="test_feed3", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf3) # Remove test feed self.function_dispatcher.dispatch(EventMessage(self.server, self.test_chan, self.test_user, "rss remove test_feed1")) data = self.server.get_send_data(1, self.test_chan, EventMessage) assert "removed rss subscription to test_feed1" in data[0].text.lower(), \ "Response did not contain expected string. Response was: {}".format(data[0].text) assert rf1 not in rfl.sub_list assert rf2 in rfl.sub_list assert rf3 in rfl.sub_list
def test_remove_multiple_matching_titles(self): # Get feed list rss_check_class = self.function_dispatcher.get_function_by_name("rss check") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: FeedCheck rfl = rss_check_obj.rss_feed_list # Add RSS feeds to feed list rf1 = RssFeed() rf1.url = "http://spangle.org.uk/hallo/test_rss.xml?1" rf1.title = "test_feed1" rf1.server_name = self.server.name rf1.channel_name = self.test_chan.name rf1.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf1) rf2 = RssFeed() rf2.url = "http://spangle.org.uk/hallo/test_rss.xml?2" rf2.title = "test_feed1" rf2.server_name = self.server.name rf2.channel_name = "another_channel" rf2.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf2) rf3 = RssFeed() rf3.url = "http://spangle.org.uk/hallo/test_rss.xml?3" rf3.title = "test_feed1" rf3.server_name = self.server.name rf3.channel_name = self.test_chan.name rf3.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf3) # Remove test feed self.function_dispatcher.dispatch("rss remove test_feed1", self.test_user, self.test_chan) data = self.server.get_send_data(1, self.test_chan, Server.MSG_MSG) assert "error" in data[0][0].lower() assert rf1 in rfl.feed_list assert rf2 in rfl.feed_list assert rf3 in rfl.feed_list
def test_list_feeds(self): another_chan = self.server.get_channel_by_address("another_channel") # Get feed list rss_check_class = self.function_dispatcher.get_function_by_name("check subscription") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: SubscriptionCheck rfl = rss_check_obj.get_sub_repo(self.hallo) # Add RSS feeds to feed list rf1 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml?1", title="test_feed1", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf1) rf2 = RssSub(self.server, another_chan, "http://spangle.org.uk/hallo/test_rss.xml?2", title="test_feed2", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf2) rf3 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml?3", title="test_feed3", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf3) # Run FeedList and check output self.function_dispatcher.dispatch(EventMessage(self.server, self.test_chan, self.test_user, "rss list")) data = self.server.get_send_data(1, self.test_chan, EventMessage) data_split = data[0].text.split("\n") assert "subscriptions posting" in data_split[0].lower(), "Actual message: {}".format(data[0].text) assert "test_feed1" in data_split[1].lower() or "test_feed1" in data_split[2].lower() assert "test_feed3" in data_split[1].lower() or "test_feed3" in data_split[2].lower() assert "http://spangle.org.uk/hallo/test_rss.xml?1" in data_split[1].lower() or \ "http://spangle.org.uk/hallo/test_rss.xml?1" in data_split[2].lower() assert "http://spangle.org.uk/hallo/test_rss.xml?3" in data_split[1].lower() or \ "http://spangle.org.uk/hallo/test_rss.xml?3" in data_split[2].lower() assert "test_feed2" not in data_split[1].lower() and "test_feed2" not in data_split[2].lower() assert "http://spangle.org.uk/hallo/test_rss.xml?2" not in data_split[1].lower() and \ "http://spangle.org.uk/hallo/test_rss.xml?2" not in data_split[2].lower()
def test_xml(self): # Setup a feed list rfl = SubscriptionRepo() rf1 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml?1", title="test_feed1", update_frequency=Commons.load_time_delta("P0T3600S")) rfl.add_sub(rf1) rf2 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml?2", title="test_feed2", update_frequency=Commons.load_time_delta("P1TS")) rfl.add_sub(rf2) rf3 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml?3", title="test_feed3", update_frequency=Commons.load_time_delta("PT60S")) rfl.add_sub(rf3) # Save to XML and load try: try: os.rename("store/subscriptions.json", "store/subscriptions.json.tmp") except OSError: pass rfl.save_json() new_rfl = SubscriptionRepo.load_json(self.hallo) assert len(new_rfl.sub_list) == 3 finally: try: os.remove("store/subscriptions.json") except OSError: pass try: os.rename("store/subscriptions.json.tmp", "store/subscriptions.json") except OSError: pass
def test_list_feeds(self): # Get feed list rss_check_class = self.function_dispatcher.get_function_by_name("e621 sub check") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: SubE621Check rfl = rss_check_obj.e621_sub_list # Add RSS feeds to feed list rf1 = E621Sub() rf1.search = "butt" rf1.server_name = self.server.name rf1.channel_name = self.test_chan.name rf1.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf1) rf2 = E621Sub() rf2.search = "deer" rf2.server_name = self.server.name rf2.channel_name = "another_channel" rf2.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf2) rf3 = E621Sub() rf3.search = "dragon" rf3.server_name = self.server.name rf3.channel_name = self.test_chan.name rf3.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf3) # Run FeedList and check output self.function_dispatcher.dispatch("e621 sub list", self.test_user, self.test_chan) data = self.server.get_send_data(1, self.test_chan, Server.MSG_MSG) data_split = data[0][0].split("\n") assert "e621 search subscriptions posting" in data_split[0].lower() assert "butt" in data_split[1].lower() or "butt" in data_split[2].lower() assert "deer" not in data_split[1].lower() and "deer" not in data_split[2].lower() assert "dragon" in data_split[1].lower() or "dragon" in data_split[2].lower()
def test_run_by_search(self): # Set up test servers and channels serv1 = ServerMock(self.hallo) serv1.name = "test_serv1" chan1 = serv1.get_channel_by_name("test_chan1") chan2 = serv1.get_channel_by_name("test_chan2") serv2 = ServerMock(self.hallo) serv2.name = "test_serv2" chan3 = serv2.get_channel_by_name("test_chan1") try: self.hallo.add_server(serv1) self.hallo.add_server(serv2) # Set up rss feeds rfl = E621SubList() rf1 = E621Sub() rf1.search = "butt" rf1.server_name = chan1.server.name rf1.channel_name = chan1.name rf1.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf1) rf2 = E621Sub() rf2.search = "deer" rf2.server_name = chan2.server.name rf2.channel_name = chan2.name rf2.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf2) rf3 = E621Sub() rf3.search = "dragon" rf3.server_name = chan3.server.name rf3.channel_name = chan3.name rf3.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_sub(rf3) # Splice this rss feed list into the function dispatcher's rss check object rss_check_class = self.function_dispatcher.get_function_by_name("e621 sub check") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: SubE621Check rss_check_obj.e621_sub_list = rfl # Invalid title self.function_dispatcher.dispatch("e621 sub check Not a valid search", self.test_user, self.test_chan) data = self.server.get_send_data(1, self.test_chan, Server.MSG_MSG) assert "error" in data[0][0].lower() # Correct title but wrong channel self.function_dispatcher.dispatch("e621 sub check deer", self.test_user, chan1) data = serv1.get_send_data(1, chan1, Server.MSG_MSG) assert "error" in data[0][0].lower() # Correct title check update self.function_dispatcher.dispatch("e621 sub check deer", self.test_user, chan2) data = serv1.get_send_data(1, chan2, Server.MSG_MSG) assert "search updates were found" in data[0][0].lower() assert len(data[0][0].lower().split("\n")) == 51 # No updates self.function_dispatcher.dispatch("e621 sub check deer", self.test_user, chan2) data = serv1.get_send_data(1, chan2, Server.MSG_MSG) assert "no updates" in data[0][0], "No further updates should be found." finally: self.hallo.remove_server(serv2) self.hallo.remove_server(serv1)
def test_load_time_delta(self): string1 = "20S" try: Commons.load_time_delta(string1) assert False, "String 1 should have failed to parse." except ISO8601ParseError: pass string2 = "P20" try: Commons.load_time_delta(string2) assert False, "String 2 should have failed to parse." except ISO8601ParseError: pass string3 = "P20S" try: Commons.load_time_delta(string3) assert False, "String 3 should have failed to parse." except ISO8601ParseError: pass string4 = "PTS" delta4 = Commons.load_time_delta(string4) assert delta4.seconds == 0, "delta4 seconds set incorrectly." assert delta4.days == 0, "delta4 days set incorrectly." string5 = "P1T1S" delta5 = Commons.load_time_delta(string5) assert delta5.seconds == 1, "delta5 seconds set incorrectly." assert delta5.days == 1, "delta5 days set incorrectly." string6 = "P10T3600S" delta6 = Commons.load_time_delta(string6) assert delta6.seconds == 3600, "delta6 seconds set incorrectly." assert delta6.days == 10, "delta6 days set incorrectly."
def test_run_all(self): # Set up test servers and channels serv1 = ServerMock(self.hallo) serv1.name = "test_serv1" chan1 = serv1.get_channel_by_address("test_chan1".lower(), "test_chan1") chan2 = serv1.get_channel_by_address("test_chan2".lower(), "test_chan2") serv2 = ServerMock(self.hallo) serv2.name = "test_serv2" chan3 = serv2.get_channel_by_address("test_chan1".lower(), "test_chan1") try: self.hallo.add_server(serv1) self.hallo.add_server(serv2) # Set up rss feeds rfl = SubscriptionRepo() rf1 = RssSub(chan1.server, chan1, "http://spangle.org.uk/hallo/test_rss.xml?1", title="test_feed1", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf1) rf2 = RssSub(chan2.server, chan2, "http://spangle.org.uk/hallo/test_rss.xml?2", title="test_feed2", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf2) rf3 = RssSub(chan3.server, chan3, "http://spangle.org.uk/hallo/test_rss.xml?3", title="test_feed1", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf3) # Splice this rss feed list into the function dispatcher's rss check object rss_check_class = self.function_dispatcher.get_function_by_name("check subscription") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: SubscriptionCheck rss_check_obj.subscription_repo = rfl # Test running all feed updates self.function_dispatcher.dispatch(EventMessage(self.server, self.test_chan, self.test_user, "rss check all")) # Check original calling channel data serv0_data = self.server.get_send_data(1, self.test_chan, EventMessage) assert "subscription updates were found" in serv0_data[0].text # Check test server 1 data serv1_data = serv1.get_send_data(6) chan1_count = 0 chan2_count = 0 for data_line in serv1_data: if data_line.channel == chan1: chan1_count += 1 if data_line.channel == chan2: chan2_count += 1 assert chan1_count == 3 assert chan2_count == 3 # Check test server 2 data serv2.get_send_data(3, chan3, EventMessage) # Test running with no new updates. self.function_dispatcher.dispatch(EventMessage(self.server, self.test_chan, self.test_user, "rss check all")) data = self.server.get_send_data(1, self.test_chan, EventMessage) assert "no updates" in data[0].text, "No further updates should be found." finally: self.hallo.remove_server(serv2) self.hallo.remove_server(serv1)
def test_run_by_title(self): # Set up test servers and channels serv1 = ServerMock(self.hallo) serv1.name = "test_serv1" chan1 = serv1.get_channel_by_address("test_chan1") chan2 = serv1.get_channel_by_address("test_chan2") user1 = serv1.get_user_by_address("test_user1") serv2 = ServerMock(self.hallo) serv2.name = "test_serv2" chan3 = serv2.get_channel_by_address("test_chan1") try: self.hallo.add_server(serv1) self.hallo.add_server(serv2) # Set up rss feeds rfl = SubscriptionRepo() rf1 = RssSub(chan1.server, chan1, "http://spangle.org.uk/hallo/test_rss.xml?1", title="test_feed1", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf1) rf2 = RssSub(chan2.server, chan2, "http://spangle.org.uk/hallo/test_rss.xml?2", title="test_feed2", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf2) rf3 = RssSub(chan3.server, chan3, "http://spangle.org.uk/hallo/test_rss.xml?3", title="test_feed1", update_frequency=Commons.load_time_delta("PT3600S")) rfl.add_sub(rf3) # Splice this rss feed list into the function dispatcher's rss check object rss_check_class = self.function_dispatcher.get_function_by_name("check subscription") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: SubscriptionCheck rss_check_obj.subscription_repo = rfl # Invalid title self.function_dispatcher.dispatch(EventMessage(self.server, self.test_chan, self.test_user, "rss check Not a valid feed")) data = self.server.get_send_data(1, self.test_chan, EventMessage) assert "error" in data[0].text.lower() # Correct title but wrong channel self.function_dispatcher.dispatch(EventMessage(serv1, chan1, user1, "rss check test_feed2")) data = serv1.get_send_data(1, chan1, EventMessage) assert "error" in data[0].text.lower() # Correct title check update self.function_dispatcher.dispatch(EventMessage(serv1, chan2, user1, "rss check test_feed2")) data = serv1.get_send_data(4, chan2, EventMessage) for x in range(3): assert "update on" in data[x].text.lower() assert "rss feed" in data[x].text.lower() assert "updates were found" in data[3].text.lower(), "Actual message: {}".format(data[0].text) # No updates rf2.title = "test_feed2" self.function_dispatcher.dispatch(EventMessage(serv1, chan2, user1, "rss check test_feed2")) data = serv1.get_send_data(1, chan2, EventMessage) assert "no updates" in data[0].text, "No further updates should be found." finally: self.hallo.remove_server(serv2) self.hallo.remove_server(serv1)
def test_needs_check(self): rf1 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml", last_check=datetime.now(), update_frequency=Commons.load_time_delta("P1TS")) assert not rf1.needs_check() rf1.last_check = datetime.now() - Commons.load_time_delta("P2TS") assert rf1.needs_check() rf1.update_frequency = Commons.load_time_delta("P7TS") assert not rf1.needs_check() rf2 = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml", last_check=datetime.now(), update_frequency=Commons.load_time_delta("PT5S")) assert not rf2.needs_check() time.sleep(10) assert rf2.needs_check()
def test_needs_check(self): rf1 = E621Sub() rf1.last_check = datetime.now() rf1.update_frequency = Commons.load_time_delta("P1TS") assert not rf1.needs_check() rf1.last_check = datetime.now() - Commons.load_time_delta("P2TS") assert rf1.needs_check() rf1.update_frequency = Commons.load_time_delta("P7TS") assert not rf1.needs_check() rf2 = E621Sub() rf2.last_check = datetime.now() rf2.update_frequency = Commons.load_time_delta("PT5S") assert not rf2.needs_check() time.sleep(10) assert rf2.needs_check()
def from_json(json_obj, hallo, sub_repo): server = hallo.get_server_by_name(json_obj["server_name"]) if server is None: raise SubscriptionException("Could not find server with name \"{}\"".format(json_obj["server_name"])) # Load channel or user if "channel_address" in json_obj: destination = server.get_channel_by_address(json_obj["channel_address"]) else: if "user_address" in json_obj: destination = server.get_user_by_address(json_obj["user_address"]) else: raise SubscriptionException("Channel or user must be defined.") if destination is None: raise SubscriptionException("Could not find chanel or user.") # Load last check last_check = None if "last_check" in json_obj: last_check = datetime.strptime(json_obj["last_check"], "%Y-%m-%dT%H:%M:%S.%f") # Load update frequency update_frequency = Commons.load_time_delta(json_obj["update_frequency"]) # Load last update last_update = None if "last_update" in json_obj: last_update = datetime.strptime(json_obj["last_update"], "%Y-%m-%dT%H:%M:%S.%f") # Type specific loading # Load last items latest_ids = [] for latest_id in json_obj["latest_ids"]: latest_ids.append(latest_id) # Load search subreddit = json_obj["subreddit"] new_sub = RedditSub(server, destination, subreddit, last_check, update_frequency, latest_ids) new_sub.last_update = last_update return new_sub
def from_xml_string(xml_string): """ Loads new E621Sub object from XML string :param xml_string: string :return: E621Sub """ # Create blank feed new_sub = E621Sub() # Load xml sub_xml = ElementTree.fromstring(xml_string) # Load title, url, server new_sub.search = sub_xml.find("search").text new_sub.server_name = sub_xml.find("server").text # Load channel or user if sub_xml.find("channel") is not None: new_sub.channel_name = sub_xml.find("channel").text else: if sub_xml.find("user") is not None: new_sub.user_name = sub_xml.find("user").text else: raise Exception("Channel or user must be defined") # Load last item for latest_id in sub_xml.findall("latest_id"): new_sub.latest_ten_ids.append(int(latest_id.text)) # Load last check if sub_xml.find("last_check") is not None: new_sub.last_check = datetime.strptime(sub_xml.find("last_check").text, "%Y-%m-%dT%H:%M:%S.%f") # Load update frequency new_sub.update_frequency = Commons.load_time_delta(sub_xml.find("update_frequency").text) # Return new feed return new_sub
def from_xml_string(xml_string): """ Loads new RssFeed object from XML string :param xml_string: string :return: RssFeed """ # Create blank feed new_feed = RssFeed() # Load xml feed_xml = ElementTree.fromstring(xml_string) # Load title, url, server new_feed.title = feed_xml.find("title").text new_feed.url = feed_xml.find("url").text new_feed.server_name = feed_xml.find("server").text # Load channel or user if feed_xml.find("channel") is not None: new_feed.channel_name = feed_xml.find("channel").text else: if feed_xml.find("user") is not None: new_feed.user_name = feed_xml.find("user").text else: raise Exception("Channel or user must be defined") # Load last item if feed_xml.find("last_item") is not None: new_feed.last_item_hash = feed_xml.find("last_item").text # Load last check if feed_xml.find("last_check") is not None: new_feed.last_check = datetime.strptime(feed_xml.find("last_check").text, "%Y-%m-%dT%H:%M:%S.%f") # Load update frequency new_feed.update_frequency = Commons.load_time_delta(feed_xml.find("update_frequency").text) # Return new feed return new_feed
def test_list_feeds(self): # Get feed list rss_check_class = self.function_dispatcher.get_function_by_name("rss check") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: FeedCheck rfl = rss_check_obj.rss_feed_list # Add RSS feeds to feed list rf1 = RssFeed() rf1.url = "http://spangle.org.uk/hallo/test_rss.xml?1" rf1.title = "test_feed1" rf1.server_name = self.server.name rf1.channel_name = self.test_chan.name rf1.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf1) rf2 = RssFeed() rf2.url = "http://spangle.org.uk/hallo/test_rss.xml?2" rf2.title = "test_feed2" rf2.server_name = self.server.name rf2.channel_name = "another_channel" rf2.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf2) rf3 = RssFeed() rf3.url = "http://spangle.org.uk/hallo/test_rss.xml?3" rf3.title = "test_feed3" rf3.server_name = self.server.name rf3.channel_name = self.test_chan.name rf3.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf3) # Run FeedList and check output self.function_dispatcher.dispatch("rss list", self.test_user, self.test_chan) data = self.server.get_send_data(1, self.test_chan, Server.MSG_MSG) data_split = data[0][0].split("\n") assert "rss feeds posting" in data_split[0].lower() assert "test_feed1" in data_split[1].lower() or "test_feed1" in data_split[2].lower() assert "test_feed3" in data_split[1].lower() or "test_feed3" in data_split[2].lower() assert ( "http://spangle.org.uk/hallo/test_rss.xml?1" in data_split[1].lower() or "http://spangle.org.uk/hallo/test_rss.xml?1" in data_split[2].lower() ) assert ( "http://spangle.org.uk/hallo/test_rss.xml?3" in data_split[1].lower() or "http://spangle.org.uk/hallo/test_rss.xml?3" in data_split[2].lower() ) assert "test_feed2" not in data_split[1].lower() and "test_feed2" not in data_split[2].lower() assert ( "http://spangle.org.uk/hallo/test_rss.xml?2" not in data_split[1].lower() and "http://spangle.org.uk/hallo/test_rss.xml?2" not in data_split[2].lower() )
def test_add_feed(self): rfl = SubscriptionRepo() assert rfl.sub_list == [] # Create example rss feed rf = RssSub(self.server, self.test_chan, "http://spangle.org.uk/hallo/test_rss.xml", update_frequency=Commons.load_time_delta("P0T3600S")) rfl.add_sub(rf) assert len(rfl.sub_list) == 1 assert rfl.sub_list[0] == rf
def create_from_input(input_evt, sub_repo): server = input_evt.server destination = input_evt.channel if input_evt.channel is not None else input_evt.user # Get user specified stuff feed_url = input_evt.command_args.split()[0] feed_period = "PT600S" if len(input_evt.command_args.split()) > 1: feed_period = input_evt.command_args.split()[1] try: feed_delta = Commons.load_time_delta(feed_period) except ISO8601ParseError: feed_delta = Commons.load_time_delta("PT600S") try: rss_sub = RssSub(server, destination, feed_url, update_frequency=feed_delta) rss_sub.check() except Exception as e: raise SubscriptionException("Failed to create RSS subscription", e) return rss_sub
def test_add_feed(self): rfl = RssFeedList() assert rfl.feed_list == [] # Create example rss feed rf = RssFeed() rf.update_frequency = Commons.load_time_delta("P0T3600S") rf.url = "http://spangle.org.uk/hallo/test_feed.xml" rfl.add_feed(rf) assert len(rfl.feed_list) == 1 assert rfl.feed_list[0] == rf
def test_xml(self): # Setup a feed list rfl = RssFeedList() rf1 = RssFeed() rf1.url = "http://spangle.org.uk/hallo/test_feed.xml?1" rf1.title = "test_feed1" rf1.update_frequency = Commons.load_time_delta("P0T3600S") rf1.server_name = "test_serv1" rf1.channel_name = "test_chan1" rfl.add_feed(rf1) rf2 = RssFeed() rf2.url = "http://spangle.org.uk/hallo/test_feed.xml?2" rf2.title = "test_feed2" rf2.update_frequency = Commons.load_time_delta("P1TS") rf2.server_name = "test_serv2" rf2.channel_name = "test_chan2" rfl.add_feed(rf2) rf3 = RssFeed() rf3.url = "http://spangle.org.uk/hallo/test_feed.xml?3" rf3.title = "test_feed3" rf3.update_frequency = Commons.load_time_delta("PT60S") rf3.server_name = "test_serv3" rf3.user_name = "test_user3" rfl.add_feed(rf3) # Save to XML and load try: try: os.rename("store/rss_feeds.xml", "store/rss_feeds.xml.tmp") except OSError: pass rfl.to_xml() new_rfl = RssFeedList.from_xml() assert len(new_rfl.feed_list) == 3 finally: try: os.remove("store/rss_feeds.xml") except OSError: pass try: os.rename("store/rss_feeds.xml.tmp", "store/rss_feeds.xml") except OSError: pass
def __init__(self, server, destination, last_check=None, update_frequency=None): """ :type server: Server.Server :type destination: Destination.Destination :type last_check: datetime :type update_frequency: timedelta """ if update_frequency is None: update_frequency = Commons.load_time_delta("PT300S") self.server = server """ :type : Server.Server""" self.destination = destination """ :type : Destination.Destination""" self.last_check = last_check """ :type : datetime""" self.update_frequency = update_frequency """ :type : timedelta""" self.last_update = None """ :type : datetime | None"""
def run(self, line, user_obj, destination_obj): # Get input feed_url = line.split()[0] feed_period = "PT3600S" if len(line.split()) > 1: feed_period = line.split()[1] # Get current RSS feed list function_dispatcher = user_obj.server.hallo.function_dispatcher feed_check_class = function_dispatcher.get_function_by_name("rss check") feed_check_obj = function_dispatcher.get_function_object(feed_check_class) # type: FeedCheck feed_list = feed_check_obj.rss_feed_list # Check link works try: Commons.load_url_string(feed_url, []) except urllib.error.URLError: return "Error, could not load link." # Check period is valid try: feed_delta = Commons.load_time_delta(feed_period) except ISO8601ParseError: return "Error, invalid time period." # Create new rss feed rss_feed = RssFeed() rss_feed.server_name = user_obj.server.name rss_feed.url = feed_url rss_feed.update_frequency = feed_delta if destination_obj.is_channel(): rss_feed.channel_name = destination_obj.name else: rss_feed.user_name = destination_obj.name # Update feed try: rss_feed.check_feed() except ParseError: return "Error, RSS feed could not be parsed." # Add new rss feed to list feed_list.add_feed(rss_feed) # Save list feed_list.to_xml() # Return output return "I have added new RSS feed titled \"" + rss_feed.title + "\""
def test_xml(self): test_rss_url = "http://spangle.org.uk/hallo/test_rss.xml" test_seconds = 3600 test_days = 0 # Create example feed sub_repo = SubscriptionRepo() rf = RssSub(self.server, self.test_chan, test_rss_url, update_frequency=Commons.load_time_delta("P"+str(test_days)+"T"+str(test_seconds)+"S")) # Clear off the current items rf.check() # Ensure there are no new items new_items = rf.check() assert len(new_items) == 0 # Save to XML and load up new RssFeed rf_xml = rf.to_json() rf2 = RssSub.from_json(rf_xml, self.hallo, sub_repo) # Ensure there's still no new items new_items = rf2.check() assert len(new_items) == 0 assert rf2.update_frequency.days == test_days assert rf2.update_frequency.seconds == test_seconds
def test_xml(self): test_rss_url = "http://spangle.org.uk/hallo/test_rss.xml" test_seconds = 3600 test_days = 0 # Create example feed rf = RssFeed() rf.url = test_rss_url rf.update_frequency = Commons.load_time_delta("P"+str(test_days)+"T"+str(test_seconds)+"S") rf.server_name = "test_serv" rf.channel_name = "test_chan" # Clear off the current items rf.check_feed() # Ensure there are no new items new_items = rf.check_feed() assert len(new_items) == 0 # Save to XML and load up new RssFeed rf_xml = rf.to_xml_string() rf2 = RssFeed.from_xml_string(rf_xml) # Ensure there's still no new items new_items = rf2.check_feed() assert len(new_items) == 0 assert rf2.update_frequency.days == test_days assert rf2.update_frequency.seconds == test_seconds
def test_xml(self): test_e621_search = "butts" test_seconds = 3600 test_days = 0 # Create example feed rf = E621Sub() rf.search = test_e621_search rf.update_frequency = Commons.load_time_delta("P"+str(test_days)+"T"+str(test_seconds)+"S") rf.server_name = "test_serv" rf.channel_name = "test_chan" # Clear off the current items rf.check_subscription() # Ensure there are no new items new_items = rf.check_subscription() assert len(new_items) == 0 # Save to XML and load up new RssFeed rf_xml = rf.to_xml_string() rf2 = E621Sub.from_xml_string(rf_xml) # Ensure there's still no new items new_items = rf2.check_subscription() assert len(new_items) == 0 assert rf2.update_frequency.days == test_days assert rf2.update_frequency.seconds == test_seconds
def test_run_all(self): # Set up test servers and channels serv1 = ServerMock(None) serv1.name = "test_serv1" chan1 = serv1.get_channel_by_name("test_chan1") chan2 = serv1.get_channel_by_name("test_chan2") serv2 = ServerMock(None) serv2.name = "test_serv2" chan3 = serv2.get_channel_by_name("test_chan1") try: self.hallo.add_server(serv1) self.hallo.add_server(serv2) # Set up rss feeds rfl = RssFeedList() rf1 = RssFeed() rf1.url = "http://spangle.org.uk/hallo/test_rss.xml?1" rf1.title = "test_feed1" rf1.server_name = chan1.server.name rf1.channel_name = chan1.name rf1.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf1) rf2 = RssFeed() rf2.url = "http://spangle.org.uk/hallo/test_rss.xml?2" rf2.title = "test_feed2" rf2.server_name = chan2.server.name rf2.channel_name = chan2.name rf2.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf2) rf3 = RssFeed() rf3.url = "http://spangle.org.uk/hallo/test_rss.xml?3" rf3.title = "test_feed1" rf3.server_name = chan3.server.name rf3.channel_name = chan3.name rf3.update_frequency = Commons.load_time_delta("PT3600S") rfl.add_feed(rf3) # Splice this rss feed list into the function dispatcher's rss check object rss_check_class = self.function_dispatcher.get_function_by_name("rss check") rss_check_obj = self.function_dispatcher.get_function_object(rss_check_class) # type: FeedCheck rss_check_obj.rss_feed_list = rfl # Test running all feed updates self.function_dispatcher.dispatch("rss check all", self.test_user, self.test_chan) # Check original calling channel data serv0_data = self.server.get_send_data(1, self.test_chan, Server.MSG_MSG) assert "feed updates were found" in serv0_data[0][0] # Check test server 1 data serv1_data = serv1.get_send_data(6) chan1_count = 0 chan2_count = 0 for data_line in serv1_data: if data_line[1] == chan1: chan1_count += 1 if data_line[1] == chan2: chan2_count += 1 assert chan1_count == 3 assert chan2_count == 3 # Check test server 2 data serv2_data = serv2.get_send_data(3, chan3, Server.MSG_MSG) # Test running with no new updates. self.function_dispatcher.dispatch("rss check all", self.test_user, self.test_chan) data = self.server.get_send_data(1, self.test_chan, Server.MSG_MSG) assert "no feed updates" in data[0][0], "No further updates should be found." finally: self.hallo.remove_server(serv2) self.hallo.remove_server(serv1)
def test_output_item(self): # Create example e621 sub element item_id = "652362" item_rate = "q" item_rating = "(Questionable)" item_elem = {"id":item_id, "rating":item_rate} # Check output works with given server and channel rf1 = E621Sub() rf1.update_frequency = Commons.load_time_delta("P1TS") serv1 = ServerMock(None) serv1.name = "test_serv1" chan1 = serv1.get_channel_by_name("test_chan1") rf1.output_item(item_elem, None, serv1, chan1) data = serv1.get_send_data(1, chan1, Server.MSG_MSG) assert item_id in data[0][0] assert item_rating in data[0][0] # Check output works with given server not channel rf2 = E621Sub() rf2.update_frequency = Commons.load_time_delta("P1TS") rf2.channel_name = "test_chan2" serv2 = ServerMock(None) serv2.name = "test_serv2" chan2 = serv2.get_channel_by_name("test_chan2") rf2.output_item(item_elem, None, serv2) data = serv2.get_send_data(1, chan2, Server.MSG_MSG) assert item_id in data[0][0] assert item_rating in data[0][0] # Check output works with given server not user rf3 = E621Sub() rf3.update_frequency = Commons.load_time_delta("P1TS") rf3.user_name = "test_user3" serv3 = ServerMock(None) serv3.name = "test_serv3" user3 = serv3.get_user_by_name("test_user3") rf3.output_item(item_elem, None, serv3) data = serv3.get_send_data(1, user3, Server.MSG_MSG) assert item_id in data[0][0] assert item_rating in data[0][0] # Check output works without given server with given channel rf4 = E621Sub() rf4.update_frequency = Commons.load_time_delta("P1TS") rf4.server_name = "test_serv4" serv4 = ServerMock(None) serv4.name = "test_serv4" hallo4 = Hallo() hallo4.add_server(serv4) chan4 = serv4.get_channel_by_name("test_chan4") rf4.output_item(item_elem, hallo4, None, chan4) data = serv4.get_send_data(1, chan4, Server.MSG_MSG) assert item_id in data[0][0] assert item_rating in data[0][0] # Check output works without given server with given user rf5 = E621Sub() rf5.update_frequency = Commons.load_time_delta("P1TS") rf5.server_name = "test_serv5" serv5 = ServerMock(None) serv5.name = "test_serv5" hallo5 = Hallo() hallo5.add_server(serv5) chan5 = serv5.get_channel_by_name("test_chan5") rf5.output_item(item_elem, hallo5, None, chan5) data = serv5.get_send_data(1, chan5, Server.MSG_MSG) assert item_id in data[0][0] assert item_rating in data[0][0] # Check output works without given server or channel to channel rf6 = E621Sub() rf6.update_frequency = Commons.load_time_delta("P1TS") rf6.server_name = "test_serv6" rf6.channel_name = "test_chan6" serv6 = ServerMock(None) serv6.name = "test_serv6" hallo6 = Hallo() hallo6.add_server(serv6) chan6 = serv6.get_channel_by_name("test_chan6") rf6.output_item(item_elem, hallo6) data = serv6.get_send_data(1, chan6, Server.MSG_MSG) assert item_id in data[0][0] assert item_rating in data[0][0] # Check output works without given server or channel to user rf7 = E621Sub() rf7.update_frequency = Commons.load_time_delta("P1TS") rf7.server_name = "test_serv7" rf7.user_name = "test_user7" serv7 = ServerMock(None) serv7.name = "test_serv7" hallo7 = Hallo() hallo7.add_server(serv7) user7 = serv7.get_user_by_name("test_user7") rf7.output_item(item_elem, hallo7) data = serv7.get_send_data(1, user7, Server.MSG_MSG) assert item_id in data[0][0] assert item_rating in data[0][0] # Check invalid server output (server name is none) rf8 = E621Sub() rf8.update_frequency = Commons.load_time_delta("P1TS") hallo8 = Hallo() resp = rf8.output_item(item_elem, hallo8) assert "error" in resp.lower() assert "server" in resp.lower() # Check invalid server output ( server name is not in hallo obj) rf9 = E621Sub() rf9.update_frequency = Commons.load_time_delta("P1TS") rf9.server_name = "not_a_server" hallo9 = Hallo() resp = rf9.output_item(item_elem, hallo9) assert "error" in resp.lower() assert "server" in resp.lower() # Check invalid channel/user output (only possible if channel name and user name are none) (with given server) rf10 = E621Sub() rf10.update_frequency = Commons.load_time_delta("P1TS") serv10 = ServerMock(None) serv10.name = "test_serv10" hallo10 = Hallo() hallo10.add_server(serv10) resp = rf10.output_item(item_elem, hallo10, serv10) assert "error" in resp.lower() assert "destination" in resp.lower() # Check invalid channel/user output (only possible if channel name and user name are none) (with named server) rf11 = E621Sub() rf11.update_frequency = Commons.load_time_delta("P1TS") rf11.server_name = "test_serv11" serv11 = ServerMock(None) serv11.name = "test_serv11" hallo11 = Hallo() hallo11.add_server(serv11) resp = rf11.output_item(item_elem, hallo11) assert "error" in resp.lower() assert "destination" in resp.lower()