146 lines
5.0 KiB
Python
146 lines
5.0 KiB
Python
|
|
from typing import Optional, Any
|
||
|
|
from datetime import datetime
|
||
|
|
|
||
|
|
class PropertyExtractor:
|
||
|
|
|
||
|
|
"Classe base com métodos de extração de propriedades do Notion"
|
||
|
|
|
||
|
|
def extract(self, prop_data: dict) -> Any:
|
||
|
|
|
||
|
|
"""
|
||
|
|
Extrai o valor de uma propriedade baseado no seu tipo.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
prop_data: Dicionário com dados da propriedade do Notion
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Valor extraído da propriedade ou None
|
||
|
|
"""
|
||
|
|
|
||
|
|
tipo = prop_data.get("type")
|
||
|
|
if not tipo:
|
||
|
|
return None
|
||
|
|
|
||
|
|
extractors = {
|
||
|
|
"title" : self._title,
|
||
|
|
"rich_text" : self._rich_text,
|
||
|
|
"number" : self._number,
|
||
|
|
"checkbox" : self._checkbox,
|
||
|
|
"url" : self._url,
|
||
|
|
"select" : self._select,
|
||
|
|
"multi_select" : self._multi_select,
|
||
|
|
"date" : self._date,
|
||
|
|
"relation" : self._relation,
|
||
|
|
"rollup" : self._rollup,
|
||
|
|
"formula" : self._formula,
|
||
|
|
}
|
||
|
|
|
||
|
|
extractor = extractors.get(tipo)
|
||
|
|
if extractor:
|
||
|
|
return extractor(prop_data)
|
||
|
|
|
||
|
|
return None
|
||
|
|
|
||
|
|
def _title(self, prop_data: dict) -> Optional[str]:
|
||
|
|
"Extrai conteúdo de propriedade tipo `title`"
|
||
|
|
title = prop_data.get("title")
|
||
|
|
if title is None:
|
||
|
|
return None
|
||
|
|
if isinstance(title, list) and len(title) == 1:
|
||
|
|
return title[0]['text'].get('content')
|
||
|
|
if isinstance(title, dict):
|
||
|
|
return title['text'].get('content')
|
||
|
|
content_list = [item['plain_text'] for item in title]
|
||
|
|
return "".join(content_list)
|
||
|
|
|
||
|
|
def _rich_text(self, prop_data: dict) -> Optional[dict]:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'rich_text'"
|
||
|
|
prop_list = prop_data.get('rich_text')
|
||
|
|
if prop_list is None:
|
||
|
|
return None
|
||
|
|
content_list = [item['plain_text'] for item in prop_list]
|
||
|
|
return {"text": "".join(content_list), "detailed": prop_list}
|
||
|
|
|
||
|
|
def _number(self, prop_data: dict) -> Optional[float]:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'number'"
|
||
|
|
return prop_data.get("number")
|
||
|
|
|
||
|
|
def _checkbox(self, prop_data: dict) -> bool:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'checkbox'"
|
||
|
|
return prop_data.get("checkbox") == True
|
||
|
|
|
||
|
|
def _url(self, prop_data: dict) -> Optional[str]:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'url'"
|
||
|
|
return prop_data.get("url")
|
||
|
|
|
||
|
|
def _select(self, prop_data: dict) -> Optional[dict]:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'select'"
|
||
|
|
select = prop_data.get("select")
|
||
|
|
if not select:
|
||
|
|
return None
|
||
|
|
return {"name": select.get("name"), "color": select.get("color")}
|
||
|
|
|
||
|
|
def _multi_select(self, prop_data: dict) -> Optional[list[dict]]:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'multi_select'"
|
||
|
|
multi_select = prop_data.get("multi_select")
|
||
|
|
if not multi_select:
|
||
|
|
return None
|
||
|
|
selects = []
|
||
|
|
for select in multi_select:
|
||
|
|
selects.append(
|
||
|
|
{"name": select.get("name"), "color": select.get("color")}
|
||
|
|
)
|
||
|
|
return selects
|
||
|
|
|
||
|
|
def _date(self, prop_data: dict) -> Optional[dict]:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'date'"
|
||
|
|
date = prop_data.get("date")
|
||
|
|
if not date:
|
||
|
|
return None
|
||
|
|
|
||
|
|
def parse_date(date_str):
|
||
|
|
if not date_str:
|
||
|
|
return None
|
||
|
|
for fmt in ["%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d"]:
|
||
|
|
try:
|
||
|
|
return datetime.strptime(date_str, fmt)
|
||
|
|
except:
|
||
|
|
continue
|
||
|
|
return None
|
||
|
|
|
||
|
|
start = parse_date(date.get("start"))
|
||
|
|
end = parse_date(date.get("end"))
|
||
|
|
return {"start": start, "end": end}
|
||
|
|
|
||
|
|
def _relation(self, prop_data: dict) -> Optional[list]:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'relation'"
|
||
|
|
relations = prop_data.get("relation", [])
|
||
|
|
if not relations:
|
||
|
|
return None
|
||
|
|
return [relation["id"] for relation in relations]
|
||
|
|
|
||
|
|
def _rollup(self, prop_data: dict) -> Any:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'rollup'"
|
||
|
|
rollup = prop_data.get("rollup", {})
|
||
|
|
rollup_type = rollup.get("type")
|
||
|
|
|
||
|
|
if rollup_type == "number":
|
||
|
|
return rollup.get("number")
|
||
|
|
elif rollup_type == "array":
|
||
|
|
return rollup.get("array", [])
|
||
|
|
return None
|
||
|
|
|
||
|
|
def _formula(self, prop_data: dict) -> Any:
|
||
|
|
"Extrai conteúdo de propriedade tipo 'formula'"
|
||
|
|
formula = prop_data.get("formula", {})
|
||
|
|
formula_type = formula.get("type")
|
||
|
|
|
||
|
|
if formula_type == "number":
|
||
|
|
return formula.get("number")
|
||
|
|
elif formula_type == "string":
|
||
|
|
return formula.get("string")
|
||
|
|
elif formula_type == "boolean":
|
||
|
|
return formula.get("boolean")
|
||
|
|
return None
|
||
|
|
|
||
|
|
__all__ = ["PropertyExtractor"]
|