feat(deck): Initialize Deck app client/server
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
from datetime import datetime
|
||||
from typing import List, Optional, Dict, Any, Union
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from .base import BaseResponse, StatusResponse
|
||||
|
||||
|
||||
class DeckUser(BaseModel):
|
||||
primaryKey: str
|
||||
uid: str
|
||||
displayname: str
|
||||
|
||||
|
||||
class DeckPermissions(BaseModel):
|
||||
PERMISSION_READ: bool
|
||||
PERMISSION_EDIT: bool
|
||||
PERMISSION_MANAGE: bool
|
||||
PERMISSION_SHARE: bool
|
||||
|
||||
|
||||
class DeckLabel(BaseModel):
|
||||
id: int
|
||||
title: str
|
||||
color: str
|
||||
boardId: Optional[int] = None
|
||||
cardId: Optional[int] = None
|
||||
|
||||
|
||||
class DeckACL(BaseModel):
|
||||
id: int
|
||||
participant: DeckUser
|
||||
type: int
|
||||
boardId: int
|
||||
permissionEdit: bool
|
||||
permissionShare: bool
|
||||
permissionManage: bool
|
||||
owner: bool
|
||||
|
||||
|
||||
class DeckBoardSettings(BaseModel):
|
||||
calendar: bool
|
||||
cardDetailsInModal: Optional[bool] = Field(default=None, alias="cardDetailsInModal")
|
||||
cardIdBadge: Optional[bool] = Field(default=None, alias="cardIdBadge")
|
||||
groupLimit: Optional[List[Dict[str, str]]] = Field(default=None, alias="groupLimit")
|
||||
notify_due: Optional[str] = Field(default=None, alias="notify-due")
|
||||
|
||||
|
||||
class DeckBoard(BaseModel):
|
||||
id: int
|
||||
title: str
|
||||
owner: DeckUser
|
||||
color: str
|
||||
archived: bool
|
||||
labels: List[DeckLabel]
|
||||
acl: List[DeckACL]
|
||||
permissions: DeckPermissions
|
||||
users: List[DeckUser]
|
||||
deletedAt: int
|
||||
lastModified: Optional[int] = None
|
||||
settings: Optional[DeckBoardSettings] = None
|
||||
etag: Optional[str] = Field(default=None, alias="ETag")
|
||||
|
||||
@field_validator("settings", mode="before")
|
||||
@classmethod
|
||||
def validate_settings(cls, v):
|
||||
# Handle case where API returns empty array instead of dict/null
|
||||
if isinstance(v, list) and len(v) == 0:
|
||||
return None
|
||||
return v
|
||||
|
||||
|
||||
class DeckCard(BaseModel):
|
||||
id: int
|
||||
title: str
|
||||
stackId: int
|
||||
type: str
|
||||
order: int
|
||||
archived: bool
|
||||
owner: Union[str, DeckUser] # Can be either string or user object
|
||||
description: Optional[str] = None
|
||||
duedate: Optional[datetime] = None
|
||||
done: Optional[datetime] = None
|
||||
lastModified: Optional[int] = None
|
||||
createdAt: Optional[int] = None
|
||||
labels: Optional[List[DeckLabel]] = None
|
||||
assignedUsers: Optional[List[DeckUser]] = None
|
||||
attachments: Optional[List[Any]] = None # Define a proper Attachment model later
|
||||
attachmentCount: Optional[int] = None
|
||||
deletedAt: Optional[int] = None
|
||||
commentsUnread: Optional[int] = None
|
||||
overdue: Optional[int] = None
|
||||
etag: Optional[str] = Field(default=None, alias="ETag")
|
||||
|
||||
@field_validator("owner", mode="before")
|
||||
@classmethod
|
||||
def validate_owner(cls, v):
|
||||
# Handle case where API returns user object instead of string
|
||||
if isinstance(v, dict):
|
||||
return v.get("uid", v.get("primaryKey", str(v)))
|
||||
return v
|
||||
|
||||
|
||||
class DeckStack(BaseModel):
|
||||
id: int
|
||||
title: str
|
||||
boardId: int
|
||||
order: int
|
||||
deletedAt: int
|
||||
lastModified: Optional[int] = None
|
||||
cards: Optional[List[DeckCard]] = None
|
||||
etag: Optional[str] = Field(default=None, alias="ETag")
|
||||
|
||||
|
||||
class DeckAttachmentExtendedData(BaseModel):
|
||||
filesize: int
|
||||
mimetype: str
|
||||
info: Dict[str, str]
|
||||
|
||||
|
||||
class DeckAttachment(BaseModel):
|
||||
id: int
|
||||
cardId: int
|
||||
type: str
|
||||
data: str
|
||||
lastModified: int
|
||||
createdAt: int
|
||||
createdBy: str
|
||||
deletedAt: int
|
||||
extendedData: DeckAttachmentExtendedData
|
||||
|
||||
|
||||
class DeckComment(BaseModel):
|
||||
id: int
|
||||
objectId: int
|
||||
message: str
|
||||
actorId: str
|
||||
actorType: str
|
||||
actorDisplayName: str
|
||||
creationDateTime: datetime
|
||||
mentions: List[Dict[str, str]]
|
||||
replyTo: Optional[Any] = None # Self-referencing, handle later if needed
|
||||
|
||||
|
||||
class DeckSession(BaseModel):
|
||||
token: str
|
||||
|
||||
|
||||
class DeckConfig(BaseModel):
|
||||
calendar: bool
|
||||
cardDetailsInModal: bool
|
||||
cardIdBadge: bool
|
||||
groupLimit: Optional[List[Dict[str, str]]] = None
|
||||
|
||||
|
||||
# Response Models for MCP Tools
|
||||
|
||||
|
||||
class ListBoardsResponse(BaseResponse):
|
||||
"""Response model for listing deck boards."""
|
||||
|
||||
boards: List[DeckBoard] = Field(description="List of deck boards")
|
||||
total: int = Field(description="Total number of boards")
|
||||
|
||||
|
||||
class CreateBoardResponse(BaseResponse):
|
||||
"""Response model for board creation."""
|
||||
|
||||
id: int = Field(description="The created board ID")
|
||||
title: str = Field(description="The created board title")
|
||||
color: str = Field(description="The created board color")
|
||||
|
||||
|
||||
class GetBoardResponse(BaseResponse):
|
||||
"""Response model for getting board details."""
|
||||
|
||||
board: DeckBoard = Field(description="Board details")
|
||||
|
||||
|
||||
class BoardOperationResponse(StatusResponse):
|
||||
"""Response model for board operations like update/delete."""
|
||||
|
||||
board_id: int = Field(description="ID of the affected board")
|
||||
Reference in New Issue
Block a user