Fixed tags management
This commit is contained in:
@@ -109,27 +109,6 @@ def chunks(lst: List[Any], n: int) -> Iterable[List[Any]]:
|
||||
yield lst[i : i + n]
|
||||
|
||||
|
||||
def _sanitize_tags(tags: Optional[List[str]]) -> Optional[List[str]]:
|
||||
if not tags:
|
||||
return None
|
||||
clean: List[str] = []
|
||||
for t in tags:
|
||||
if t is None:
|
||||
continue
|
||||
s = str(t).strip()
|
||||
if not s or s.lower() in ("undefined", "null", "none"):
|
||||
continue
|
||||
clean.append(s)
|
||||
# dedup preserving order
|
||||
seen = set()
|
||||
out = []
|
||||
for s in clean:
|
||||
if s not in seen:
|
||||
seen.add(s)
|
||||
out.append(s)
|
||||
return out or None
|
||||
|
||||
|
||||
def _valid_name(x: Any) -> Optional[str]:
|
||||
if x is None:
|
||||
return None
|
||||
@@ -193,6 +172,28 @@ def build_tududi_description_from_todoist(task: Dict[str, Any], task_name: str)
|
||||
|
||||
return "\n\n".join(parts).strip()
|
||||
|
||||
|
||||
def build_tududi_tag_objects(tag_names: List[str], tag_by_name: Dict[str, Dict[str, Any]]) -> List[Dict[str, str]]:
|
||||
objs: List[Dict[str, str]] = []
|
||||
seen = set()
|
||||
for n in tag_names or []:
|
||||
key = str(n).strip()
|
||||
if not key or key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
|
||||
t = tag_by_name.get(key)
|
||||
if not t:
|
||||
continue
|
||||
uid = t.get("uid")
|
||||
name = t.get("name") or key
|
||||
if not uid or not name:
|
||||
continue
|
||||
|
||||
objs.append({"name": name, "uid": uid})
|
||||
return objs
|
||||
|
||||
|
||||
# ----------------------------
|
||||
# Todoist client (API v1)
|
||||
# ----------------------------
|
||||
@@ -286,7 +287,7 @@ class TududiClient:
|
||||
password: Optional[str] = None,
|
||||
timeout: int = 60,
|
||||
dry_run: bool = False,
|
||||
request_sleep: float = 0.25,
|
||||
request_sleep: float = 0.15,
|
||||
) -> None:
|
||||
self.base_url = base_url.rstrip("/")
|
||||
self.timeout = timeout
|
||||
@@ -343,7 +344,7 @@ class TududiClient:
|
||||
print(f"[DRY_RUN] POST {path} payload={payload}")
|
||||
return {"_dry_run": True}
|
||||
if payload is not None and isinstance(payload, dict):
|
||||
print(f"[DEBUG] POST {path} payload.Tags={payload.get('Tags')}")
|
||||
print(f"[DEBUG] POST {path} payload.Tags={payload.get('Tags') if isinstance(payload, dict) else None}")
|
||||
r = self.s.post(url, data=json.dumps(payload or {}), timeout=self.timeout)
|
||||
|
||||
# 429 -> retry
|
||||
@@ -444,7 +445,7 @@ class TududiClient:
|
||||
project_id: Optional[int] = None,
|
||||
due_date: Optional[str] = None,
|
||||
priority: Optional[str] = None,
|
||||
tags: Optional[List[Dict[str, str]]] = None,
|
||||
tag_objs: Optional[List[Dict[str, str]]] = None,
|
||||
description: Optional[str] = None,
|
||||
note: Optional[str] = None,
|
||||
parent_task_id: Optional[int] = None,
|
||||
@@ -461,24 +462,10 @@ class TududiClient:
|
||||
if priority:
|
||||
payload["priority"] = priority
|
||||
|
||||
tags = _sanitize_tags(tags)
|
||||
if tags:
|
||||
clean_tags: List[Dict[str, str]] = []
|
||||
for t in tags:
|
||||
if not isinstance(t, dict):
|
||||
continue
|
||||
name = str(t.get("name") or "").strip()
|
||||
uid = str(t.get("uid") or "").strip()
|
||||
if not name or name.lower() in ("undefined", "null", "none"):
|
||||
continue
|
||||
if not uid or uid.lower() in ("undefined", "null", "none"):
|
||||
continue
|
||||
clean_tags.append({"name": name, "uid": uid})
|
||||
|
||||
if tag_objs:
|
||||
payload["Tags"] = tag_objs
|
||||
|
||||
if clean_tags:
|
||||
payload["Tags"] = clean_tags
|
||||
|
||||
# Tududi spesso usa "note" (tu l’hai mostrato), non "description"
|
||||
if note:
|
||||
payload["note"] = note
|
||||
if description:
|
||||
@@ -835,6 +822,8 @@ def main() -> None:
|
||||
return None
|
||||
return project_map.get(str(pid))
|
||||
|
||||
|
||||
|
||||
def get_tags_for_task(task: Dict[str, Any]) -> List[Dict[str, str]]:
|
||||
lbls = task.get("labels") or task.get("label_ids") or task.get("labelIds") or []
|
||||
names: List[str] = []
|
||||
@@ -889,8 +878,7 @@ def main() -> None:
|
||||
due = normalize_due(task)
|
||||
prio = map_priority(task.get("priority"))
|
||||
project_uid = get_project_uid_for_task(task)
|
||||
tags = get_tags_for_task(task)
|
||||
|
||||
|
||||
# Tududi note: Todoist link + Todoist description
|
||||
tududi_description = build_tududi_description_from_todoist(task, name)
|
||||
|
||||
@@ -903,12 +891,20 @@ def main() -> None:
|
||||
is_completed = is_done_map.get(tid, False)
|
||||
completed_at = task.get("completed_at") or task.get("completedAt")
|
||||
|
||||
tag_objs = get_tags_for_task(task) # già [{"name":..., "uid":...}]
|
||||
|
||||
if tag_objs:
|
||||
print(f"[DEBUG] task={tid} tags_obj={tag_objs}")
|
||||
else:
|
||||
raw_lbls = task.get("labels") or task.get("label_ids") or task.get("labelIds")
|
||||
print(f"[DEBUG] task={tid} NO TAGS. raw_labels={raw_lbls}")
|
||||
|
||||
created = tud.create_task(
|
||||
name=name,
|
||||
project_id=project_uid,
|
||||
due_date=due,
|
||||
priority=prio,
|
||||
tags=tags if tags else None,
|
||||
tag_objs=tag_objs if tag_objs else None,
|
||||
description=tududi_description,
|
||||
note=tududi_description,
|
||||
parent_task_id=tud_parent_id,
|
||||
|
||||
Reference in New Issue
Block a user