""" YouTube Content ID models. """ from dataclasses import dataclass, field from typing import Any from ....config import YT_OWNER_ID_ORCHARD from ....constants import YtCid as YT from ....typings import ( ISRC, ISWC, AssetID, ClaimID, CountryCode2, Numeric, OptionalStrDict, VideoID, ) from ..models import _BaseModel @dataclass class AssetLookupResult(_BaseModel): """A YouTube asset lookup result. Schema: https://developers.google.com/youtube/partner/reference/rest/v1/assetSearch """ id: AssetID kind: str type: str title: str = field(default="") custom_id: str | None = None isrc: ISRC | None = None isrcs: list[ISRC] | None = field(default_factory=list) iswc: ISWC | None = None iswcs: list[ISWC] | None = field(default_factory=list) time_created: str | None = None @dataclass class Asset(_BaseModel): """A YouTube asset. Schema: https://developers.google.com/youtube/partner/reference/rest/v1/assets """ id: AssetID kind: str type: str time_created: str alias_id: list[str] | None = None label: list[str] | None = None status: str | None = None metadata: OptionalStrDict = None metadata_mine: OptionalStrDict = None metadata_effective: OptionalStrDict = None ownership: OptionalStrDict = None ownership_mine: OptionalStrDict = None ownership_effective: OptionalStrDict = None ownership_conflicts: OptionalStrDict = None match_policy: OptionalStrDict = None match_policy_mine: OptionalStrDict = None match_policy_effective: OptionalStrDict = None licensability: OptionalStrDict = None n_way_revenue_sharing: OptionalStrDict = None @dataclass class AssetRelationships(_BaseModel): """A YouTube asset relationships object. For a given asset, this object contains a list of parent assets and a list of child assets. """ id: AssetID parents: list[AssetID] = field(default_factory=list) children: list[AssetID] = field(default_factory=list) @property def related_assets(self) -> list[AssetID]: """Return a list of related assets IDs, including parents and children.""" return self.parents + self.children @dataclass class MetadataHistory(_BaseModel): """A YouTube metadata history object. Schema: https://developers.google.com/youtube/partner/reference/rest/v1/metadataHistory """ kind: str metadata: dict[str, Any] origination: dict[str, Any] time_provided: str @dataclass class Reference(_BaseModel): """A YouTube reference. Schema: https://developers.google.com/youtube/partner/reference/rest/v1/references#Reference Custom properties: owned_own (bool): Whether the reference is owned by us. conflicts (bool): Whether the reference has conflicts, regardless of ownership. conflicts_own (bool): Whether a reference owned by us has conflicts. """ id: str kind: str origination: dict[str, Any] asset_id: AssetID | None = None status: str | None = None status_reason: str | None = None length: int | None = None hash_code: str | None = None urgent: bool | None = None fp_direct: bool | None = None content_type: str | None = None audioswap_enabled: bool | None = None ignore_fp_match: bool | None = None excluded_intervals: list[dict[str, Any]] | None = None duplicate_leader: str | None = None claim_id: str | None = None video_id: VideoID | None = None owned_own: bool = field(init=False) conflicts: bool = field(init=False) conflicts_own: bool = field(init=False) def __post_init__(self): """Post-initialization hook.""" self.owned_own = self._check_if_own() self.conflicts = self._conflicts self.conflicts_own = self._conflicts_own @property def _conflicts(self) -> bool: """Whether the reference has conflicts.""" return self._check_for_conflicts() @property def _conflicts_own(self) -> bool: """Whether a reference owned by us has conflicts.""" return self._check_if_own() and self._check_for_conflicts() def _check_for_conflicts(self) -> bool: """Check if the reference has conflicts.""" # Keep method separate from property to avoid recursion issues. if not self.excluded_intervals: return False excluded_intervals_with_origin = ( interval for interval in self.excluded_intervals if YT.ORIGIN in interval ) return any( interval[YT.ORIGIN] == YT.REFERENCE_CONFLICT for interval in excluded_intervals_with_origin ) def _check_if_own(self) -> bool: """Check if the reference is owned by us.""" # Keep method separate from property to avoid recursion issues. return self.origination[YT.OWNER] == YT_OWNER_ID_ORCHARD @dataclass class Ownership: """A YouTube ownership object for a given asset. An asset may have multiple ownership objects, each representing a different owner or ownership type. Schema: https://developers.google.com/youtube/partner/reference/rest/v1/ownership Properties: asset_id (str): The asset ID. owner (str): The owner of the asset. type (str): The type of the ownership. ratio (float): The ownership ratio. territories (list[str]): The territories in which the asset is owned, represented by their ISO 3166-1 alpha-2 codes. """ asset_id: AssetID owner: str type: str ratio: Numeric territories: list[CountryCode2] def __len__(self) -> int: """Return the number of territories in the ownership object, if any.""" return len(self.territories) @dataclass class Claim: """A YouTube claim object. Schema: https://developers.google.com/youtube/partner/reference/rest/v1/claims Properties: id (str): The claim ID. kind (str): The kind of the claim. time_created (str): The time the claim was created. content_type (str): The content type of the claim. is_partner_uploaded (bool): Whether the claim is partner uploaded. time_status_last_modified (str): The time the status of the claim was last modified. block_outside_ownership (bool): Whether the claim blocks outside ownership. status (str): The status of the claim. asset_id (str): The asset ID. video_id (str): The video ID. ugc_type (str): The UGC type of the claim. policy (dict): The policy of the claim. applied_policy (dict): The applied policy of the claim. match_info (dict): The match info of the claim. studio_info (dict): The studio info of the claim. origin (dict): The origin of the claim. """ id: ClaimID kind: str time_created: str content_type: str is_partner_uploaded: bool time_status_last_modified: str block_outside_ownership: bool status: str asset_id: AssetID video_id: VideoID ugc_type: str | None = None policy: OptionalStrDict = None applied_policy: OptionalStrDict = None match_info: OptionalStrDict = None studio_info: OptionalStrDict = None origin: OptionalStrDict = None