예제 #1
0
    def test_ConvertWebp(self):
        """webp形式の画像ファイルをpngに変換する機能をチェック
        """
        with ExitStack() as stack:
            mockgt = stack.enter_context(
                patch("PictureGathering.LSSkeb.LSSkeb.GetToken"))
            mockgt = self.__MakeGetTokenMock(mockgt)
            lssk_cont = LSSkeb.LSSkeb(self.twitter_id, self.twitter_password,
                                      self.TEST_BASE_PATH)

            def ReturnImage(target_path):
                r = MagicMock()
                type(r).convert = lambda s, m: r
                type(r).save = lambda s, fp: fp.touch()
                return r if target_path.is_file() else None

            mockimg = stack.enter_context(
                patch("PictureGathering.LSSkeb.Image.open"))
            mockimg.side_effect = ReturnImage

            # 正常系
            EXT = ".png"
            self.TBP.mkdir(exist_ok=True, parents=True)
            e_target_path = self.TBP / "illust.webp"
            e_target_path.touch()
            expect = str(e_target_path.with_suffix(EXT))
            actual = lssk_cont.ConvertWebp(e_target_path)
            self.assertIsNotNone(actual)
            self.assertTrue(actual.is_file())
            self.assertFalse(e_target_path.is_file())
            self.assertEqual(expect, str(actual))

            # 異常系
            # 存在しないファイルを指定
            self.TBP.mkdir(exist_ok=True, parents=True)
            e_target_path = self.TBP / "illust.webp"
            e_target_path.unlink(missing_ok=True)
            actual = lssk_cont.ConvertWebp(e_target_path)
            self.assertIsNone(actual)
예제 #2
0
    def test_GetUserWorkID(self):
        """Skeb作品ページURLから作者アカウント名と作品idを取得する機能をチェック
        """
        with ExitStack() as stack:
            mockgt = stack.enter_context(
                patch("PictureGathering.LSSkeb.LSSkeb.GetToken"))
            mockgt = self.__MakeGetTokenMock(mockgt)
            lssk_cont = LSSkeb.LSSkeb(self.twitter_id, self.twitter_password,
                                      self.TEST_BASE_PATH)

            # 正常系
            author_name_s = "author_name"
            work_id_s = random.randint(1, 100)
            url_s = f"https://skeb.jp/@{author_name_s}/works/{work_id_s}"
            actual = lssk_cont.GetUserWorkID(url_s)
            self.assertEqual((author_name_s, work_id_s), actual)

            # 異常系
            # 全く関係ないアドレス(Google)
            url_s = "https://www.google.co.jp/"
            actual = lssk_cont.GetUserWorkID(url_s)
            self.assertEqual(("", -1), actual)
예제 #3
0
    def test_MakeCallbackURL(self):
        """コールバックURLを生成する機能をチェック
        """
        with ExitStack() as stack:
            mockgt = stack.enter_context(
                patch("PictureGathering.LSSkeb.LSSkeb.GetToken"))
            mockgt = self.__MakeGetTokenMock(mockgt)
            lssk_cont = LSSkeb.LSSkeb(self.twitter_id, self.twitter_password,
                                      self.TEST_BASE_PATH)

            # 正常系
            # 通常
            e_top_url = "https://skeb.jp/"
            e_path = "ok_path"
            e_token = "ok_token"
            expect = f"{e_top_url}callback?path=/{e_path}&token={e_token}"
            actual = lssk_cont.MakeCallbackURL(e_path, e_token)
            self.assertEqual(expect, actual)

            # pathの先頭と末尾に"/"が含まれていても処理可能かどうか
            expect = f"{e_top_url}callback?path=/{e_path}&token={e_token}"
            actual = lssk_cont.MakeCallbackURL("/" + e_path, e_token)
            self.assertEqual(expect, actual)
            actual = lssk_cont.MakeCallbackURL("/" + e_path + "/", e_token)
            self.assertEqual(expect, actual)
            actual = lssk_cont.MakeCallbackURL(e_path + "/", e_token)
            self.assertEqual(expect, actual)

            # pathが"/"のみの場合
            expect = f"{e_top_url}callback?path=/&token={e_token}"
            actual = lssk_cont.MakeCallbackURL("/", e_token)
            self.assertEqual(expect, actual)

            # 異常系
            # top_urlが壊れている
            del lssk_cont.top_url
            actual = lssk_cont.MakeCallbackURL(e_path, e_token)
            self.assertEqual("", actual)
