Ctrl K
ComunidadGuías…

tests/test_agency_reject.py

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

Archivo original ↗Preguntar a KiBot
"""驳回一家事务所:记在人身上,撤归属、删空了的实体,重跑安装与标签修复都不写回。"""
import json
import sqlite3
import tempfile
import unittest

from peach.entities import normalize_entity_name, rejected_agencies
from support.ledger import fresh_ledger
from scripts.install_agencies import collect as agency_plan
from scripts.reject_agency import apply_rows, plan
from scripts.repair_link_labels import apply_rows as repair_labels
from scripts.repair_link_labels import collect as collect_labels

STAMP = "2026-09-24T00:00:00Z"


class RejectFixture(unittest.TestCase):
    """一家只有她一个人的个人公司,一家有两个人的事务所。"""

    def setUp(self):
        self.tmp = tempfile.TemporaryDirectory()
        self.addCleanup(self.tmp.cleanup)
        self.db = fresh_ledger(self.tmp.name)
        self.con = sqlite3.connect(self.db)
        self.con.row_factory = sqlite3.Row
        self.addCleanup(self.con.close)
        held = {"agency": {"name": "株式会社Miss", "checked_at": STAMP}}
        self.con.executemany(
            "INSERT INTO entity(id,kind,canonical_name,normalized_name,metadata_json,"
            "created_at,updated_at) VALUES(?,?,?,?,?,'t','t')",
            [(11, "performer", "三上悠亚", normalize_entity_name("三上悠亚"),
              json.dumps(held, ensure_ascii=False)),
             (12, "performer", "松本一香", normalize_entity_name("松本一香"), "{}"),
             (13, "performer", "宫西光", normalize_entity_name("宫西光"), "{}"),
             (30, "agency", "株式会社Miss", normalize_entity_name("株式会社Miss"), "{}"),
             (31, "agency", "LIGHT", normalize_entity_name("LIGHT"), "{}")])
        self.con.executemany(
            "INSERT INTO entity_membership(member_id,agency_id,source,confidence,checked_at)"
            " VALUES(?,?,'minnano-av:所属事務所',1.0,?)",
            [(11, 30, STAMP), (12, 31, STAMP), (13, 31, STAMP)])
        self.con.execute(
            "INSERT INTO entity_link(entity_id,link_kind,label,url,hostname,created_at,updated_at)"
            " VALUES(30,'official','官方网站','https://miss.co.jp/','miss.co.jp','t','t')")
        self.con.execute(
            "INSERT INTO entity_external_ref(entity_id,provider,external_kind,external_id,"
            "metadata_json,last_synced_at) VALUES(30,'minnano-av','production','1215','{}',?)",
            (STAMP,))
        self.con.commit()

    def reject(self, performer, agency, reason="个人经纪公司", replacement=""):
        rows = plan(self.con, [{"performer": performer, "agency": agency, "reason": reason,
                                "replacement": replacement}])
        done = apply_rows(self.con, rows, STAMP)
        self.con.commit()
        return rows, done

    def metadata(self, entity_id):
        row = self.con.execute("SELECT metadata_json FROM entity WHERE id=?", (entity_id,))
        return json.loads(row.fetchone()[0] or "{}")

    def count(self, sql, *params):
        return self.con.execute(sql, params).fetchone()[0]


