inital commit, very early alpha stage
This commit is contained in:
260
backend/app/services/serializers.py
Normal file
260
backend/app/services/serializers.py
Normal file
@@ -0,0 +1,260 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime
|
||||
from typing import Any
|
||||
|
||||
from app.models import (
|
||||
Announcement,
|
||||
Event,
|
||||
FileAsset,
|
||||
Group,
|
||||
HomeDevice,
|
||||
HomeProfile,
|
||||
Member,
|
||||
MemberDevice,
|
||||
Message,
|
||||
Poll,
|
||||
PollOption,
|
||||
PollVote,
|
||||
RemoteServerConnection,
|
||||
Task,
|
||||
Thread,
|
||||
)
|
||||
|
||||
|
||||
def iso(value: datetime | date | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
return value.isoformat()
|
||||
|
||||
|
||||
def group_dict(group: Group) -> dict[str, Any]:
|
||||
return {
|
||||
"id": group.id,
|
||||
"server_origin": group.server_origin,
|
||||
"name": group.name,
|
||||
"description": group.description,
|
||||
"visibility": group.visibility,
|
||||
"legacy_channel_status": group.legacy_channel_status,
|
||||
"transition_deadline": iso(group.transition_deadline),
|
||||
"created_at": iso(group.created_at),
|
||||
"updated_at": iso(group.updated_at),
|
||||
}
|
||||
|
||||
|
||||
def member_dict(member: Member) -> dict[str, Any]:
|
||||
return {
|
||||
"id": member.id,
|
||||
"group_id": member.group_id,
|
||||
"home_profile_id": member.home_profile_id,
|
||||
"display_name": member.display_name,
|
||||
"role": member.role,
|
||||
"status": member.status,
|
||||
"joined_at": iso(member.joined_at),
|
||||
"last_seen_at": iso(member.last_seen_at),
|
||||
"notification_enabled_at": iso(member.notification_enabled_at),
|
||||
}
|
||||
|
||||
|
||||
def profile_dict(profile: HomeProfile | None, member: Member | None = None) -> dict[str, Any] | None:
|
||||
if profile:
|
||||
return {
|
||||
"id": profile.id,
|
||||
"primary_display_name": profile.primary_display_name,
|
||||
"status": profile.status,
|
||||
"last_seen_at": iso(profile.last_seen_at),
|
||||
}
|
||||
if member:
|
||||
return {
|
||||
"id": None,
|
||||
"primary_display_name": member.display_name,
|
||||
"status": "membership_only",
|
||||
"last_seen_at": iso(member.last_seen_at),
|
||||
}
|
||||
return None
|
||||
|
||||
|
||||
def announcement_dict(announcement: Announcement, group: Group | None = None) -> dict[str, Any]:
|
||||
return {
|
||||
"id": announcement.id,
|
||||
"group_id": announcement.group_id,
|
||||
"group_name": group.name if group else None,
|
||||
"source_type": "local",
|
||||
"source_server_origin": group.server_origin if group else None,
|
||||
"author_member_id": announcement.author_member_id,
|
||||
"title": announcement.title,
|
||||
"body": announcement.body,
|
||||
"priority": announcement.priority,
|
||||
"official": announcement.official,
|
||||
"requires_ack": announcement.requires_ack,
|
||||
"created_at": iso(announcement.created_at),
|
||||
"updated_at": iso(announcement.updated_at),
|
||||
}
|
||||
|
||||
|
||||
def event_dict(event: Event, group: Group | None = None, rsvp_status: str | None = None) -> dict[str, Any]:
|
||||
return {
|
||||
"id": event.id,
|
||||
"group_id": event.group_id,
|
||||
"group_name": group.name if group else None,
|
||||
"source_type": "local",
|
||||
"source_server_origin": group.server_origin if group else None,
|
||||
"created_by_member_id": event.created_by_member_id,
|
||||
"title": event.title,
|
||||
"description": event.description,
|
||||
"starts_at": iso(event.starts_at),
|
||||
"ends_at": iso(event.ends_at),
|
||||
"location_name": event.location_name,
|
||||
"location_address": event.location_address,
|
||||
"rsvp_required": event.rsvp_required,
|
||||
"rsvp_status": rsvp_status,
|
||||
"changed_at": iso(event.changed_at),
|
||||
"created_at": iso(event.created_at),
|
||||
"updated_at": iso(event.updated_at),
|
||||
}
|
||||
|
||||
|
||||
def task_dict(task: Task, group: Group | None = None) -> dict[str, Any]:
|
||||
return {
|
||||
"id": task.id,
|
||||
"group_id": task.group_id,
|
||||
"group_name": group.name if group else None,
|
||||
"source_type": "local",
|
||||
"source_server_origin": group.server_origin if group else None,
|
||||
"created_by_member_id": task.created_by_member_id,
|
||||
"assigned_to_member_id": task.assigned_to_member_id,
|
||||
"title": task.title,
|
||||
"description": task.description,
|
||||
"due_at": iso(task.due_at),
|
||||
"status": task.status,
|
||||
"created_at": iso(task.created_at),
|
||||
"updated_at": iso(task.updated_at),
|
||||
}
|
||||
|
||||
|
||||
def poll_dict(poll: Poll, options: list[PollOption], votes: list[PollVote], group: Group | None = None) -> dict[str, Any]:
|
||||
counts: dict[str, int] = {option.id: 0 for option in options}
|
||||
for vote in votes:
|
||||
counts[vote.option_id] = counts.get(vote.option_id, 0) + 1
|
||||
return {
|
||||
"id": poll.id,
|
||||
"group_id": poll.group_id,
|
||||
"group_name": group.name if group else None,
|
||||
"source_type": "local",
|
||||
"source_server_origin": group.server_origin if group else None,
|
||||
"title": poll.title,
|
||||
"description": poll.description,
|
||||
"closes_at": iso(poll.closes_at),
|
||||
"status": poll.status,
|
||||
"created_by_member_id": poll.created_by_member_id,
|
||||
"created_at": iso(poll.created_at),
|
||||
"options": [{"id": option.id, "label": option.label, "position": option.position, "vote_count": counts.get(option.id, 0)} for option in options],
|
||||
}
|
||||
|
||||
|
||||
def file_dict(file: FileAsset, group: Group | None = None) -> dict[str, Any]:
|
||||
return {
|
||||
"id": file.id,
|
||||
"group_id": file.group_id,
|
||||
"group_name": group.name if group else None,
|
||||
"source_type": "local",
|
||||
"source_server_origin": group.server_origin if group else None,
|
||||
"uploaded_by_member_id": file.uploaded_by_member_id,
|
||||
"filename_original": file.filename_original,
|
||||
"content_type": file.content_type,
|
||||
"size_bytes": file.size_bytes,
|
||||
"visibility": file.visibility,
|
||||
"description": file.description,
|
||||
"requires_ack": file.requires_ack,
|
||||
"created_at": iso(file.created_at),
|
||||
"download_url": f"/api/files/{file.id}/download",
|
||||
}
|
||||
|
||||
|
||||
def thread_dict(thread: Thread, messages: list[Message] | None = None, group: Group | None = None) -> dict[str, Any]:
|
||||
return {
|
||||
"id": thread.id,
|
||||
"group_id": thread.group_id,
|
||||
"group_name": group.name if group else None,
|
||||
"source_type": "local",
|
||||
"source_server_origin": group.server_origin if group else None,
|
||||
"title": thread.title,
|
||||
"kind": thread.kind,
|
||||
"created_by_member_id": thread.created_by_member_id,
|
||||
"created_at": iso(thread.created_at),
|
||||
"updated_at": iso(thread.updated_at),
|
||||
"messages": [message_dict(message) for message in messages or []],
|
||||
}
|
||||
|
||||
|
||||
def message_dict(message: Message) -> dict[str, Any]:
|
||||
return {
|
||||
"id": message.id,
|
||||
"thread_id": message.thread_id,
|
||||
"author_member_id": message.author_member_id,
|
||||
"body": message.body,
|
||||
"created_at": iso(message.created_at),
|
||||
"edited_at": iso(message.edited_at),
|
||||
"deleted_at": iso(message.deleted_at),
|
||||
}
|
||||
|
||||
|
||||
def action_dict(
|
||||
*,
|
||||
id: str,
|
||||
source_type: str,
|
||||
source_server_origin: str,
|
||||
source_group_id: str,
|
||||
source_group_name: str,
|
||||
type: str,
|
||||
priority: str,
|
||||
title: str,
|
||||
summary: str,
|
||||
object_type: str,
|
||||
object_id: str,
|
||||
due_at: datetime | None = None,
|
||||
status: str = "open",
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"id": id,
|
||||
"source_type": source_type,
|
||||
"source_server_origin": source_server_origin,
|
||||
"source_group_id": source_group_id,
|
||||
"source_group_name": source_group_name,
|
||||
"type": type,
|
||||
"status": status,
|
||||
"priority": priority,
|
||||
"title": title,
|
||||
"summary": summary,
|
||||
"object_type": object_type,
|
||||
"object_id": object_id,
|
||||
"due_at": iso(due_at),
|
||||
}
|
||||
|
||||
|
||||
def device_dict(device: HomeDevice | MemberDevice, current_id: str | None = None) -> dict[str, Any]:
|
||||
return {
|
||||
"id": device.id,
|
||||
"label": device.label,
|
||||
"created_at": iso(device.created_at),
|
||||
"last_seen_at": iso(device.last_seen_at),
|
||||
"revoked_at": iso(device.revoked_at),
|
||||
"trust_level": device.trust_level,
|
||||
"current": device.id == current_id,
|
||||
}
|
||||
|
||||
|
||||
def remote_connection_dict(connection: RemoteServerConnection) -> dict[str, Any]:
|
||||
return {
|
||||
"id": connection.id,
|
||||
"server_origin": connection.server_origin,
|
||||
"server_name": connection.server_name,
|
||||
"api_base": connection.api_base,
|
||||
"protocol_version": connection.protocol_version,
|
||||
"capabilities": connection.capabilities_json,
|
||||
"status": connection.status,
|
||||
"last_sync_at": iso(connection.last_sync_at),
|
||||
"last_error": connection.last_error,
|
||||
"created_at": iso(connection.created_at),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user