def test_add_and_get_channels(self): db = Database(":memory:") db.add_channel(Channel(displayname="Webdriver Torso", yt_channelid="UCsLiV4WJfkTEHH0b9PmRklw")) db.add_channel(Channel(displayname="Webdriver YPP", yt_channelid="UCxexYYtOetqikZqriLuTS-g")) channels = db.get_channels() self.assertEqual(len(channels), 2) self.assertEqual(channels[0].displayname, "Webdriver Torso") self.assertEqual(channels[0].yt_channelid, "UCsLiV4WJfkTEHH0b9PmRklw") self.assertEqual(channels[1].displayname, "Webdriver YPP") self.assertEqual(channels[1].yt_channelid, "UCxexYYtOetqikZqriLuTS-g")
def setUp(self): self.current_dir = os.path.dirname(__file__) self.ytcc = Ytcc(os.path.join(self.current_dir, "data/ytcc_test.conf")) self.db_conn = self.ytcc.database self.db_conn.engine.execute("delete from video") self.db_conn.engine.execute("delete from channel") self.db_conn.add_channel( Channel(displayname="Webdriver Torso", yt_channelid="UCsLiV4WJfkTEHH0b9PmRklw")) self.db_conn.add_channel( Channel(displayname="Webdriver YPP", yt_channelid="UCxexYYtOetqikZqriLuTS-g"))
def _create_channel(elem: etree.Element) -> Channel: rss_url = urlparse(elem.attrib["xmlUrl"]) query_dict = parse_qs(rss_url.query, keep_blank_values=False) channel_id = query_dict.get("channel_id", []) if len(channel_id) != 1: message = f"'{file.name}' is not a valid YouTube export file" raise InvalidSubscriptionFileError(message) return Channel(displayname=elem.attrib["title"], yt_channelid=channel_id[0])
def add_channel(self, displayname: str, channel_url: str) -> None: """Subscribe to a channel. :param displayname: A human readable name of the channel. :param channel_url: The url to a page that can identify the channel. :raises ChannelDoesNotExistException: If the given URL does not exist. :raises DuplicateChannelException: If the channel already exists in the database. :raises BadURLException: If the given URL does not refer to a YouTube channel. """ known_yt_domains = [ "youtu.be", "youtube.com", "youtubeeducation.com", "youtubekids.com", "youtube-nocookie.com", "yt.be", "ytimg.com" ] url_parts = urlparse(channel_url, scheme="https") if not url_parts.netloc: url_parts = urlparse("https://" + channel_url) domain = url_parts.netloc.split(":")[0] domain = ".".join(domain.split(".")[-2:]) if domain not in known_yt_domains: raise BadURLException(f"{channel_url} is not a valid URL") url = urlunparse( ("https", url_parts.netloc, url_parts.path, url_parts.params, url_parts.query, url_parts.fragment)) try: response = urlopen(url).read().decode('utf-8') except URLError: raise BadURLException(f"{channel_url} is not a valid URL") parser = etree.HTMLParser() root = etree.parse(StringIO(response), parser).getroot() site_name_node = root.xpath( '/html/head/meta[@property="og:site_name"]') channel_id_node = root.xpath('//meta[@itemprop="channelId"]') if not site_name_node or site_name_node[0].attrib.get("content", "") != "YouTube": raise BadURLException( f"{channel_url} does not seem to be a YouTube URL") if not channel_id_node: raise ChannelDoesNotExistException( f"{channel_url} does not seem to be a YouTube URL") yt_channelid = channel_id_node[0].attrib.get("content") try: self.database.add_channel( Channel(displayname=displayname, yt_channelid=yt_channelid)) except sqlalchemy.exc.IntegrityError: raise DuplicateChannelException( f"Channel already subscribed: {displayname}")
def init_db(): insert_list = [ Video(yt_videoid="0", title="title1", description="description1", publisher="id_publisher1", publish_date=1488286166, watched=False), Video(yt_videoid="0", title="title1", description="description1", publisher="id_publisher1", publish_date=1488286167, watched=False), Video(yt_videoid="1", title="title2", description="description1", publisher="id_publisher1", publish_date=1488286168, watched=False), Video(yt_videoid="1", title="title2", description="description2", publisher="id_publisher2", publish_date=1488286170, watched=False), Video(yt_videoid="2", title="title3", description="description3", publisher="id_publisher2", publish_date=1488286171, watched=False) ] db = Database(":memory:") db.add_channel(Channel(displayname="publisher1", yt_channelid="id_publisher1")) db.add_channel(Channel(displayname="publisher2", yt_channelid="id_publisher2")) db.add_channel(Channel(displayname="publisher3", yt_channelid="id_publisher3")) db.add_videos(insert_list) return db
def setUp(self): self.current_dir = os.path.dirname(__file__) self.ytcc = Ytcc(os.path.join(self.current_dir, "data/ytcc_test.conf")) self.db_conn = self.ytcc.database insert_list = [ Video(yt_videoid="V-ozGFl3Jks", title="tmptYnCut", description="", publisher="UCsLiV4WJfkTEHH0b9PmRklw", publish_date=1488348731.0, watched=True), Video(yt_videoid="a1gOeiyIqPs", title="tmp99Yc1l", description="", publisher="UCsLiV4WJfkTEHH0b9PmRklw", publish_date=1488348519.0, watched=True), Video(yt_videoid="0ounUgOrcqo", title="tmppfXKp6", description="", publisher="UCsLiV4WJfkTEHH0b9PmRklw", publish_date=1488345630.0, watched=True), Video(yt_videoid="7mckB-NdKWY", title="tmpiM62pN", description="", publisher="UCsLiV4WJfkTEHH0b9PmRklw", publish_date=1488345565.0, watched=False), Video(yt_videoid="RmRPt93uAsQ", title="tmpIXBgjd", description="", publisher="UCsLiV4WJfkTEHH0b9PmRklw", publish_date=1488344217.0, watched=False), Video(yt_videoid="nDPy3RyKdrg", title="tmpwA0TjG", description="", publisher="UCsLiV4WJfkTEHH0b9PmRklw", publish_date=1488343000.0, watched=False), Video(yt_videoid="L0_F805qUIM", title="tmpKDOkro", description="", publisher="UCxexYYtOetqikZqriLuTS-g", publish_date=1488344253.0, watched=True), Video(yt_videoid="lXWrdlDEzQs", title="tmpEvCR4s", description="", publisher="UCxexYYtOetqikZqriLuTS-g", publish_date=1488343152.0, watched=True), Video(yt_videoid="cCnXsCQNkr8", title="tmp1rpsWK", description="", publisher="UCxexYYtOetqikZqriLuTS-g", publish_date=1488343046.0, watched=True), Video(yt_videoid="rSxVs0XeQa4", title="tmpc5Y2pd", description="", publisher="UCxexYYtOetqikZqriLuTS-g", publish_date=1488342015.0, watched=False), Video(yt_videoid="gQAsWrGfsrw", title="tmpn1M1Oa", description="", publisher="UCxexYYtOetqikZqriLuTS-g", publish_date=1488341324.0, watched=False), ] self.db_conn.session.execute("delete from video") self.db_conn.session.execute("delete from channel") self.db_conn.add_channel( Channel(displayname="Webdriver Torso", yt_channelid="UCsLiV4WJfkTEHH0b9PmRklw")) self.db_conn.add_channel( Channel(displayname="Webdriver YPP", yt_channelid="UCxexYYtOetqikZqriLuTS-g")) self.db_conn.add_videos(insert_list) self.video = self.db_conn.session.query(Video).filter( Video.title == "tmpIXBgjd").one() self.video_id = self.video.id
def test_add_channel_duplicate(self): db = Database(":memory:") db.add_channel(Channel(displayname="Webdriver Torso", yt_channelid="UCsLiV4WJfkTEHH0b9PmRklw")) db.add_channel(Channel(displayname="Webdriver Torso2", yt_channelid="UCsLiV4WJfkTEHH0b9PmRklw"))