MediaRouter / app /analytics /schemas.py
basyx's picture
Upload 340 files
3493993 verified
Raw
History Blame Contribute Delete
4.13 kB
from __future__ import annotations
from datetime import datetime
from typing import Any, Literal
from pydantic import BaseModel, ConfigDict, Field
MetricName = Literal[
"views",
"impressions",
"likes",
"comments",
"shares",
"engagement_rate",
"reach",
"clicks",
"saves",
"watch_time",
"completion_rate",
]
Granularity = Literal["day", "week", "month"]
class AnalyticsQuery(BaseModel):
model_config = ConfigDict(extra="forbid")
date_from: datetime | None = None
date_to: datetime | None = None
timezone: str = Field(default="UTC", min_length=1, max_length=100)
provider: str | None = Field(default=None, max_length=32)
project_id: str | None = Field(default=None, max_length=36)
social_account_id: str | None = Field(default=None, max_length=36)
post_id: str | None = Field(default=None, max_length=36)
metric: MetricName | None = None
granularity: Granularity = "day"
search: str | None = Field(default=None, max_length=200)
sort: Literal["date", "views", "engagement_rate", "likes", "comments", "shares"] = "date"
descending: bool = True
offset: int = Field(default=0, ge=0, le=100_000)
limit: int = Field(default=50, ge=1, le=500)
class AnalyticsMetric(BaseModel):
model_config = ConfigDict(extra="forbid")
provider: str
post_id: str | None = None
project_id: str | None = None
metric_date: datetime
views: int | None = None
impressions: int | None = None
likes: int | None = None
comments: int | None = None
shares: int | None = None
engagement_rate: float | None = None
status: Literal["available", "unavailable", "unsupported", "not_synchronized"] = "available"
source: str = "provider"
collected_at: datetime | None = None
class AnalyticsFreshness(BaseModel):
status: Literal["fresh", "stale", "not_synchronized", "partial", "failed"]
last_collected_at: datetime | None = None
last_sync_id: str | None = None
reason: str | None = None
class AnalyticsOverview(BaseModel):
model_config = ConfigDict(extra="forbid")
date_from: datetime
date_to: datetime
timezone: str
timezone_source: Literal["requested", "utc_fallback"] = "requested"
totals: dict[str, int | float | None]
platforms: list[dict[str, Any]]
top_posts: list[AnalyticsMetric]
freshness: AnalyticsFreshness
class AnalyticsTimeseries(BaseModel):
date_from: datetime
date_to: datetime
timezone: str
granularity: Granularity
metric: str
points: list[dict[str, Any]]
freshness: AnalyticsFreshness
class AnalyticsSyncRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
date_from: datetime | None = None
date_to: datetime | None = None
timezone: str = Field(default="UTC", min_length=1, max_length=100)
provider: str | None = Field(default=None, max_length=32)
project_id: str | None = Field(default=None, max_length=36)
idempotency_key: str | None = Field(default=None, min_length=8, max_length=255)
class AnalyticsSyncRunView(BaseModel):
model_config = ConfigDict(from_attributes=True, extra="forbid")
id: str
status: Literal["queued", "running", "succeeded", "partial", "failed", "cancelled"]
provider: str | None = None
project_id: str | None = None
date_from: datetime
date_to: datetime
timezone: str
attempt_count: int
metrics_count: int
error_code: str | None = None
error_message: str | None = None
created_at: datetime
started_at: datetime | None = None
completed_at: datetime | None = None
updated_at: datetime
class AnalyticsCapabilities(BaseModel):
provider: str
implementation_status: str
status: Literal["available", "unsupported", "unavailable"]
metrics: list[str]
required_scopes: list[str] = Field(default_factory=list)
class AnalyticsSyncList(BaseModel):
items: list[AnalyticsSyncRunView]
offset: int
limit: int
class AnalyticsPostList(BaseModel):
items: list[AnalyticsMetric]
offset: int
limit: int
freshness: AnalyticsFreshness