1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# Copyright (C) 2026 Danilo M. <danix@danix.xyz> GPL-2.0-only
from firefly_cli.errors import ResolutionError
class Resolver:
def __init__(self, client):
self.client = client
def _list(self, path):
resp = self.client.request("GET", path, params={"limit": 1000})
out = []
for item in resp.get("data", []):
attrs = item.get("attributes", {})
out.append({"id": item.get("id"), **attrs})
return out
def _match(self, kind, items, name):
hits = [i for i in items if str(i.get("name", "")).lower() == name.lower()]
if len(hits) == 1:
return hits[0]
names = ", ".join(f'{i.get("name")}(id={i.get("id")})' for i in items)
if not hits:
raise ResolutionError(
f'No {kind} named "{name}". Available: {names or "(none)"}')
raise ResolutionError(
f'Ambiguous {kind} "{name}" matches ids '
+ ", ".join(i["id"] for i in hits))
def account(self, name):
return self._match("account", self._list("/api/v1/accounts"), name)
def account_by_id(self, acc_id):
# Escape hatch for same-name accounts (ISSUES.md #2): GET the account
# directly; a bad id 404s and client.request surfaces a FireflyError.
item = self.client.request("GET", f"/api/v1/accounts/{acc_id}")["data"]
return {"id": item["id"], **item.get("attributes", {})}
def tag(self, name):
return self._match("tag", self._list("/api/v1/tags"), name)
def category(self, name):
return self._match("category", self._list("/api/v1/categories"), name)
|