/
artyuhovs
/
AIFeedBackTrainingBot
Обзор
Документация
Войти
/
artyuhovs
/
AIFeedBackTrainingBot
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
app/db/models.py
272 строки
6 KB
Codex
Добавить статистику использования по пользователям
21 июл 2026, 01:34
21 июл 2026, 01:34
02504ee
Код
Авторство
О чём код?
from __future__ import annotations from dataclasses import dataclass from enum import StrEnum class ProcessingStatus(StrEnum): RECEIVED = "received" DOWNLOADED = "downloaded" AUDIO_PREPARING = "audio_preparing" AUDIO_PREPARED = "audio_prepared" TRANSCRIBING = "transcribing" TRANSCRIBED = "transcribed" FAILED = "failed" class AnalysisStatus(StrEnum): ANALYZING = "analyzing" ANALYZED = "analyzed" ANALYSIS_FAILED = "analysis_failed" class MembershipStatus(StrEnum): PENDING = "pending" APPROVED = "approved" DENIED = "denied" class StreamRole(StrEnum): LEARNER = "learner" CURATOR = "curator" class CourseVersionStatus(StrEnum): DRAFT = "draft" PUBLISHED = "published" class StreamStatus(StrEnum): DRAFT = "draft" ACTIVE = "active" PAUSED = "paused" COMPLETED = "completed" class OutboundJobStatus(StrEnum): PENDING = "pending" RETRY = "retry" LEASED = "leased" SENT = "sent" DEAD = "dead" UNCERTAIN = "uncertain" CANCELLED = "cancelled" class IdentityKind(StrEnum): TELEGRAM = "telegram" PLACEHOLDER = "placeholder" SYNTHETIC = "synthetic" class SubmissionFinalizeOutcome(StrEnum): ACCEPTED = "accepted" STORED_UNCREDITED = "stored_uncredited" REJECTED = "rejected" @dataclass(frozen=True) class IdentityClaimDiagnostic: duplicate_group: int source_user_id: int target_user_id: int conflicts: tuple[str, ...] @dataclass(frozen=True) class IdentityDiagnostics: duplicate_username_groups: int duplicate_real_username_groups: int claim_candidates: tuple[IdentityClaimDiagnostic, ...] @dataclass(frozen=True) class MessageRecord: id: int stream_id: int | None participant_assignment_id: int | None submission_kind: str telegram_user_id: int telegram_chat_id: int telegram_message_id: int telegram_received_at: str | None input_intent_id: int | None telegram_file_id: str telegram_file_unique_id: str | None media_type: str original_file_name: str | None mime_type: str | None file_size_bytes: int | None status: ProcessingStatus error_code: str | None error_message: str | None original_file_path: str | None audio_file_path: str | None duration_sec: float | None audio_size_bytes: int | None transcript_text: str | None transcript_sha256: str | None transcript_file_path: str | None provider_raw_response_path: str | None created_at: str updated_at: str downloaded_at: str | None audio_prepared_at: str | None transcribed_at: str | None failed_at: str | None @dataclass(frozen=True) class BotUser: telegram_user_id: int identity_kind: IdentityKind username: str first_name: str last_name: str is_admin: bool current_stream_id: int | None current_assignment_id: int | None current_assignment_kind: str free_training_pending: bool created_at: str updated_at: str @dataclass(frozen=True) class Stream: id: int title: str slug: str description: str is_active: bool course_version_id: int | None starts_at: str | None timezone: str ends_at: str | None status: StreamStatus telegram_chat_id: int | None created_at: str updated_at: str @dataclass(frozen=True) class StreamMembership: id: int stream_id: int telegram_user_id: int status: MembershipStatus requested_at: str decided_at: str | None decided_by_user_id: int | None updated_at: str roles: tuple[StreamRole, ...] @property def role(self) -> str: """Compatibility display value; authorization always checks normalized roles.""" if StreamRole.CURATOR in self.roles: return StreamRole.CURATOR.value return StreamRole.LEARNER.value @dataclass(frozen=True) class Course: id: int title: str description: str is_active: bool created_at: str updated_at: str @dataclass(frozen=True) class CourseVersion: id: int course_id: int version_number: int status: CourseVersionStatus reminder_offsets_minutes: str created_at: str updated_at: str published_at: str | None @dataclass(frozen=True) class CourseTopic: id: int course_version_id: int position: int title: str description: str created_at: str updated_at: str @dataclass(frozen=True) class CoursePublication: id: int course_topic_id: int position: int publication_type: str content_text: str delivery_channel: str publish_offset_minutes: int deadline_offset_minutes: int | None response_format: str | None reminder_offsets_minutes: str | None crowd_training_enabled: bool required_reviews: int assigned_reviews: int review_criteria_json: str | None review_duration_minutes: int review_reminder_offsets_minutes: str review_quality_duration_minutes: int review_quality_reminder_offsets_minutes: str correction_duration_minutes: int correction_reminder_offsets_minutes: str created_at: str updated_at: str @property def is_assignment(self) -> bool: return self.deadline_offset_minutes is not None @dataclass(frozen=True) class StreamPublication: id: int stream_id: int course_publication_id: int scheduled_at: str deadline_at: str | None crowd_distributed_at: str | None review_deadline_at: str | None review_closed_at: str | None review_quality_deadline_at: str | None review_quality_closed_at: str | None created_at: str updated_at: str @dataclass(frozen=True) class AnalysisRun: id: int message_id: int provider: str | None model: str | None framework: str | None prompt_version: str | None prompt_hash: str status: AnalysisStatus input_text: str | None input_text_sha256: str | None output_text: str | None raw_response_path: str | None error_code: str | None error_message: str | None prompt_tokens: int | None completion_tokens: int | None total_tokens: int | None created_at: str updated_at: str completed_at: str | None