albert-heijn-mcp 1.8.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -47,6 +47,8 @@ Ask in Dutch, English or any language your assistant speaks:
47
47
 
48
48
  > *"Plan three weeknight dinners around what's on bonus this week."*
49
49
 
50
+ > *"Put everything for the recipes in my AH meal planner on my shopping list."*
51
+
50
52
  **Save money**
51
53
 
52
54
  > *"Which products I usually buy are on bonus this week?"*
@@ -55,11 +57,19 @@ Ask in Dutch, English or any language your assistant speaks:
55
57
 
56
58
  > *"Is next week's bonus out yet? If not, when does it appear?"*
57
59
 
60
+ > *"Which of my personal offers are worth activating this week?"*
61
+
62
+ > *"How many koopzegels do I have, and what are they worth?"*
63
+
58
64
  > *"What's in the 2+1 gratis kaas deal?"*
59
65
 
60
66
  **Shop**
61
67
 
62
- > *"Put the products I've had delivered at least three times back on my list."*
68
+ > *"Put the products I buy most back on my list."*
69
+
70
+ > *"What's this product, and is it on bonus?"* (with a photo of its barcode)
71
+
72
+ > *"What's the cheapest cheese at AH right now?"*
63
73
 
64
74
  > *"Find organic, gluten-free pasta, cheapest first."*
65
75
 
