Ctrl K
ComunidadGuías…

tests/test_follow_avatar.py

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import json
import unittest

from peach.follow import FollowSourceError
from peach.follow_avatar import (
    profile_avatar_tiers, profile_identities, resolve_official_avatar, resolve_official_profile,
)
from peach.http import HttpResponse


class _Transport:
    def __init__(self, responses):
        self.responses = list(responses)
        self.requests = []

    def __call__(self, request, _timeout, _max_bytes):
        self.requests.append(request)
        return self.responses.pop(0)


class OfficialAvatarTests(unittest.TestCase):
    def _responses(self, *, user_id="30917150",
                   icon="https://pixiv.pximg.net/c/160x160/icon.jpeg"):
        metadata = {"urlContext": {"host": {"creatorId": "lazyprocrast"}}}
        page = (
            "<html><meta name='metadata' content='"
            + json.dumps(metadata).replace("'", "&#39;")
            + "'></html>"
        ).encode()
        api = json.dumps({"body": {"user": {
            "userId": user_id, "name": "LazyProcrastinator", "iconUrl": icon,
        }}}).encode()
        return [HttpResponse(200, {"content-type": "text/html"}, page),
                HttpResponse(200, {"content-type": "application/json"}, api)]

    def test_fanbox_avatar_comes_from_the_official_creator_profile(self):
        transport = _Transport(self._responses())
        avatar = resolve_official_avatar("fanbox", "30917150", transport=transport)
        self.assertEqual(avatar, "https://pixiv.pximg.net/c/160x160/icon.jpeg")
        self.assertEqual(transport.requests[0].url,
                         "https://www.pixiv.net/fanbox/creator/30917150")
        self.assertIn("creatorId=lazyprocrast", transport.requests[1].url)
        self.assertEqual(transport.requests[1].headers["Origin"],
                         "https://lazyprocrast.fanbox.cc")

    def test_the_same_verified_lookup_returns_the_official_profile(self):
        profile = resolve_official_profile(
            "fanbox", "30917150", transport=_Transport(self._responses()))
        self.assertEqual(profile.creator_id, "lazyprocrast")
        self.assertEqual(profile.name, "LazyProcrastinator")
        self.assertEqual(profile.url, "https://lazyprocrast.fanbox.cc/")

    def test_the_official_api_must_return_the_requested_user(self):
        with self.assertRaises(FollowSourceError):
            resolve_official_avatar(
                "fanbox", "30917150", transport=_Transport(
                    self._responses(user_id="999")))

    def test_the_avatar_cannot_redirect_to_an_untrusted_host(self):
        with self.assertRaises(FollowSourceError):
            resolve_official_avatar(
                "fanbox", "30917150", transport=_Transport(
                    self._responses(icon="https://example.test/avatar.jpg")))

    def test_only_verified_fanbox_identities_are_accepted(self):
        for service, user in (("patreon", "30917150"), ("fanbox", "../secret"),
                              ("fanbox", "")):
            with self.assertRaises(FollowSourceError):
                resolve_official_avatar(service, user, transport=_Transport([]))

    def test_a_creator_id_skips_the_lookup_page(self):
        """论坛名片上只有 `jul3dnsfw.fanbox.cc` 这一个身份,没有 pixiv 的数字 id。

        `creator.get` 本来就收创作者 id,那一步换算可以省掉。
        """
        transport = _Transport(self._responses()[1:])
        avatar = resolve_official_avatar("fanbox", "lazyprocrast",
                                         transport=transport)
        self.assertEqual(avatar, "https://pixiv.pximg.net/c/160x160/icon.jpeg")
        self.assertEqual(len(transport.requests), 1)
        self.assertIn("creatorId=lazyprocrast", transport.requests[0].url)

    def test_a_pixiv_profile_link_resolves_through_the_same_fanbox_lookup(self):
        transport = _Transport(self._responses())
        self.assertEqual(profile_avatar_tiers("pixiv", "30917150", transport=transport),
                         ["https://pixiv.pximg.net/c/160x160/icon.jpeg"])
        self.assertEqual(transport.requests[0].url,
                         "https://www.pixiv.net/fanbox/creator/30917150")

    def test_a_creator_id_still_needs_a_real_user_behind_it(self):
        # 没有可核对的数字 id 时,身份以官方资料回的为准;回不出就是没有头像。
        with self.assertRaises(FollowSourceError):
            resolve_official_avatar("fanbox", "lazyprocrast", transport=_Transport(
                self._responses(user_id="")[1:]))