class RejectTests(RejectFixture):

    def test_her_only_company_goes_away_with_its_links_and_numbers(self):
        _, done = self.reject("三上悠亚", "株式会社Miss")
        self.assertEqual(done, {"驳回": 1, "归属": 1, "事务所": 1, "改挂": 0, "新建事务所": 0,
                                "链接标签": 0})
        self.assertEqual(self.count("SELECT count(*) FROM entity WHERE id=30"), 0)
        self.assertEqual(self.count("SELECT count(*) FROM entity_link WHERE entity_id=30"), 0)
        self.assertEqual(
            self.count("SELECT count(*) FROM entity_external_ref WHERE entity_id=30"), 0)
        self.assertEqual(self.con.execute("PRAGMA foreign_key_check").fetchall(), [])

    def test_the_rejection_stays_on_her_and_the_stale_evidence_goes(self):
        self.reject("三上悠亚", "株式会社Miss")
        found = self.metadata(11)
        self.assertNotIn("agency", found)
        self.assertEqual(rejected_agencies(found), {normalize_entity_name("株式会社Miss")})
        self.assertEqual(found["agency_rejected"][0]["source"], "user:manual")

    def test_an_agency_with_other_members_keeps_its_entity(self):
        rows, done = self.reject("松本一香", "LIGHT")
        self.assertEqual(done["事务所"], 0)
        self.assertEqual(self.count("SELECT count(*) FROM entity_membership WHERE agency_id=31"), 1)
        self.assertIn("还有 1 人", str(rows[0]["note"]))

    def test_rejecting_twice_records_it_once(self):
        self.reject("三上悠亚", "株式会社Miss")
        _, done = self.reject("三上悠亚", "株式会社Miss")
        self.assertEqual(done["驳回"], 0)
        self.assertEqual(len(self.metadata(11)["agency_rejected"]), 1)

    def test_an_unknown_performer_is_reported_not_written(self):
        rows, done = self.reject("不存在的人", "株式会社Miss")
        self.assertTrue(str(rows[0]["note"]).startswith("未取得"))
        self.assertEqual(set(done.values()), {0})

    def test_the_replacement_becomes_her_agency_and_survives_a_reinstall(self):
        """改挂到 AV 时期的事务所:实体、读音别名、归属、证据四样一致,重跑安装得出同一家。"""
        _, done = self.reject("三上悠亚", "株式会社Miss",
                              replacement="ONE'S DOUBLE(ワンズダブル)")
        self.assertEqual((done["改挂"], done["新建事务所"]), (1, 1))
        agency_id = self.count("SELECT agency_id FROM entity_membership WHERE member_id=11")
        self.assertEqual(self.count("SELECT canonical_name FROM entity WHERE id=?", agency_id),
                         "ONE'S DOUBLE")
        self.assertEqual(self.count("SELECT alias FROM entity_alias WHERE entity_id=?", agency_id),
                         "ワンズダブル")
        self.assertEqual(self.metadata(11)["agency"]["name"], "ONE'S DOUBLE(ワンズダブル)")
        self.assertEqual([item["agency"] for item in agency_plan(self.con)], ["ONE'S DOUBLE"])

    def add_link(self, label, url, hostname):
        self.con.execute(
            "INSERT INTO entity_link(entity_id,link_kind,label,url,hostname,created_at,updated_at)"
            " VALUES(11,'official',?,?,?,'t','t')", (label, url, hostname))
        self.con.commit()
        return self.count("SELECT max(id) FROM entity_link")

    def label(self, link_id):
        return self.count("SELECT label FROM entity_link WHERE id=?", link_id)

    def test_her_links_stop_speaking_for_the_rejected_agency(self):
        """官网链接上贴着的那家被驳回:有 AV 时期事务所写它,别的标签不动。"""
        wrong = self.add_link("株式会社Miss", "https://ones-double.com/people/mikami-yua/",
                              "ones-double.com")
        other = self.add_link("FALENO", "https://faleno.jp/top/actress/", "faleno.jp")
        _, done = self.reject("三上悠亚", "株式会社Miss", replacement="ONE'S DOUBLE(ワンズダブル)")
        self.assertEqual(done["链接标签"], 1)
        self.assertEqual((self.label(wrong), self.label(other)), ("ONE'S DOUBLE", "FALENO"))

    def test_without_a_replacement_the_label_falls_back_to_the_generic_one(self):
        wrong = self.add_link("株式会社Miss", "https://ones-double.com/people/mikami-yua/",
                              "ones-double.com")
        self.reject("三上悠亚", "株式会社Miss")
        self.assertEqual(self.label(wrong), "官方网站")


class WriteBackTests(RejectFixture):
    """驳回之后,站上那一格原样再来一遍:两条写回路径都要跳过。"""

    def test_the_installer_does_not_rebuild_a_rejected_agency(self):
        self.reject("三上悠亚", "株式会社Miss")
        found = self.metadata(11)
        found["agency"] = {"name": "株式会社Miss", "checked_at": STAMP}
        self.con.execute("UPDATE entity SET metadata_json=? WHERE id=11",
                         (json.dumps(found, ensure_ascii=False),))
        self.assertEqual([item["agency"] for item in agency_plan(self.con)], [])

    def test_relabelling_links_does_not_write_the_rejected_agency_back(self):
        self.reject("三上悠亚", "株式会社Miss")
        repair_labels(self.con, [{"entity_id": 11, "agency": "株式会社Miss", "verdict": "keep",
                                  "link_id": 0, "link_kind": "official",
                                  "new_label": "", "new_link_kind": "official"}], STAMP)
        self.assertNotIn("agency", self.metadata(11))

    def test_the_label_repair_rewrites_a_label_naming_a_rejected_agency(self):
        """驳回早于链接采集时,标签修复自己认出来:写着已驳回事务所的标签判 auto。"""
        self.reject("三上悠亚", "株式会社Miss")
        self.con.execute(
            "INSERT INTO entity_link(entity_id,link_kind,label,url,hostname,created_at,updated_at)"
            " VALUES(11,'official','株式会社Miss','https://ones-double.com/people/mikami-yua/',"
            "'ones-double.com','t','t')")
        found = [row for row in collect_labels(self.con) if row["entity_id"] == 11]
        self.assertEqual([(row["verdict"], row["new_label"], row["agency"]) for row in found],
                         [("auto", "官方网站", "")])


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