@@ -354,7 +364,7 @@ Tools that return data also return it as [structured output](https://modelcontex
354
364
  |---|---|
355
365
  | `ah_login` | Log in: opens a login window on your computer, or returns AH's login link and completes the login with the code you paste back. |
356
366
  | `ah_logout` | Delete the stored tokens, to switch accounts or reset a session. |
357
- | `ah_get_member_profile` | Name, masked email, and bonus card number (last 4 digits). |
367
+ | `ah_get_member_profile` | Name, masked email, bonus card number (last 4 digits), and your savings: koopzegels (stamps, and what they're worth with interest) and Air Miles. |
358
368
 
359
369
  </details>
360
370
 
@@ -363,8 +373,9 @@ Tools that return data also return it as [structured output](https://modelcontex
363
373
 
364
374
  | Tool | Description |
365
375
  |---|---|
366
- | `ah_search_products` | Search one or more keywords at once; Dutch terms work best. Filter by `bonus=true` or by `filters` (organic, vegan, gluten_free and other diets, allergens and labels), and `sort` by price, what you buy most, or Nutri-Score. |
367
- | `ah_get_products` | Details for one or more products. `include_nutritional_info=true` adds the nutrition table. |
376
+ | `ah_search_products` | Search one or more keywords at once; Dutch terms work best. Filter by `bonus=true` or by `filters` (organic, vegan, gluten_free and other diets, allergens and labels), and `sort` by price, what you buy most, or Nutri-Score. `category_id` limits it to one category, or lists the category on its own. |
377
+ | `ah_get_products` | Details for one or more products, by product ID or by `barcodes` (the number under a barcode). `include_nutritional_info=true` adds the nutrition table. |
378
+ | `ah_get_categories` | AH's top-level product categories, or a category's subcategories with their product counts, for `category_id` in `ah_search_products`. |
368
379
  | `ah_get_product_alternatives` | Similar products and substitutes AH suggests for a product. |
369
380
  | `ah_get_bonus_offers` | This week's bonus offers, or next week's with `period=next`. `previously_bought=true` limits them to products you bought before (AH's "Eerder gekocht"). Can filter by keyword. |
370
381
  | `ah_get_bonus_group_products` | The individual products behind a group deal such as "2+1 gratis". |
@@ -382,6 +393,7 @@ Tools that return data also return it as [structured output](https://modelcontex
382
393
  |---|---|
383
394
  | `ah_search_recipes` | Search Allerhande recipes; Dutch terms work best. `filters` narrows by diet, course, cuisine, occasion, season or cooking method (e.g. `vegetarian`, `quick`, `italian`), and works without a query too; `sort` orders by relevance, newest or popular. |
384
395
  | `ah_get_recipe` | Ingredients, steps, and nutrition per serving. `servings` scales the ingredients. |
396
+ | `ah_get_meal_plan` | What's planned in the AH app's weekplanner for the next two weeks: recipes, products and notes. |
385
397
  | `ah_add_recipe_to_shopping_list` | Match a recipe's ingredients to products and add them to the list in one step. It prefers products on bonus (`prefer_bonus=false` turns that off); `skip` leaves out what you have, and `dry_run=true` previews the matches. |
386
398
 
387
399
  </details>
@@ -428,7 +440,7 @@ Choosing a delivery or pick-up slot in the AH app moves your shopping list into
428
440
  | `ah_get_order_details` | Products in one order. |
429
441
  | `ah_get_frequent_items` | The products you buy most, counted over your delivery orders and in-store receipts of the last few months (`months`, default 3). `source` limits it to `online` or `in_store`. |
430
442
  | `ah_get_receipts` | Recent in-store receipts (kassabonnen). |
431
- | `ah_get_receipt_details` | Items, discounts and payment for one receipt. |
443
+ | `ah_get_receipt_details` | Items, deposit, discounts, koopzegels bought and payment for one receipt, with its total. |
432
444
 
433
445
  </details>
434
446
 
@@ -436,8 +448,8 @@ Choosing a delivery or pick-up slot in the AH app moves your shopping list into
436
448
 
437
449
  - **Delivery orders can't be started through the API.** `ah_get_delivery_slots` lists the windows, but booking one, which starts the order, happens in the AH app or on ah.nl. While the order is active, AH doesn't serve the shopping list; the tools say so and point to the order tools.
438
450
  - **Ticking off shopping-list items isn't supported:** the API returns no usable item IDs.
439
- - **Bonus Box**, AH's personal weekly deals, is not available: its API is unknown.
440
- - **Limits per call:** at most 99 of a product, 50 items, and 100 characters for a free-text item or list name.
451
+ - **Recipes can't be planned in the meal planner:** `ah_get_meal_plan` reads it, but AH's API refuses to add recipes, so planning happens in the AH app.
452
+ - **Limits per call:** at most 99 of a product, 50 items, 100 characters for a free-text item or list name, and details for 20 products.
441
453
 
442
454
  ## Development
443
455
 
@@ -3,8 +3,8 @@ import { describeError } from "../log.js";
3
3
  // The API expects the official iOS app. If AH starts rejecting requests,
4
4
  // update the version and user agent to the current app release first.
5
5
  export const CLIENT_NAME = "appie-ios";
6
- const CLIENT_VERSION = "9.28";
7
- const USER_AGENT = "Appie/9.28 (iPhone17,3; iPhone; CPU OS 26_1 like Mac OS X)";
6
+ const CLIENT_VERSION = "9.48";
7
+ const USER_AGENT = "Appie/9.48 (iPhone17,3; iPhone; CPU OS 26_1 like Mac OS X)";
8
8
  const BASE_URL = "https://api.ah.nl";
9
9
  const TIMEOUT_MS = 30_000;
10
10
  /**
@@ -62,9 +62,15 @@ export function wrapError(message, err) {
62
62
  }
63
63
  /** The errors array of a GraphQL response. */
64
64
  export class GraphQLError extends Error {
65
- constructor(messages) {
65
+ /** Top-level fields the errors belong to, where AH says. */
66
+ fields;
67
+ /** Some error came without a field, so it may belong to any. */
68
+ unattributed;
69
+ constructor(messages, fields = [], unattributed = false) {
66
70
  super(`AH GraphQL error: ${messages.join("; ")}`);
67
71
  this.name = "GraphQLError";
72
+ this.fields = fields;
73
+ this.unattributed = unattributed;
68
74
  }
69
75
  logText() {
70
76
  return "AH GraphQL error";
@@ -131,7 +137,9 @@ export class AhClient {
131
137
  });
132
138
  return {
133
139
  data: res.data ?? undefined,
134
- errors: res.errors?.length ? new GraphQLError(res.errors.map((e) => e.message)) : undefined,
140
+ errors: res.errors?.length
141
+ ? new GraphQLError(res.errors.map((e) => e.message), res.errors.flatMap((e) => (typeof e.path?.[0] === "string" ? [e.path[0]] : [])), res.errors.some((e) => typeof e.path?.[0] !== "string"))
142
+ : undefined,
135
143
  };
136
144
  }
137
145
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/ahapi/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/ahapi/client.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { log } from "../log.js";
1
2
  /** "First Last", as AH shows it. */
2
3
  export function fullName(m) {
3
4
  return `${m.firstName} ${m.lastName}`.trim();
@@ -24,4 +25,43 @@ export async function getMember(c) {
24
25
  function isComplete(a) {
25
26
  return Boolean(a?.street && a.houseNumber && a.postalCode && a.city && a.countryCode);
26
27
  }
28
+ export async function getSavings(c) {
29
+ const query = `query Savings {
30
+ purchaseStampBalance {
31
+ points { totalPoints fullBooklets }
32
+ money { invested { amount } interest { amount } payout { amount } }
33
+ }
34
+ milesBalance { balance errorState }
35
+ }`;
36
+ // One balance failing leaves the other.
37
+ const { data, errors } = await c.graphqlPartial(query);
38
+ if (!data)
39
+ throw errors ?? new Error("AH returned no savings");
40
+ const k = data.purchaseStampBalance;
41
+ const m = data.milesBalance;
42
+ if (errors)
43
+ log.warn("some savings could not be fetched", { err: errors });
44
+ // A balance with an error of its own, at any depth, is unavailable or incomplete; an error AH gives no
45
+ // field for may be any balance's. A null balance without an error: the member just has none.
46
+ const failed = (field) => errors !== undefined && (errors.fields.includes(field) || errors.unattributed);
47
+ const unavailable = [];
48
+ if (failed("purchaseStampBalance"))
49
+ unavailable.push("koopzegels");
50
+ if (failed("milesBalance"))
51
+ unavailable.push("air_miles");
52
+ const koopzegels = {
53
+ stamps: k?.points?.totalPoints ?? undefined,
54
+ fullBooklets: k?.points?.fullBooklets ?? undefined,
55
+ invested: k?.money?.invested?.amount,
56
+ interest: k?.money?.interest?.amount,
57
+ payout: k?.money?.payout?.amount,
58
+ };
59
+ return {
60
+ // Absent, not empty, when AH sent no koopzegel figures at all.
61
+ koopzegels: Object.values(koopzegels).some((v) => v !== undefined) ? koopzegels : undefined,
62
+ // With an error state AH's balance (often 0) isn't the member's real balance.
63
+ airMiles: m ? { balance: m.errorState ? undefined : (m.balance ?? undefined), error: m.errorState ?? undefined } : undefined,
64
+ unavailable,
65
+ };
66
+ }
27
67
  //# sourceMappingURL=member.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"member.js","sourceRoot":"","sources":["../../src/ahapi/member.ts"],"names":[],"mappings":"AAsBA,oCAAoC;AACpC,MAAM,UAAU,QAAQ,CAAC,CAAS;IAChC,OAAO,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,CAAW;IACzC,MAAM,KAAK,GAAG;;;;;;;EAOd,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,OAAO,CAOlC,KAAK,CAAC,CAAC;IACV,OAAO;QACL,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QAC9B,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE;QAC5B,KAAK,EAAE,CAAC,CAAC,YAAY,IAAI,EAAE;QAC3B,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE;QACvC,eAAe,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;QACrC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;KACvD,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,CAA4C;IAC9D,OAAO,OAAO,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,CAAC,CAAC;AACxF,CAAC"}
1
+ {"version":3,"file":"member.js","sourceRoot":"","sources":["../../src/ahapi/member.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { hasStatus } from "./client.js";
1
2
  /**
2
3
  * Regular price, and the bonus price for products on bonus (else 0). Deals like
3
4
  * "2 voor 1.19" have no single bonus price: AH sends the regular price as both.
@@ -49,6 +50,10 @@ export async function getProductAlternatives(c, id, size) {
49
50
  }
50
51
  /** Largest page AH serves. */
51
52
  const MAX_PAGE = 100;
53
+ /** One page of AH's product search. */
54
+ function searchPage(c, params) {
55
+ return c.request(`/mobile-services/product/search/v2?${params}`);
56
+ }
52
57
  /** Searches by keyword; returns at most size products. */
53
58
  export async function searchProducts(c, query, size, opts = {}) {
54
59
  const properties = opts.properties ?? [];
@@ -62,12 +67,14 @@ export async function searchProducts(c, query, size, opts = {}) {
62
67
  else if (filterBonus)
63
68
  fetch = Math.min(Math.max(size * 4, 40), MAX_PAGE);
64
69
  const params = new URLSearchParams({ query, page: "0", size: String(fetch), sortOn: opts.sort ?? "RELEVANCE" });
70
+ if (opts.categoryId)
71
+ params.set("taxonomyId", String(opts.categoryId));
65
72
  // Several properties go comma-separated, which AH combines with AND.
66
73
  if (properties.length)
67
74
  params.set("filters", `property=${properties.join(",")}`);
68
75
  else if (opts.bonus)
69
76
  params.set("filters", "bonus=Bonus");
70
- const res = await c.request(`/mobile-services/product/search/v2?${params}`);
77
+ const res = await searchPage(c, params);
71
78
  let products = res.products ?? [];
72
79
  if (opts.bonus)
73
80
  products = products.filter((p) => p.isBonus);
@@ -79,18 +86,19 @@ export async function searchProducts(c, query, size, opts = {}) {
79
86
  }
80
87
  return products.slice(0, size);
81
88
  }
82
- export async function getProduct(c, id) {
83
- const res = await c.request(`/mobile-services/product/detail/v4/fir/${id}`);
84
- return res.productCard;
85
- }
86
89
  /** Ids per productsByIds call that keep the request URL a safe length. */
87
90
  export const PRODUCT_IDS_BATCH = 50;
88
- /** Returns products in the order of ids. */
91
+ /** Returns products in the order of ids, PRODUCT_IDS_BATCH per request; ids AH doesn't know are left out. */
89
92
  export async function productsByIds(c, ids) {
90
- const params = new URLSearchParams({ sortOn: "INPUT_PRODUCT_IDS" });
91
- for (const id of ids)
92
- params.append("ids", String(id));
93
- return (await c.request(`/mobile-services/product/search/v2/products?${params}`)) ?? [];
93
+ const products = [];
94
+ // One batch at a time, so a long list doesn't send AH a burst of requests.
95
+ for (let i = 0; i < ids.length; i += PRODUCT_IDS_BATCH) {
96
+ const params = new URLSearchParams({ sortOn: "INPUT_PRODUCT_IDS" });
97
+ for (const id of ids.slice(i, i + PRODUCT_IDS_BATCH))
98
+ params.append("ids", String(id));
99
+ products.push(...((await c.request(`/mobile-services/product/search/v2/products?${params}`)) ?? []));
100
+ }
101
+ return products;
94
102
  }
95
103
  /** First nutrition table (usually per 100 g/ml), or undefined if AH has none. */
96
104
  export async function getNutrition(c, id) {
@@ -125,4 +133,97 @@ export async function convertPosIds(c, posIds) {
125
133
  });
126
134
  return out;
127
135
  }
136
+ /**
137
+ * The code AH looks a barcode up by: its digits, a 12-digit UPC-A padded to the EAN-13 it is; undefined
138
+ * unless that is an EAN-8, EAN-13 or GTIN-14.
139
+ */
140
+ export function normalizeBarcode(barcode) {
141
+ // Only digits with spaces or dashes between them, as printed: other text ("x2") would change the number.
142
+ if (!/^[\d\s-]+$/.test(barcode.trim()))
143
+ return undefined;
144
+ const digits = barcode.replace(/\D/g, "");
145
+ // A 14-digit GTIN starting with 0 is the EAN-13 behind it: one form, so both share a lookup.
146
+ const code = digits.length === 12 ? `0${digits}` : digits.length === 14 && digits[0] === "0" ? digits.slice(1) : digits;
147
+ return [8, 13, 14].includes(code.length) ? code : undefined;
148
+ }
149
+ /**
150
+ * Whether a normalized barcode's last digit is its GS1 check digit; a digit misread from a photo fails this.
151
+ * 8-digit codes pass unchecked: a UPC-E has a different check digit than an EAN-8 of the same length.
152
+ */
153
+ export function hasValidCheckDigit(code) {
154
+ if (code.length === 8)
155
+ return true;
156
+ const digits = [...code].map(Number);
157
+ const check = digits.pop();
158
+ // From the right: weights 3, 1, 3, 1, ...
159
+ const sum = digits.reverse().reduce((acc, d, i) => acc + d * (i % 2 === 0 ? 3 : 1), 0);
160
+ return (10 - (sum % 10)) % 10 === check;
161
+ }
162
+ /** Webshop id of the product with this barcode (EAN/GTIN), or undefined if AH sells none. Throws on a malformed barcode. */
163
+ export async function productIdByBarcode(c, barcode) {
164
+ const code = normalizeBarcode(barcode);
165
+ if (!code)
166
+ throw new Error(`${barcode} is not a barcode number: barcodes have 8, 12, 13 or 14 digits`);
167
+ if (!hasValidCheckDigit(code))
168
+ throw new Error(`${barcode} is not a valid barcode (its check digit doesn't match): re-read the number`);
169
+ try {
170
+ const p = await c.request(`/mobile-services/product/search/v1/gtin/${code}`);
171
+ return p?.webshopId || undefined;
172
+ }
173
+ catch (err) {
174
+ // AH answers any number it doesn't know with 404.
175
+ if (hasStatus(err, 404))
176
+ return undefined;
177
+ throw err;
178
+ }
179
+ }
180
+ /**
181
+ * AH's top-level categories (the aisles of ah.nl). The API has no list of them since the product-shelves
182
+ * endpoints were removed, and the search facets only name a sample of narrower categories.
183
+ */
184
+ export const TOP_CATEGORIES = [
185
+ { id: 6401, name: "Groente, aardappelen" },
186
+ { id: 20885, name: "Fruit, verse sappen" },
187
+ { id: 1301, name: "Maaltijden, salades" },
188
+ { id: 9344, name: "Vlees" },
189
+ { id: 1651, name: "Vis" },
190
+ { id: 20128, name: "Vegetarisch, vegan en plantaardig" },
191
+ { id: 5481, name: "Vleeswaren" },
192
+ { id: 1192, name: "Kaas" },
193
+ { id: 1730, name: "Zuivel, eieren" },
194
+ { id: 1355, name: "Bakkerij" },
195
+ { id: 4246, name: "Glutenvrij" },
196
+ { id: 20824, name: "Borrel, chips, snacks" },
197
+ { id: 1796, name: "Pasta, rijst, wereldkeuken" },
198
+ { id: 6409, name: "Soepen, sauzen, kruiden, olie" },
199
+ { id: 20129, name: "Koek, snoep, chocolade" },
200
+ { id: 6405, name: "Ontbijtgranen, beleg" },
201
+ { id: 2457, name: "Tussendoortjes" },
202
+ { id: 5881, name: "Diepvries" },
203
+ { id: 1043, name: "Koffie, thee" },
204
+ { id: 20130, name: "Frisdrank, sappen, water" },
205
+ { id: 6406, name: "Bier, wijn, aperitieven" },
206
+ { id: 11717, name: "Gezondheid en sport" },
207
+ { id: 1045, name: "Drogisterij" },
208
+ { id: 18521, name: "Baby en kind" },
209
+ { id: 1165, name: "Huishouden" },
210
+ { id: 18519, name: "Huisdier" },
211
+ { id: 1057, name: "Koken, tafelen, vrije tijd" },
212
+ ];
213
+ const TOP_CATEGORY_IDS = new Set(TOP_CATEGORIES.map((t) => t.id));
214
+ /**
215
+ * Subcategories of parentId: the narrower categories its products fall into. AH's categories overlap, so one
216
+ * can show up under several parents. undefined if parentId has no products (not a category id).
217
+ */
218
+ export async function getSubcategories(c, parentId) {
219
+ const res = await searchPage(c, new URLSearchParams({ query: "", page: "0", size: "1", taxonomyId: String(parentId) }));
220
+ const total = res.page?.totalElements ?? 0;
221
+ if (total === 0)
222
+ return undefined;
223
+ const options = res.filters?.find((f) => f.id === "taxonomy")?.options ?? [];
224
+ // The facet also names the category itself and every category holding all its products (its ancestors).
225
+ return options
226
+ .map((o) => ({ id: Number(o.id), name: o.label, products: o.count }))
227
+ .filter((o) => Number.isInteger(o.id) && o.id > 0 && o.id !== parentId && !TOP_CATEGORY_IDS.has(o.id) && o.products < total);
228
+ }
128
229
  //# sourceMappingURL=products.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/ahapi/products.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/ahapi/products.ts"],"names":[],"mappings":"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"}
@@ -16,9 +16,11 @@ export async function getReceipt(c, id) {
16
16
  const query = `query Receipt($id: String!) {
17
17
  posReceiptDetails(id: $id) {
18
18
  id
19
- products { name quantity price { amount } amount { amount } }
19
+ products { name quantity price { amount } amount { amount } deposit { amount } }
20
20
  discounts { name amount { amount } }
21
+ stamps { quantity amount { amount } }
21
22
  payments { method amount { amount } }
23
+ total { amount }
22
24
  }
23
25
  }`;
24
26
  const { posReceiptDetails: d } = await c.graphql(query, { id });
@@ -29,9 +31,14 @@ export async function getReceipt(c, id) {
29
31
  quantity: p.quantity,
30
32
  unitPrice: p.price?.amount,
31
33
  total: p.amount?.amount ?? 0,
34
+ deposit: p.deposit?.amount || undefined,
32
35
  })),
33
36
  discounts: (d.discounts ?? []).map((x) => ({ name: x.name, amount: x.amount?.amount ?? 0 })),
37
+ stamps: d.stamps?.quantity || d.stamps?.amount?.amount
38
+ ? { quantity: d.stamps.quantity ?? 0, amount: d.stamps.amount?.amount ?? 0 }
39
+ : undefined,
34
40
  payments: (d.payments ?? []).map((x) => ({ method: x.method, amount: x.amount?.amount ?? 0 })),
41
+ total: d.total?.amount,
35
42
  };
36
43
  }
37
44
  const RECEIPT_PAGE = 100;
@@ -1 +1 @@
1
- {"version":3,"file":"receipts.js","sourceRoot":"","sources":["../../src/ahapi/receipts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"receipts.js","sourceRoot":"","sources":["../../src/ahapi/receipts.ts"],"names":[],"mappings":"AASA,uDAAuD;AACvD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,CAAW,EAAE,KAAa,EAAE,MAAM,GAAG,CAAC;IACtE,MAAM,KAAK,GAAG;;;;EAId,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,OAAO,CAEzB,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1D,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,KAAK,EAAE,CAAC,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC;KAClC,CAAC,CAAC,CAAC;AACN,CAAC;AAcD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,CAAW,EAAE,EAAU;IACtD,MAAM,KAAK,GAAG;;;;;;;;;EASd,CAAC;IAED,MAAM,EAAE,iBAAiB,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,OAAO,CAS7C,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAClB,OAAO;QACL,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM;YAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;YAC5B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,SAAS;SACxC,CAAC,CAAC;QACH,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM;YACpD,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE;YAC5E,CAAC,CAAC,SAAS;QACb,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9F,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,CAAW,EACX,IAAoC,EACpC,GAAW;IAEX,MAAM,GAAG,GAAqB,EAAE,CAAC;IACjC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,IAAI,YAAY,EAAE,CAAC;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAChD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAE,OAAO,GAAG,CAAC;YACzB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI;YAAE,MAAM;IAChC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAQD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,CAAW,EAAE,GAAa;IAC9D,IAAI,GAAG,CAAC,MAAM,GAAG,mBAAmB;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,mBAAmB,oBAAoB,CAAC,CAAC;IAC1G,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,8BAA8B,CAAC,qCAAqC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEzH,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,cAAc,CAC7C,sBAAsB,IAAI,UAAU,MAAM,KAAK,EAC/C,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CACvD,CAAC;IACF,IAAI,CAAC,IAAI;QAAE,MAAM,MAAM,IAAI,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACvE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;aAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;aACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { log } from "../log.js";
1
2
  const AH_WEB = new URL("https://www.ah.nl/");
2
3
  export function recipeUrl(id, slug) {
3
4
  return new URL(`/allerhande/recept/R-R${id}/${encodeURIComponent(slug)}`, AH_WEB).href;
@@ -13,7 +14,8 @@ function decodeEntities(s) {
13
14
  return s.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi, (m, e) => {
14
15
  if (e[0] === "#") {
15
16
  const code = e[1] === "x" || e[1] === "X" ? parseInt(e.slice(2), 16) : parseInt(e.slice(1), 10);
16
- return Number.isFinite(code) ? String.fromCodePoint(code) : m;
17
+ // Beyond Unicode, fromCodePoint throws: leave such an entity as written.
18
+ return Number.isFinite(code) && code <= 0x10ffff ? String.fromCodePoint(code) : m;
17
19
  }
18
20
  return named[e.toLowerCase()] ?? m;
19
21
  });
@@ -61,4 +63,63 @@ export async function getRecipe(c, id, servings) {
61
63
  preparation: r.preparation && { steps: r.preparation.steps?.map(decodeEntities) },
62
64
  };
63
65
  }
66
+ /**
67
+ * The planner from today, one entry per day (AH returns two weeks), with what is planned on it.
68
+ * incomplete: AH failed on some days or entries, so the plan may be missing some.
69
+ */
70
+ export async function getMealPlan(c) {
71
+ const query = `query MealPlan {
72
+ recipeWeekPlannerOverview {
73
+ days {
74
+ date
75
+ items {
76
+ __typename
77
+ ... on WeekPlannerRecipeItem { recipeId recipeTitle recipe { slug } }
78
+ ... on WeekPlannerMemberRecipeItem { recipeId recipeTitle }
79
+ ... on WeekPlannerNoteItem { text }
80
+ ... on WeekPlannerProductItem { productId productTitle }
81
+ }
82
+ }
83
+ }
84
+ }`;
85
+ // An entry AH fails to resolve (e.g. an unpublished recipe) comes back null without losing the other days.
86
+ const { data, errors } = await c.graphqlPartial(query);
87
+ const days = data?.recipeWeekPlannerOverview?.days;
88
+ // With errors, no days, or days that all failed, is a failed fetch; an empty list is an empty plan.
89
+ if (!data || (errors && (!days || (days.length > 0 && !days.some(Boolean)))))
90
+ throw errors ?? new Error("AH returned no meal plan");
91
+ if (errors)
92
+ log.warn("some meal plan entries could not be fetched", { err: errors });
93
+ // undefined when AH sent no title.
94
+ const titleOf = (t) => (t ? decodeEntities(t) : undefined);
95
+ const toItem = (i) => {
96
+ if (!i)
97
+ return { kind: "other" };
98
+ switch (i.__typename) {
99
+ case "WeekPlannerRecipeItem":
100
+ if (i.recipeId) {
101
+ return { kind: "recipe", recipeId: i.recipeId, title: titleOf(i.recipeTitle), slug: i.recipe?.slug ?? undefined };
102
+ }
103
+ break;
104
+ case "WeekPlannerMemberRecipeItem":
105
+ if (i.recipeId)
106
+ return { kind: "own_recipe", recipeId: i.recipeId, title: titleOf(i.recipeTitle) };
107
+ break;
108
+ case "WeekPlannerProductItem":
109
+ if (i.productId)
110
+ return { kind: "product", productId: i.productId, title: titleOf(i.productTitle) };
111
+ break;
112
+ case "WeekPlannerNoteItem":
113
+ return { kind: "note", text: decodeEntities(i.text ?? "") };
114
+ }
115
+ // A kind this server doesn't know, or an entry missing its id: shown, not hidden.
116
+ const title = i.recipeTitle ?? i.productTitle ?? i.text;
117
+ return { kind: "other", title: title ? decodeEntities(title) : undefined };
118
+ };
119
+ // No planner yet (never used) is an empty plan; a day AH fails to resolve comes back null and is left out.
120
+ return {
121
+ days: (days ?? []).flatMap((d) => (d ? [{ date: d.date, items: (d.items ?? []).map(toItem) }] : [])),
122
+ incomplete: Boolean(errors),
123
+ };
124
+ }
64
125
  //# sourceMappingURL=recipes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"recipes.js","sourceRoot":"","sources":["../../src/ahapi/recipes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recipes.js","sourceRoot":"","sources":["../../src/ahapi/recipes.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { z } from "zod";
2
- import { fullName, getMember, LOGIN_URL } from "../ahapi/index.js";
2
+ import { fullName, getMember, getSavings, LOGIN_URL } from "../ahapi/index.js";
3
3
  import { openInDefaultBrowser } from "../auth/browser.js";
4
4
  import { extractCode, manualLoginSteps, STALE_LOGIN } from "../auth/login.js";
5
5
  import { log } from "../log.js";
6
- import { addAuthedTool, addTool, structured, text } from "./common.js";
6
+ import { addAuthedTool, addTool, nonFatal, structured, text, withRetry } from "./common.js";
7
7
  export function registerAccountTools(server, ctx) {
8
8
  addTool(server, {
9
9
  name: "ah_login",
@@ -93,16 +93,55 @@ export function registerAccountTools(server, ctx) {
93
93
  name: "ah_get_member_profile",
94
94
  title: "Albert Heijn: Member Profile",
95
95
  kind: "readOnly",
96
- output: { name: z.string(), email: z.string().optional(), bonus_card_number: z.string().optional() },
97
- description: "Get your Albert Heijn member profile. " +
98
- "Returns name, email (masked), and bonus_card_number (last 4 digits only).",
96
+ output: {
97
+ name: z.string(),
98
+ email: z.string().optional(),
99
+ bonus_card_number: z.string().optional(),
100
+ koopzegels: z
101
+ .object({
102
+ stamps: z.number().optional(),
103
+ full_booklets: z.number().optional(),
104
+ invested: z.number().optional(),
105
+ interest: z.number().optional(),
106
+ payout_value: z.number().optional(),
107
+ })
108
+ .optional(),
109
+ air_miles: z.number().optional(),
110
+ air_miles_error: z.string().optional(),
111
+ savings_error: z.string().optional(),
112
+ },
113
+ description: "Get your Albert Heijn member profile and savings. " +
114
+ "Returns name, email (masked), bonus_card_number (last 4 digits only), " +
115
+ "koopzegels (savings stamps: stamps saved, full booklets, euros invested, interest earned, and payout_value " +
116
+ "they are worth now), and the air_miles balance.",
99
117
  }, async (c) => {
100
- const m = await getMember(c);
118
+ const [m, savings] = await Promise.all([
119
+ // Not the member cache: the profile should show changes made in the AH app right away.
120
+ getMember(c),
121
+ // The profile still comes back if the balances can't.
122
+ nonFatal(() => withRetry("ah_get_member_profile", () => getSavings(c)), (err) => {
123
+ log.warn("could not fetch savings", { tool: "ah_get_member_profile", err });
124
+ // The details stay in the log: an AH error can quote a whole response body.
125
+ return { unavailable: ["koopzegels", "air_miles"] };
126
+ }),
127
+ ]);
101
128
  const card = m.bonusCardNumber;
129
+ const k = savings.koopzegels;
102
130
  return structured({
103
131
  name: fullName(m),
104
132
  email: maskEmail(m.email) || undefined,
105
133
  bonus_card_number: card ? (card.length > 4 ? `****${card.slice(-4)}` : card) : undefined,
134
+ koopzegels: k && {
135
+ stamps: k.stamps,
136
+ full_booklets: k.fullBooklets,
137
+ invested: k.invested,
138
+ interest: k.interest,
139
+ payout_value: k.payout,
140
+ },
141
+ air_miles: savings.airMiles?.balance,
142
+ air_miles_error: savings.airMiles?.error,
143
+ // A balance listed here may be missing or incomplete.
144
+ savings_error: savings.unavailable.length ? `could not fully fetch: ${savings.unavailable.join(", ")}` : undefined,
106
145
  });
107
146
  });
108
147
  }