예제 #1
0
 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")
예제 #2
0
 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"))
예제 #3
0
파일: core.py 프로젝트: gruberma/ytcc
 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])
예제 #4
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}")
예제 #5
0
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
예제 #6
0
    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
예제 #7
0
 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"))