예제 #4
0
    def test_MakeSaveDirectoryPath(self):
        """保存先ディレクトリパスを生成する機能をチェック
        """
        with ExitStack() as stack:
            mockgt = stack.enter_context(
                patch("PictureGathering.LSSkeb.LSSkeb.GetToken"))
            mockgt = self.__MakeGetTokenMock(mockgt)
            lssk_cont = LSSkeb.LSSkeb(self.twitter_id, self.twitter_password,
                                      self.TEST_BASE_PATH)

            # 正常系
            author_name_s = "author_1"
            work_id_s = 1
            url_s = f"https://skeb.jp/@{author_name_s}/works/{work_id_s}"
            expect = self.TBP / author_name_s / f"{work_id_s:03}"
            actual = lssk_cont.MakeSaveDirectoryPath(url_s, self.TBP)
            self.assertEqual(str(expect), actual)

            # 異常系
            # 不正なURL
            url_s = f"https://skeb.jp/invalid_url"
            actual = lssk_cont.MakeSaveDirectoryPath(url_s, self.TBP)
            self.assertEqual("", actual)
예제 #5
0
    def LinkSearchRegister(self) -> int:
        """外部リンク探索機構のセットアップ

        Notes:
            self.lsbに設定する

        Returns:
            int: 成功時0
        """
        # 外部リンク探索を登録
        self.lsb = LinkSearchBase.LinkSearchBase()
        # pixivURLを処理する担当者を登録
        config = self.config["pixiv"]
        if config.getboolean("is_pixiv_trace"):
            lsp = LSPixiv.LSPixiv(config["username"], config["password"], config["save_base_path"])
            self.lsb.Register(lsp)
            lspn = LSPixivNovel.LSPixivNovel(config["username"], config["password"], config["save_base_path"])
            self.lsb.Register(lspn)

        # nijieURLを処理する担当者を登録
        config = self.config["nijie"]
        if config.getboolean("is_nijie_trace"):
            lsn = LSNijie.LSNijie(config["email"], config["password"], config["save_base_path"])
            self.lsb.Register(lsn)

        # ニコニコ静画のURLを処理する担当者を登録
        config = self.config["nico_seiga"]
        if config.getboolean("is_seiga_trace"):
            lsns = LSNicoSeiga.LSNicoSeiga(config["email"], config["password"], config["save_base_path"])
            self.lsb.Register(lsns)

        # ニコニコ静画のURLを処理する担当者を登録
        config = self.config["skeb"]
        if config.getboolean("is_skeb_trace"):
            lssk = LSSkeb.LSSkeb(config["twitter_id"], config["twitter_password"], config["save_base_path"])
            self.lsb.Register(lssk)
