import datetime from pydantic import BaseModel, ConfigDict, Field, Json from dmp.api.schemas import LabelId, LimitOffsetPage from dmp.artists.dtos import CampaignType from dmp.artists.enums import ArtistFanDataType, ParticipantType from dmp.fandata.enums import ( AcquisitionChannel, AgeRange, FanSegment, Gender, HeavyRotation, SegmentExplainedResponseLanguage, ) # Always populate by name BaseModel.model_config["populate_by_name"] = True class Artist(BaseModel): global_participant_id: str = Field(alias="globalParticipantId") name: str labels: list[LabelId] model_config = ConfigDict(from_attributes=True) class GetArtistsInput(BaseModel): vendor_id: int | None = Field( None, alias="vendorId", description="Account vendor id", ) subaccount_id: int | None = Field( None, alias="subaccountId", description="Account subaccount id", ) search: str | None = Field( None, description="Search by partial name match", ) participant_type: ParticipantType | None = Field( None, alias="type", description="Filter by participant type: ARTIST or CUSTOM_LIST", ) virtual_participant_ids: list[str] | None = Field( None, alias="virtualParticipantIds", description="Filter by specific virtual participant IDs", ) limit: int | None = Field( None, ge=1, le=200, description="Page size limit", ) offset: int | None = Field( None, ge=0, description="Page offset", ) class GetArtistsOutput(LimitOffsetPage[Artist]): model_config = ConfigDict(from_attributes=True) class GetArtistAccountsWithFanDataOutput(BaseModel): has_fandata: bool = Field(alias="hasFanData") has_global_fandata_list: bool = Field(alias="hasGlobalFanDataList") accounts: list[LabelId] class ArtistAccount(BaseModel): vendor_id: int = Field(alias="vendorId") subaccount_id: int = Field(alias="subaccountId") fans_count: int = Field(alias="fansCount", default=0) class ArtistFansCountOutput(BaseModel): fans_count: int = Field(alias="fansCount") email_consent_fans_count: int = Field(alias="emailConsentFansCount") ad_consent_fans_count: int = Field(alias="adConsentFansCount") sms_consent_fans_count: int = Field(default=0, alias="smsConsentFansCount") class ArtistAccountInput(BaseModel): vendor_id: int | None = Field(default=None, alias="vendorId") subaccount_id: int | None = Field(default=None, alias="subaccountId") class GetArtistFanReportByCountriesInput(ArtistAccountInput): countries: list[str] | None = Field(None) class GetArtistSegmenstExplainedByCountriesInput(ArtistAccountInput): countries: list[str] | None = Field(None) language: SegmentExplainedResponseLanguage class GetArtistFanReportByTypeInput(GetArtistFanReportByCountriesInput): start_date: datetime.date = Field(alias="startDate", description="Start date") end_date: datetime.date = Field(alias="endDate", description="End date") type: ArtistFanDataType class GetArtistFanReportByCampaignInput(GetArtistFanReportByCountriesInput): start_date: datetime.date = Field(alias="startDate", description="Start date") end_date: datetime.date = Field(alias="endDate", description="End date") class GetArtistFanTimeseriesByTypeInput(GetArtistFanReportByCountriesInput): start_date: datetime.date = Field(alias="startDate", description="Start date") end_date: datetime.date = Field(alias="endDate", description="End date") type: ArtistFanDataType totals_countries: list[str] | None = Field( default=None, alias="totalsCountries", description="Return totals for given countries. In case of missings value totals" "by country filter or global totals for acquisition by country timeseries.", ) class ArtistFansSegmentValue(BaseModel): label: FanSegment value: int class ArtistFansTimeseriesValue(BaseModel): date: datetime.date value: int class ArtistFansTimeseries(BaseModel): id: str name: str | None = None channel: AcquisitionChannel | None = None items: list[ArtistFansTimeseriesValue] class ArtistFansSummaryValue(BaseModel): id: str value: int change: int | None class ArtistFansCampaignSummaryValue(BaseModel): id: str name: str url: str | None channel: AcquisitionChannel value: int change: int | None date: datetime.date = Field(alias="createdAt") class ArtistFansShare(BaseModel): fans_share: float = Field(alias="fansShare") class ArtistFansShareByCountryCountry(ArtistFansShare): country_code: str = Field(alias="countryCode") class ArtistFansShareByAgeRange(ArtistFansShare): age_range: AgeRange = Field(alias="ageRange") class ArtistFansShareByGender(ArtistFansShare): gender: Gender class ArtistSegmentActivityByCategory(BaseModel): label: str value: float class ArtistFansShareByHeavyRotation(ArtistFansShare): heavy_rotation: HeavyRotation = Field(alias="heavyRotation") class ArtistAvailableFansShareOutput(BaseModel): available_fans_share: float = Field(alias="availableFansShare") class ArtistFansShareByLocationOutput(ArtistAvailableFansShareOutput): items: list[ArtistFansShareByCountryCountry] class ArtistFansShareByAgeRangeOutput(ArtistAvailableFansShareOutput): items: list[ArtistFansShareByAgeRange] class ArtistFansShareByGenderOutput(ArtistAvailableFansShareOutput): items: list[ArtistFansShareByGender] class ArtistFansShareByHeavyRotationOutput(ArtistAvailableFansShareOutput): items: list[ArtistFansShareByHeavyRotation] class ArtistFansShareByArtist(ArtistFansShare): global_participant_id: str = Field(alias="globalParticipantId") class ArtistFansAlsoListeningOutput(BaseModel): items: list[ArtistFansShareByArtist] class ArtistSegmentActivityBreakdownOutput(BaseModel): id: FanSegment count: int items: list[ArtistSegmentActivityByCategory] class GetArtistMaxSpendOutput(BaseModel): max_spend: float = Field(alias="maxSpend") class GetArtistMainRepAccountsInput(BaseModel): campaign_type: CampaignType | None = Field(None, alias="campaignType") class ArtistSegmentExplainedValue(BaseModel): segment: FanSegment explanation: str class GetParticipantsInput(BaseModel): vendor_id: int | None = Field( None, alias="vendorId", description="Account vendor id", ) subaccount_id: int | None = Field( None, alias="subaccountId", description="Account subaccount id", ) search: str | None = Field( None, description="Search by partial name match", ) participant_type: ParticipantType | None = Field( None, alias="type", description="Filter by participant type: ARTIST or CUSTOM_LIST", ) virtual_participant_ids: list[str] | None = Field( None, alias="virtualParticipantIds", description="Filter by specific virtual participant IDs", ) limit: int | None = Field( None, ge=1, le=200, description="Page size limit", ) offset: int | None = Field( None, ge=0, description="Page offset", ) class Participant(BaseModel): global_participant_id: str | None = Field(None, alias="globalParticipantId") virtual_participant_id: str | None = Field(None, alias="virtualParticipantId") crm_mailing_list_id: str | None = Field(None, alias="crmMailingListId") spotify_id: str | None = Field(None, alias="spotifyId") name: str labels: Json[list[LabelId]] | list[LabelId] class GetParticipantsOutput(LimitOffsetPage[Participant]): pass class GetArtistsV2Output(LimitOffsetPage[Participant]): pass