krz/hutch-stats
Server-side utility for calculating contributions for sourcehut users.
clone: git clone https://gitbay.org/krz/hutch-stats.git
main: src/srht_contrib/schemas.py · raw
1from __future__ import annotations
2
3from datetime import date, datetime
4from typing import Literal
5
6from pydantic import BaseModel, Field, model_validator
7
8
9class NormalizedEvent(BaseModel):
10 service: str
11 event_type: str
12 actor: str
13 repo_name: str | None = None
14 resource_id: str
15 external_uid: str
16 occurred_at: datetime
17 weight: float
18 raw_payload_json: dict | None = None
19
20
21class ContributionDay(BaseModel):
22 date: date
23 count: int
24 score: float
25
26
27class ContributionIndexMetadata(BaseModel):
28 is_indexed: bool
29 last_polled_at: datetime | None = None
30 indexing_state: Literal["pending", "indexed", "error"]
31 is_recent_window_backfilled: bool = False
32 recent_backfill_state: Literal["pending", "in_progress", "completed", "error"] = "pending"
33 recent_backfill_completed_at: datetime | None = None
34
35
36class ContributionCalendarResponse(ContributionIndexMetadata):
37 actor: str
38 from_date: date = Field(alias="from")
39 to_date: date = Field(alias="to")
40 days: list[ContributionDay]
41
42 model_config = {"populate_by_name": True}
43
44
45class ContributionStatsResponse(ContributionIndexMetadata):
46 actor: str
47 from_date: date = Field(alias="from")
48 to_date: date = Field(alias="to")
49 total_events: int
50 total_score: float
51 active_days: int
52 longest_streak: int
53 current_streak: int
54
55 model_config = {"populate_by_name": True}
56
57
58class HealthResponse(BaseModel):
59 status: str
60
61
62class PollResponse(BaseModel):
63 actor: str
64 inserted_events: int
65 services: list[str]
66
67
68class TrackedRepositoryCreateRequest(BaseModel):
69 actor: str
70 repo_name: str
71
72
73class TrackedRepositoryUpdateRequest(BaseModel):
74 actor: str | None = None
75 repo_name: str | None = None
76
77 @model_validator(mode="after")
78 def validate_any_field_present(self) -> "TrackedRepositoryUpdateRequest":
79 if self.actor is None and self.repo_name is None:
80 raise ValueError("Provide `actor`, `repo_name`, or both.")
81 return self
82
83
84class TrackedRepositoryResponse(BaseModel):
85 id: int
86 service: str
87 actor: str
88 repo_name: str