mirror of
https://github.com/tcsenpai/pensieve.git
synced 2025-06-06 03:05:25 +00:00
279 lines
6.0 KiB
Python
279 lines
6.0 KiB
Python
from pydantic import (
|
|
BaseModel,
|
|
ConfigDict,
|
|
DirectoryPath,
|
|
HttpUrl,
|
|
Field,
|
|
model_validator,
|
|
)
|
|
from typing import List, Optional, Any, Dict
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
|
|
|
|
class FolderType(Enum):
|
|
DEFAULT = "DEFAULT"
|
|
DUMMY = "DUMMY"
|
|
|
|
|
|
class MetadataSource(Enum):
|
|
USER_GENERATED = "user_generated"
|
|
SYSTEM_GENERATED = "system_generated"
|
|
PLUGIN_GENERATED = "plugin_generated"
|
|
|
|
|
|
class MetadataType(Enum):
|
|
JSON_DATA = "json"
|
|
TEXT_DATA = "text"
|
|
NUMBER_DATA = "number"
|
|
|
|
|
|
class NewFolderParam(BaseModel):
|
|
path: DirectoryPath
|
|
last_modified_at: datetime
|
|
type: str = FolderType.DEFAULT
|
|
|
|
|
|
class NewLibraryParam(BaseModel):
|
|
name: str
|
|
folders: List[NewFolderParam] = []
|
|
|
|
|
|
class NewFoldersParam(BaseModel):
|
|
folders: List[NewFolderParam] = []
|
|
|
|
|
|
class EntityMetadataParam(BaseModel):
|
|
key: str
|
|
value: str
|
|
source: str
|
|
data_type: MetadataType
|
|
|
|
|
|
class NewEntityParam(BaseModel):
|
|
filename: str
|
|
filepath: str
|
|
size: int
|
|
file_created_at: datetime
|
|
file_last_modified_at: datetime
|
|
file_type: str
|
|
file_type_group: str
|
|
folder_id: int
|
|
tags: List[str] | None = None
|
|
metadata_entries: List[EntityMetadataParam] | None = None
|
|
|
|
|
|
class UpdateEntityParam(BaseModel):
|
|
size: int | None = None
|
|
file_created_at: datetime | None = None
|
|
file_last_modified_at: datetime | None = None
|
|
file_type: str | None = None
|
|
file_type_group: str | None = None
|
|
tags: List[str] | None = None
|
|
metadata_entries: List[EntityMetadataParam] | None = None
|
|
|
|
|
|
class UpdateTagParam(BaseModel):
|
|
description: str | None
|
|
color: str | None
|
|
|
|
|
|
class UpdateEntityTagsParam(BaseModel):
|
|
tags: List[str] = []
|
|
|
|
|
|
class UpdateEntityMetadataParam(BaseModel):
|
|
metadata_entries: List[EntityMetadataParam]
|
|
|
|
|
|
class NewPluginParam(BaseModel):
|
|
name: str
|
|
description: str | None
|
|
webhook_url: HttpUrl
|
|
|
|
|
|
class NewLibraryPluginParam(BaseModel):
|
|
plugin_id: Optional[int] = None
|
|
plugin_name: Optional[str] = None
|
|
|
|
@model_validator(mode="after")
|
|
def check_either_id_or_name(self):
|
|
plugin_id = self.plugin_id
|
|
plugin_name = self.plugin_name
|
|
if not (plugin_id or plugin_name):
|
|
raise ValueError("Either plugin_id or plugin_name must be provided")
|
|
if plugin_id is not None and plugin_name is not None:
|
|
raise ValueError("Only one of plugin_id or plugin_name should be provided")
|
|
return self
|
|
|
|
|
|
class Folder(BaseModel):
|
|
id: int
|
|
path: str
|
|
last_modified_at: datetime
|
|
type: FolderType
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class Plugin(BaseModel):
|
|
id: int
|
|
name: str
|
|
description: str | None
|
|
webhook_url: str
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class Library(BaseModel):
|
|
id: int
|
|
name: str
|
|
folders: List[Folder] = []
|
|
plugins: List[Plugin] = []
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class Tag(BaseModel):
|
|
id: int
|
|
name: str
|
|
description: str | None
|
|
color: str | None
|
|
created_at: datetime
|
|
# source: str
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class EntityMetadata(BaseModel):
|
|
id: int
|
|
entity_id: int
|
|
key: str
|
|
value: str
|
|
source: str
|
|
data_type: MetadataType
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class Entity(BaseModel):
|
|
id: int
|
|
filepath: str
|
|
filename: str
|
|
size: int
|
|
file_created_at: datetime
|
|
file_last_modified_at: datetime
|
|
file_type: str
|
|
file_type_group: str
|
|
last_scan_at: datetime | None
|
|
folder_id: int
|
|
library_id: int
|
|
tags: List[Tag] = []
|
|
metadata_entries: List[EntityMetadata] = []
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
def get_metadata_by_key(self, key: str) -> Optional[EntityMetadata]:
|
|
"""
|
|
Get EntityMetadata by key.
|
|
|
|
Args:
|
|
key (str): The key to search for in metadata entries.
|
|
|
|
Returns:
|
|
Optional[EntityMetadata]: The EntityMetadata if found, None otherwise.
|
|
"""
|
|
for metadata in self.metadata_entries:
|
|
if metadata.key == key:
|
|
return metadata
|
|
return None
|
|
|
|
|
|
class MetadataIndexItem(BaseModel):
|
|
key: str
|
|
value: Any
|
|
source: str
|
|
|
|
|
|
class EntitySearchResult(BaseModel):
|
|
id: str
|
|
filepath: str
|
|
filename: str
|
|
size: int
|
|
file_created_at: int = Field(..., description="Unix timestamp")
|
|
created_date: Optional[str] = None
|
|
created_month: Optional[str] = None
|
|
created_year: Optional[str] = None
|
|
file_last_modified_at: int = Field(..., description="Unix timestamp")
|
|
file_type: str
|
|
file_type_group: str
|
|
last_scan_at: Optional[int] = Field(None, description="Unix timestamp")
|
|
library_id: int
|
|
folder_id: int
|
|
tags: List[str]
|
|
metadata_entries: List[MetadataIndexItem]
|
|
facets: Optional[Dict[str, Any]] = None
|
|
|
|
|
|
class FacetCount(BaseModel):
|
|
count: int
|
|
highlighted: str
|
|
value: str
|
|
|
|
|
|
class FacetStats(BaseModel):
|
|
total_values: int
|
|
|
|
|
|
class Facet(BaseModel):
|
|
counts: List[FacetCount]
|
|
field_name: str
|
|
sampled: bool
|
|
stats: FacetStats
|
|
|
|
|
|
class TextMatchInfo(BaseModel):
|
|
best_field_score: str
|
|
best_field_weight: int
|
|
fields_matched: int
|
|
num_tokens_dropped: int
|
|
score: str
|
|
tokens_matched: int
|
|
typo_prefix_score: int
|
|
|
|
|
|
class HybridSearchInfo(BaseModel):
|
|
rank_fusion_score: float
|
|
|
|
|
|
class SearchHit(BaseModel):
|
|
document: EntitySearchResult
|
|
highlight: Dict[str, Any] = {}
|
|
highlights: List[Any] = []
|
|
hybrid_search_info: Optional[HybridSearchInfo] = None
|
|
text_match: Optional[int] = None
|
|
text_match_info: Optional[TextMatchInfo] = None
|
|
|
|
|
|
class RequestParams(BaseModel):
|
|
collection_name: str
|
|
first_q: str
|
|
per_page: int
|
|
q: str
|
|
|
|
|
|
class SearchResult(BaseModel):
|
|
facet_counts: List[Facet]
|
|
found: int
|
|
hits: List[SearchHit]
|
|
out_of: int
|
|
page: int
|
|
request_params: RequestParams
|
|
search_cutoff: bool
|
|
search_time_ms: int
|
|
|
|
|
|
class EntityContext(BaseModel):
|
|
prev: List[Entity]
|
|
next: List[Entity]
|