예제 #6
0
    def test_DownloadWorks(self):
        """作品をダウンロードする機能をチェック
           実際にアクセスしてDLはしない
        """
        with ExitStack() as stack:
            # open()をモックに置き換える
            # mockfout = mock_open()
            # mockfp = stack.enter_context(patch("pathlib.Path.open", mockfout))
            mockle = stack.enter_context(patch.object(logger, "error"))
            mockli = stack.enter_context(patch.object(logger, "info"))
            mockrequest = stack.enter_context(
                patch("PictureGathering.LSSkeb.requests.get"))
            mockcw = stack.enter_context(
                patch("PictureGathering.LSSkeb.LSSkeb.ConvertWebp"))
            mockgt = stack.enter_context(
                patch("PictureGathering.LSSkeb.LSSkeb.GetToken"))
            mockgt = self.__MakeGetTokenMock(mockgt)
            lssk_cont = LSSkeb.LSSkeb(self.twitter_id, self.twitter_password,
                                      self.TEST_BASE_PATH)

            # 正常系
            # サイドエフェクト設定
            def ReturnConvertWebp(target_path: Path, ext: str = ".png"):
                dst_path = target_path.with_suffix(ext)
                shutil.copy(target_path, dst_path)
                target_path.unlink(missing_ok=True)
                return dst_path

            def ReturnGet(url, headers):
                response = MagicMock()
                type(response).content = str(url).encode()
                return response

            mockcw.side_effect = ReturnConvertWebp
            mockrequest.side_effect = ReturnGet

            # 検証用作者アカウント名等設定
            NUM = 3  # 検証用作者アカウント数
            work_id = 0  # 作品id(インクリメントされる)
            # 変換処理用辞書
            p_dict = {
                "illust": (True, ".webp", ".png"),
                "video": (False, ".mp4", ".mp4"),
            }
            # 検証用作者名リスト
            author_name_list = [f"author_{i}" for i in range(1, NUM + 1)]
            # タイプリスト
            type_list = ["illust", "video"]
            # すべての検証用作者アカウント,タイプについて検証する
            for author_name in author_name_list:
                for type_s in type_list:
                    # 単一作品と複数作品について検証する
                    urls_list = [
                        ["https://skeb.resource.test/001_xxx?yyy"],  # 単一
                        [
                            f"https://skeb.resource.test/{i:03}_xxx?yyy"
                            for i in range(1, random.randint(3, NUM + 3))
                        ],  # 複数
                    ]
                    for urls in urls_list:
                        # source_list設定
                        # work_id = random.randint(1, NUM * 2)
                        work_id = work_id + 1
                        dst_ext = p_dict.get(type_s, (False, "", ""))[2]
                        source_list_s = [(url, type_s) for url in urls]

                        # save_directory_path設定
                        url_s = f"https://skeb.jp/@{author_name}/works/{work_id}"
                        save_directory_path = lssk_cont.MakeSaveDirectoryPath(
                            url_s, self.TBP)
                        sd_path = Path(save_directory_path)

                        # 1回目の実行
                        actual = lssk_cont.DownloadWorks(
                            source_list_s, save_directory_path)
                        self.assertEqual(0, actual)

                        # DL後のディレクトリ構成とファイルの存在チェック
                        sd_path = Path(save_directory_path)
                        if len(source_list_s) > 1:
                            # 複数作品
                            expect_names = []
                            for i, src in enumerate(source_list_s):
                                file_name = f"{author_name}_{work_id:03}_{i:03}{dst_ext}"
                                expect_names.append(file_name)

                            self.assertTrue(self.TBP.is_dir())
                            self.assertTrue(sd_path.is_dir())
                            for name_s in expect_names:
                                self.assertTrue((sd_path / name_s).is_file())
                        else:
                            # 単一作品
                            file_name = f"{author_name}_{work_id:03}{dst_ext}"
                            self.assertTrue(self.TBP.is_dir())
                            self.assertTrue(sd_path.parent.is_dir())
                            self.assertTrue(
                                (sd_path.parent / file_name).is_file())

                        # requests.getが呼ばれたかどうか確認
                        mockrequest.assert_called()
                        mockrequest.reset_mock()

                        # 変換処理をする設定なら変換処理が呼ばれたかどうか確認
                        if p_dict.get(type_s, (False, "", ""))[0]:
                            mockcw.assert_called()
                            mockcw.reset_mock()
                        else:
                            mockcw.assert_not_called()

                        # 2回目の実行
                        actual = lssk_cont.DownloadWorks(
                            source_list_s, save_directory_path)
                        self.assertEqual(1, actual)
                        pass

            # 異常系
            # requests.getに失敗
            def ReturnGetFailed(url, headers):
                response = MagicMock()
                response.raise_for_status.side_effect = Exception(
                    "Mock Exception")
                return response

            mockrequest.side_effect = ReturnGetFailed
            urls_list = [
                ["https://skeb.resource.test/001_xxx?yyy"],  # 単一
                [
                    f"https://skeb.resource.test/{i:03}_xxx?yyy"
                    for i in range(1, random.randint(3, NUM + 3))
                ],  # 複数
            ]
            for urls in urls_list:
                source_list_s = [(url, "illust") for url in urls]
                url_s = f"https://skeb.jp/@author_1/works/99"
                save_directory_path = lssk_cont.MakeSaveDirectoryPath(
                    url_s, self.TBP)
                with self.assertRaises(Exception):
                    actual = lssk_cont.DownloadWorks(source_list_s,
                                                     save_directory_path)

            # タイプが不正
            mockrequest.side_effect = ReturnGet
            for urls in urls_list:
                source_list_s = [(url, "invlid_type") for url in urls]
                url_s = f"https://skeb.jp/@author_2/works/99"
                save_directory_path = lssk_cont.MakeSaveDirectoryPath(
                    url_s, self.TBP)

                actual = lssk_cont.DownloadWorks(source_list_s,
                                                 save_directory_path)
                self.assertEqual(-1, actual)
            pass
