commands/store.ts (view raw)
1import type { DatabaseSync } from "node:sqlite";
2import { callLLM } from "../utils/llm.ts";
3import { decodeHtmlChars } from "../utils/html.ts";
4
5export default async (db: DatabaseSync, recipeId: string) => {
6 let recipeUrl = "";
7 if (!recipeId) throw new Error("Please provide a recipe ID");
8 else if (recipeId.startsWith("https://")) recipeUrl = recipeId;
9 else recipeUrl = `https://cookidoo.fr/recipes/recipe/fr-FR/${recipeId}`;
10
11 const recipePage = await fetch(recipeUrl).then((res) => res.text());
12 const jsonLdTag = recipePage.match(
13 /<script type="application\/ld\+json">(.*?)<\/script>/s
14 )?.[1];
15 if (!jsonLdTag) throw new Error("No JSON-LD tag found");
16
17 const recipeJson = JSON.parse(jsonLdTag);
18
19 const existingItem = db
20 .prepare("SELECT * FROM recipes WHERE url = ?")
21 .get(recipeUrl);
22 if (existingItem) {
23 console.log("Recipe already exists in db");
24 db.close();
25 Deno.exit(0);
26 }
27
28 const rawIngredientsJson = await callLLM(`
29 À partir de la liste suivante, renvoi un objet JSON avec unit, value, name pour chacun des éléments.
30 ${decodeHtmlChars(recipeJson.recipeIngredient.join("\n"))}
31 Si la quantité est un nombre décimal, convertis le.
32 Utilise de préférences les unités les plus courantes comme g, pincée, cuillère à café, gousse.
33 Les unités doivent toujours être au singulier.
34 `);
35
36 const recipe = {
37 name: recipeJson.name,
38 ingredients: rawIngredientsJson,
39 imageUrl: recipeJson.image,
40 url: recipeUrl,
41 };
42
43 db.prepare(
44 `INSERT INTO recipes (url, name, ingredients, imageUrl) VALUES (?, ?, ?, ?)`
45 ).run(recipe.url, recipe.name, recipe.ingredients, recipe.imageUrl);
46
47 console.log(`New recipe "${recipe.name}" added to db.`);
48};