import { createWriteStream, existsSync, mkdirSync } from "fs"; import sharp from "sharp"; import fs from "fs/promises"; import { pipeline } from "stream"; import { promisify } from "util"; const streamPipeline = promisify(pipeline); const apiUrl = "https://admin.ceiba-conseil.com"; async function fetchJSONApi(path) { const url = `${apiUrl}${path}`; const options = { method: "GET", headers: { "content-type": "application/json", }, }; console.log(`fetchJSONApi: ${url}`); const response = await fetch(url, options); if (!response.ok) { const errors = await response.json(); throw errors.errors[0].message; } return response.json(); } async function fetchAsset(uuid) { const url = `${apiUrl}/assets/${uuid}`; return fetch(url); } async function fetchScoresData() { const fields = [ "*", "translations.*", "questions.sort", "questions.questions_id.*", "questions.questions_id.translations.*", "questions.questions_id.answers.*", "questions.questions_id.answers.answers_id.*", "questions.questions_id.answers.answers_id.translations.*", "results.*", "results.results_id.*", "results.results_id.translations.*", ]; const url = `/items/scores?${fields .map((item) => `fields[]=${item}`) .join("&")}`; let scores = (await fetchJSONApi(url)).data; if (process.env.NODE_ENV == "production") { console.log("Suppresion des scores avec le mode brouillon en production"); scores = scores.filter((score) => !score.draft); } else if (process.env.NODE_ENV == "test") { console.log("Suppresion des scores sans l'environnement test"); scores = scores.filter((score) => score.env_test); } await fs.writeFile("./src/data.json", JSON.stringify(scores), "utf8"); const folder = "public/answers"; if (!existsSync(folder)) mkdirSync(folder); for (const score of scores) { const uuid_score = score.image; if (uuid_score) { console.log(`Score image : ${folder}/${uuid_score}`); const response = await fetchAsset(uuid_score); try { const thumbnail = sharp().resize({ height: 200 }).webp(); await streamPipeline( response.body, thumbnail, createWriteStream(`${folder}/${uuid_score}.webp`), ); } catch (err) { console.log(err); } } for (const question of score.questions) { for (const answer of question.questions_id.answers) { const uuid = answer.answers_id.image; if (uuid) { await downloadImage(uuid, `${folder}/${uuid}.webp`, { height: 200 }); } } } } // await sharp('src/assets/arbre.png').resize({ width: 440, height: 690 }).webp().toFile('public/arbre.webp') } async function transformImage(response, path, options, format = "webp") { try { let thumbnail; console.log(path); if (format == "webp") { thumbnail = sharp().resize(options).webp(); } else { thumbnail = sharp().resize(options).toFormat("png"); } const stream = createWriteStream(path); await streamPipeline(response.body, thumbnail, stream); await stream; } catch (err) { console.log(err); } } async function downloadImage(uuid, path, options, format = "webp") { const response = await fetchAsset(uuid); await transformImage(response, path, options, format); } async function fetchHomepageData() { const fields = ["*"]; const url = `/items/homepage?${fields .map((item) => `fields[]=${item}`) .join("&")}`; const homepage = (await fetchJSONApi(url)).data; await downloadImage(homepage.image, `public/homepage.webp`, { width: 1280, height: 720, fit: sharp.fit.cover, }); const favicons = [ { path: `public/favicon/android-icon-192x192.png`, options: { width: 192, height: 192, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-57x57.png`, options: { width: 57, height: 57, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-60x60.png`, options: { width: 60, height: 60, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-72x72.png`, options: { width: 72, height: 72, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-76x76.png`, options: { width: 76, height: 76, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-114x114.png`, options: { width: 114, height: 114, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-120x120.png`, options: { width: 120, height: 120, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-144x144.png`, options: { width: 144, height: 144, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-152x152.png`, options: { width: 152, height: 152, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/apple-icon-180x180.png`, options: { width: 180, height: 180, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/favicon-16x16.png`, options: { width: 16, height: 16, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/favicon-32x32.png`, options: { width: 32, height: 32, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/favicon-96x96.png`, options: { width: 96, height: 96, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/favicon-256x256.png`, options: { width: 256, height: 256, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/ms-icon-70x70.png`, options: { width: 70, height: 70, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/ms-icon-144x144.png`, options: { width: 144, height: 144, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/ms-icon-150x150.png`, options: { width: 150, height: 150, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, { path: `public/favicon/ms-icon-310x310.png`, options: { width: 310, height: 310, fit: sharp.fit.contain, background: { r: 255, g: 255, b: 255, alpha: 0 }, }, format: "png", }, ]; for (const favicon of favicons) { downloadImage(homepage.logo, favicon.path, favicon.options, favicon.format); } } async function fetchData() { await fetchHomepageData(); await fetchScoresData(); } fetchData();