feat(lists): get_lists() without scope returns all circles (v0.8.2)
Implement v0.8.2: When get_lists() is called without a scope parameter, it now fetches lists from ALL circles instead of only the primary circle. Implementation: - Login once, call famlistfamily to get all circle IDs - For each circle, call taskgettasklists(scope=<circle_id>) - Merge results and return all lists with circle_id field All tests passed: test_multi circle creation, list creation in secondary circle, get_lists() without scope returns lists from both circles. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -286,7 +286,7 @@ def get_lists(scope: str | None = None) -> str:
|
||||
- A circle display name (e.g. ``"Test Kreis 2"``) — resolved to
|
||||
the matching circle metaId via ``get_circles`` first.
|
||||
|
||||
When ``None`` (default) the primary circle's lists are returned.
|
||||
When ``None`` (default) all lists from all circles are returned.
|
||||
|
||||
Returns:
|
||||
JSON list of list objects with keys id, name, type, open, total,
|
||||
@@ -300,10 +300,10 @@ def get_lists(scope: str | None = None) -> str:
|
||||
# Build the scope param for taskgettasklists.
|
||||
# When scope is provided as a circle name (not a metaId), we need to
|
||||
# resolve it via famlistfamily first — done in the same session.
|
||||
api_scope: str | None = None
|
||||
api_scopes: list[str] = []
|
||||
if scope:
|
||||
if scope.startswith("family/"):
|
||||
api_scope = scope
|
||||
api_scopes = [scope]
|
||||
else:
|
||||
# Treat as circle name — look up the metaId.
|
||||
try:
|
||||
@@ -321,41 +321,43 @@ def get_lists(scope: str | None = None) -> str:
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
api_scope = matched["metaId"]
|
||||
api_scopes = [matched["metaId"]]
|
||||
else:
|
||||
# No scope filter: fetch all circles and iterate over them.
|
||||
try:
|
||||
circles = _famlistfamily()
|
||||
api_scopes = [c["metaId"] for c in circles if "metaId" in c]
|
||||
except RuntimeError as exc:
|
||||
return f"Error: {exc}"
|
||||
|
||||
try:
|
||||
with FamilyWallClient() as client:
|
||||
client.login(email, password)
|
||||
params: dict[str, Any] = {}
|
||||
if api_scope:
|
||||
params["scope"] = api_scope
|
||||
data = client.call("taskgettasklists", params)
|
||||
all_lists: list[dict[str, Any]] = []
|
||||
for circle_scope in api_scopes:
|
||||
params: dict[str, Any] = {"scope": circle_scope}
|
||||
data = client.call("taskgettasklists", params)
|
||||
raw_lists: list[dict[str, Any]] | None = None
|
||||
try:
|
||||
candidate = data["a00"]["r"]["r"]
|
||||
if isinstance(candidate, list):
|
||||
raw_lists = candidate
|
||||
elif isinstance(candidate, dict) and isinstance(candidate.get("updatedCreated"), list):
|
||||
raw_lists = candidate["updatedCreated"]
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
|
||||
if raw_lists is not None:
|
||||
all_lists.extend(raw_lists)
|
||||
|
||||
client.logout()
|
||||
except FamilyWallError as exc:
|
||||
return f"Error: {exc}"
|
||||
except Exception as exc:
|
||||
return f"Connection error: {exc}"
|
||||
|
||||
# Try known response patterns; fall back to raw JSON for verification.
|
||||
raw_lists: list[dict[str, Any]] | None = None
|
||||
try:
|
||||
candidate = data["a00"]["r"]["r"]
|
||||
if isinstance(candidate, list):
|
||||
raw_lists = candidate
|
||||
elif isinstance(candidate, dict) and isinstance(candidate.get("updatedCreated"), list):
|
||||
raw_lists = candidate["updatedCreated"]
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
|
||||
if raw_lists is None:
|
||||
return json.dumps(
|
||||
{"warning": "Unexpected taskgettasklists response structure", "raw": data},
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
|
||||
result = []
|
||||
for item in raw_lists:
|
||||
for item in all_lists:
|
||||
# emoji: API returns "" when unset — normalise to None for a clean JSON null.
|
||||
# color: API omits the key entirely when unset — .get() returns None directly.
|
||||
raw_emoji: str = item.get("emoji", "")
|
||||
|
||||
Reference in New Issue
Block a user