class ProfileAvatarTests(unittest.TestCase):
    """论坛名片上的 X、Patreon 与 pixiv:各给一串从原图到小图的地址,主机写死。"""

    @staticmethod
    def _page(image):
        body = f'<html><meta property="og:image" content="{image}"></html>'.encode()
        return HttpResponse(200, {"content-type": "text/html"}, body)

    @staticmethod
    def _campaigns(vanity="sharkarts",
                   host="c10.patreonusercontent.com"):
        return HttpResponse(200, {"content-type": "application/json"}, json.dumps({"data": [
            {"attributes": {"vanity": vanity, "avatar_photo_image_urls": {
                "original": f"https://{host}/p/campaign/1/original.png",
                "default": f"https://{host}/p/campaign/1/default.png",
            }}}]}).encode())

    def test_x_avatar_tiers_come_from_the_logged_out_profile_page(self):
        transport = _Transport([self._page(
            "https://pbs.twimg.com/profile_images/1334790870760042496/QzmzhT0y_200x200.jpg")])
        tiers = profile_avatar_tiers("twitter", "Rekin3D", transport=transport)
        self.assertEqual(transport.requests[0].url, "https://x.com/Rekin3D")
        self.assertEqual(tiers[0],
                         "https://pbs.twimg.com/profile_images/1334790870760042496/QzmzhT0y.jpg")
        self.assertEqual(len(tiers), 3)

    def test_an_x_page_without_its_own_avatar_has_none(self):
        with self.assertRaises(FollowSourceError):
            profile_avatar_tiers("twitter", "Rekin3D", transport=_Transport([
                self._page("https://abs.twimg.com/rich_link_card.png")]))

    def test_litlink_avatar_uses_the_profile_icon_original(self):
        original = "https://prd.storage.lit.link/images/creator/example/profile.jpeg"
        body = ('<img alt="profile icon" src="https://prd.resource-api.lit.link/v1/images/resized'
                '?image_url=images/creator/example/profile.jpeg&amp;width=240">'
                f'<script>{json.dumps({"pictureUrl": original})}</script>')
        transport = _Transport([HttpResponse(200, {}, body.encode())])
        self.assertEqual(profile_avatar_tiers("litlink", "example", transport=transport), [original])
        self.assertEqual(transport.requests[0].url, "https://lit.link/example")
        self.assertEqual(profile_identities("litlink:example"), (("litlink", "example"),))

    def test_litlink_share_posters_and_foreign_hosts_are_not_profile_avatars(self):
        bodies = [
            '<meta property="og:image" content="https://prd.storage.lit.link/images/creators/a/ogp/ogp_image.jpg">',
            '<img alt="profile icon" src="https://example.test/avatar.jpg">',
            '<img alt="profile icon" src="https://prd.resource-api.lit.link/v1/images/resized?image_url=images/creators/a/ogp/ogp_image.jpg">',
        ]
        for body in bodies:
            with self.subTest(body=body), self.assertRaises(FollowSourceError):
                profile_avatar_tiers("litlink", "example", transport=_Transport([
                    HttpResponse(200, {}, body.encode())]))

    def test_patreon_avatar_starts_from_the_uploaded_original(self):
        transport = _Transport([self._campaigns()])
        tiers = profile_avatar_tiers("patreon", "sharkarts", transport=transport)
        self.assertIn("filter%5Bvanity%5D=sharkarts", transport.requests[0].url)
        self.assertEqual(tiers, [
            "https://c10.patreonusercontent.com/p/campaign/1/original.png",
            "https://c10.patreonusercontent.com/p/campaign/1/default.png",
        ])

    def test_patreon_must_answer_for_the_same_creator_on_its_own_image_host(self):
        for response in (self._campaigns(vanity="someoneelse"),
                         self._campaigns(host="example.test")):
            with self.subTest(response=response.body[:60]), \
                    self.assertRaises(FollowSourceError):
                profile_avatar_tiers("patreon", "sharkarts", transport=_Transport([response]))

    def test_profile_identities_accept_only_known_services_and_handle_shapes(self):
        self.assertEqual(profile_identities("twitter:Rekin3D,patreon:sharkarts,pixiv:14934767"),
                         (("twitter", "Rekin3D"), ("patreon", "sharkarts"),
                          ("pixiv", "14934767")))
        for value in ("", "twitter:../x", "fanbox:jul3dnsfw", "pixiv:flim13",
                      "twitter:Rekin3D,patreon:a/b",
                      ",".join(f"patreon:user{index}" for index in range(5))):
            with self.subTest(value=value):
                self.assertEqual(profile_identities(value), ())
        for service, handle in (("twitter", "../x"), ("fanbox", "jul3dnsfw")):
            with self.subTest(service=service), self.assertRaises(FollowSourceError):
                profile_avatar_tiers(service, handle, transport=_Transport([]))


if __name__ == "__main__":
    unittest.main()