예제 #7
0
    def test_GetWorkURLs(self):
        """Skeb作品ページURLから作品URLを取得する機能をチェック
        """
        with ExitStack() as stack:
            mockle = stack.enter_context(patch.object(logger, "error"))
            mocksession = stack.enter_context(
                patch("PictureGathering.LSSkeb.HTMLSession"))
            mockgt = stack.enter_context(
                patch("PictureGathering.LSSkeb.LSSkeb.GetToken"))
            mockgt = self.__MakeGetTokenMock(mockgt)
            lssk_cont = LSSkeb.LSSkeb(self.twitter_id, self.twitter_password,
                                      self.TEST_BASE_PATH)

            work_id_s = 1

            def ReturnSession():
                response = MagicMock()

                def ReturnGet(s, url, headers):
                    r_get = MagicMock()

                    def ReturnFind(key):
                        r_find = MagicMock()
                        sd = self.__GetSkebData(work_id_s)

                        if work_id_s == 1 and key == "img":
                            # イラスト
                            r_find.attrs = {"src": sd.get("url", "")}
                        elif work_id_s == 2 and key == "video":
                            # gif
                            r_find.attrs = {
                                "preload": "auto",
                                "autoplay": "autoplay",
                                "muted": "muted",
                                "loop": "loop",
                                "src": sd.get("url", "")
                            }
                        elif work_id_s == 3 and key == "source":
                            # 動画
                            r_find.attrs = {
                                "type": "video/mp4",
                                "src": sd.get("url", "")
                            }
                        else:
                            return []

                        return [r_find]

                    r_get.html.find = ReturnFind
                    return r_get

                type(response).get = ReturnGet
                return response

            # 正常系
            # イラスト
            mocksession.side_effect = ReturnSession
            author_name_s = "author_1"
            work_id_s = 1
            url_s = f"https://skeb.jp/@{author_name_s}/works/{work_id_s}"
            sd = self.__GetSkebData(work_id_s)
            expect = [(sd.get("url", ""), "illust")]
            actual = lssk_cont.GetWorkURLs(url_s)
            self.assertEqual(expect, actual)

            # gif
            work_id_s = 2
            url_s = f"https://skeb.jp/@{author_name_s}/works/{work_id_s}"
            sd = self.__GetSkebData(work_id_s)
            expect = [(sd.get("url", ""), "video")]
            actual = lssk_cont.GetWorkURLs(url_s)
            self.assertEqual(expect, actual)

            # 動画
            work_id_s = 3
            url_s = f"https://skeb.jp/@{author_name_s}/works/{work_id_s}"
            sd = self.__GetSkebData(work_id_s)
            expect = [(sd.get("url", ""), "video")]
            actual = lssk_cont.GetWorkURLs(url_s)
            self.assertEqual(expect, actual)

            # どのリソースも取得できなかった
            work_id_s = 4
            url_s = f"https://skeb.jp/@{author_name_s}/works/{work_id_s}"
            expect = []
            actual = lssk_cont.GetWorkURLs(url_s)
            self.assertEqual(expect, actual)

            # 異常系
            # URLが不正
            work_id_s = 1
            url_s = f"https://skeb.jp/invalid_url/{work_id_s}"
            expect = []
            actual = lssk_cont.GetWorkURLs(url_s)
            self.assertEqual(expect, actual)

            pass
