| from datetime import datetime, timezone |
| from enum import Enum |
| from typing import Any |
| from sqlmodel import SQLModel, Field, Column |
| from sqlalchemy import JSON |
|
|
| def utcnow() -> datetime: |
| return datetime.now(timezone.utc) |
|
|
| class PageContext(str, Enum): |
| healthcare = "healthcare" |
| civic = "civic" |
|
|
| class Channel(str, Enum): |
| messenger = "messenger" |
| comment = "comment" |
| page_post = "page_post" |
| reel = "reel" |
| lead = "lead" |
| unknown = "unknown" |
|
|
| class DraftStatus(str, Enum): |
| draft = "draft" |
| needs_review = "needs_review" |
| approved = "approved" |
| rejected = "rejected" |
| sent = "sent" |
| published = "published" |
| scheduled = "scheduled" |
| failed = "failed" |
|
|
| class PublishMode(str, Enum): |
| now = "now" |
| scheduled = "scheduled" |
| validation_only = "validation_only" |
|
|
| class RiskLevel(str, Enum): |
| low = "low" |
| medium = "medium" |
| high = "high" |
| blocked = "blocked" |
|
|
| class InboundEvent(SQLModel, table=True): |
| id: int | None = Field(default=None, primary_key=True) |
| page_context: PageContext = Field(index=True) |
| platform_page_id: str = Field(index=True) |
| channel: Channel = Field(index=True) |
| event_type: str = Field(index=True) |
| sender_id_hash: str | None = Field(default=None, index=True) |
| object_id: str | None = Field(default=None, index=True) |
| parent_id: str | None = Field(default=None, index=True) |
| permalink_url: str | None = None |
| message_text: str | None = None |
| raw_payload: dict[str, Any] = Field(default_factory=dict, sa_column=Column(JSON)) |
| normalized_payload: dict[str, Any] = Field(default_factory=dict, sa_column=Column(JSON)) |
| forwarded_at: datetime | None = None |
| forward_error: str | None = None |
| created_at: datetime = Field(default_factory=utcnow, index=True) |
|
|
| class Draft(SQLModel, table=True): |
| id: int | None = Field(default=None, primary_key=True) |
| page_context: PageContext = Field(index=True) |
| source_event_id: int | None = Field(default=None, foreign_key="inboundevent.id") |
| channel: Channel = Field(index=True) |
| target_object_id: str | None = Field(default=None, index=True) |
| recipient_psid: str | None = Field(default=None, index=True) |
| draft_text: str |
| sources: list[str] = Field(default_factory=list, sa_column=Column(JSON)) |
| media_attachments: list[dict[str, Any]] = Field(default_factory=list, sa_column=Column(JSON)) |
| media_required: bool = Field(default=False, index=True) |
| publish_mode: PublishMode = Field(default=PublishMode.now, index=True) |
| scheduled_publish_time: datetime | None = Field(default=None, index=True) |
| risk_level: RiskLevel = Field(default=RiskLevel.medium, index=True) |
| status: DraftStatus = Field(default=DraftStatus.needs_review, index=True) |
| created_by: str = "openclaw" |
| approved_by: str | None = None |
| rejection_reason: str | None = None |
| meta_response: dict[str, Any] | None = Field(default=None, sa_column=Column(JSON)) |
| created_at: datetime = Field(default_factory=utcnow, index=True) |
| approved_at: datetime | None = None |
| published_at: datetime | None = None |
|
|
| class AuditLog(SQLModel, table=True): |
| id: int | None = Field(default=None, primary_key=True) |
| page_context: PageContext | None = Field(default=None, index=True) |
| actor: str = Field(index=True) |
| action: str = Field(index=True) |
| draft_id: int | None = Field(default=None, index=True) |
| event_id: int | None = Field(default=None, index=True) |
| details: dict[str, Any] = Field(default_factory=dict, sa_column=Column(JSON)) |
| created_at: datetime = Field(default_factory=utcnow, index=True) |
|
|