mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
Homebox sync: fall back to tags when /labels is gone
Newer Homebox releases renamed labels to tags (/api/v1/tags and the items?tags= filter), so the labels call answered 404. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
@@ -5,7 +5,8 @@
|
||||
* API (Homebox's REST API, v1):
|
||||
* - `POST /api/v1/users/login` with username and password gives a token
|
||||
* (already prefixed `Bearer `), sent as `Authorization`.
|
||||
* - `GET /api/v1/labels` and `GET /api/v1/locations` name the ids to filter on.
|
||||
* - `GET /api/v1/labels` (`/api/v1/tags` on newer releases) and `GET /api/v1/locations`
|
||||
* name the ids to filter on.
|
||||
* - `GET /api/v1/items?labels=<id>&page=&pageSize=` (or `locations=<id>`)
|
||||
* lists the items, each with name, quantity and description.
|
||||
*
|
||||
@@ -84,7 +85,10 @@ export function materialOptions(items: HomeboxItem[]): StockOption[] {
|
||||
}
|
||||
|
||||
async function call(ctx: SyncContext, url: string, init: RequestInit = {}) {
|
||||
const res = await ctx.fetch(url, init);
|
||||
return checked(await ctx.fetch(url, init));
|
||||
}
|
||||
|
||||
async function checked(res: Response) {
|
||||
if (res.status === 401 || res.status === 403) throw new Error(`Homebox refused the request (${res.status}); check HOMEBOX_USER and HOMEBOX_PASS`);
|
||||
if (!res.ok) throw new Error(`Homebox answered ${res.status}`);
|
||||
return res.json() as Promise<unknown>;
|
||||
@@ -110,9 +114,14 @@ export function homeboxJob(o: HomeboxOptions): SyncJob {
|
||||
...(o.locations ?? []).map((f) => ({ kind: "locations" as const, f })),
|
||||
];
|
||||
const ids = { labels: new Map<string, string>(), locations: new Map<string, string>() };
|
||||
for (const kind of ["labels", "locations"] as const) {
|
||||
if (filters.some((x) => x.kind === kind)) ids[kind] = parseNamed(await call(ctx, api(`/${kind}`), { headers }));
|
||||
// Newer Homebox releases call labels "tags" (`/api/v1/tags`, `items?tags=`).
|
||||
let labelParam = "labels";
|
||||
if (filters.some((x) => x.kind === "labels")) {
|
||||
const res = await ctx.fetch(api("/labels"), { headers });
|
||||
if (res.status === 404) labelParam = "tags";
|
||||
ids.labels = parseNamed(res.status === 404 ? await call(ctx, api("/tags"), { headers }) : await checked(res));
|
||||
}
|
||||
if (filters.some((x) => x.kind === "locations")) ids.locations = parseNamed(await call(ctx, api("/locations"), { headers }));
|
||||
|
||||
const byGroup = new Map<string, HomeboxItem[]>();
|
||||
const unknown: string[] = [];
|
||||
@@ -124,7 +133,7 @@ export function homeboxJob(o: HomeboxOptions): SyncJob {
|
||||
}
|
||||
const items = byGroup.get(f.group) ?? [];
|
||||
for (let page = 1; page <= 20; page++) {
|
||||
const p = new URLSearchParams({ [kind]: id, page: String(page), pageSize: "100" });
|
||||
const p = new URLSearchParams({ [kind === "labels" ? labelParam : kind]: id, page: String(page), pageSize: "100" });
|
||||
const r = parseItems(await call(ctx, api(`/items?${p}`), { headers }));
|
||||
items.push(...r.items);
|
||||
if (r.items.length < 100 || page * 100 >= r.total) break;
|
||||
|
||||
Reference in New Issue
Block a user