예제 #8
0
    def test_GetTokenFromOAuth(self):
        """ツイッターログインを行いSkebページで使うtokenを取得する機能をチェック
        """
        with ExitStack() as stack:
            mockle = stack.enter_context(patch.object(logger, "error"))
            mockli = stack.enter_context(patch.object(logger, "info"))
            mockpl = stack.enter_context(patch("pyppeteer.launch"))
            mockgt = stack.enter_context(
                patch("PictureGathering.LSSkeb.LSSkeb.GetToken"))
            mockgt = self.__MakeGetTokenMock(mockgt)
            lssk_cont = LSSkeb.LSSkeb(self.twitter_id, self.twitter_password,
                                      self.TEST_BASE_PATH)

            # 正常系
            expect = "ok_token"
            callback_url = f"https://skeb.jp/callback?path=/&token={expect}"
            selector_mock = AsyncMock()
            mockpl, r_launch, r_np = self.__MakePyppeteerMock(
                mockpl, callback_url, [None, selector_mock])
            loop = asyncio.new_event_loop()
            actual = loop.run_until_complete(
                lssk_cont.GetTokenFromOAuth(self.twitter_id,
                                            self.twitter_password))
            self.assertEqual(expect, actual)

            # 正常系の呼び出し確認
            expect_newPage_call = [
                "goto",
                "waitForNavigation",
                "content",
                "cookies",
                "waitForNavigation",
                "content",
                "cookies",
                "waitFor",
                "type",
                "waitFor",
                "type",
                "waitFor",
                "click",
                "waitForNavigation",
                "waitForNavigation",
                "content",
                "cookies",
            ]
            self.assertEqual(len(expect_newPage_call), len(r_np.mock_calls))
            for enc, npc in zip(expect_newPage_call, r_np.mock_calls):
                self.assertEqual(enc, npc[0])

            # 異常系
            # コールバックURLがキャッチできなかった
            # ツイッターログインに失敗した場合もこちら
            callback_url = f"https://skeb.jp/invalid_url"
            selector_mock = AsyncMock()
            mockpl, r_launch, r_np = self.__MakePyppeteerMock(
                mockpl, callback_url, [None, selector_mock])
            loop = asyncio.new_event_loop()
            actual = loop.run_until_complete(
                lssk_cont.GetTokenFromOAuth(self.twitter_id,
                                            self.twitter_password))
            self.assertEqual("", actual)

            # ログインボタンセレクト失敗
            expect = "ok_token"
            callback_url = f"https://skeb.jp/callback?path=/&token={expect}"
            mockpl, r_launch, r_np = self.__MakePyppeteerMock(
                mockpl, callback_url, [None, None])
            loop = asyncio.new_event_loop()
            actual = loop.run_until_complete(
                lssk_cont.GetTokenFromOAuth(self.twitter_id,
                                            self.twitter_password))
            self.assertEqual("", actual)
            pass