aboutsummaryrefslogtreecommitdiffstats
path: root/src/internal-server/app/Controllers/Http/RecipeController.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal-server/app/Controllers/Http/RecipeController.js')
-rw-r--r--src/internal-server/app/Controllers/Http/RecipeController.js120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/internal-server/app/Controllers/Http/RecipeController.js b/src/internal-server/app/Controllers/Http/RecipeController.js
new file mode 100644
index 000000000..8a6b4f684
--- /dev/null
+++ b/src/internal-server/app/Controllers/Http/RecipeController.js
@@ -0,0 +1,120 @@
1const Recipe = use('App/Models/Recipe');
2const Drive = use('Drive');
3const {
4 validateAll,
5} = use('Validator');
6const Env = use('Env');
7
8const fetch = require('node-fetch');
9
10const RECIPES_URL = 'https://api.getferdi.com/v1/recipes';
11
12class RecipeController {
13 // List official and custom recipes
14 async list({
15 response,
16 }) {
17 const officialRecipes = JSON.parse(await (await fetch(RECIPES_URL)).text());
18 const customRecipesArray = (await Recipe.all()).rows;
19 const customRecipes = customRecipesArray.map(recipe => ({
20 id: recipe.recipeId,
21 name: recipe.name,
22 ...JSON.parse(recipe.data),
23 }));
24
25 const recipes = [
26 ...officialRecipes,
27 ...customRecipes,
28 ];
29
30 return response.send(recipes);
31 }
32
33 // Search official and custom recipes
34 async search({
35 request,
36 response,
37 }) {
38 // Validate user input
39 const validation = await validateAll(request.all(), {
40 needle: 'required',
41 });
42 if (validation.fails()) {
43 return response.status(401).send({
44 message: 'Please provide a needle',
45 messages: validation.messages(),
46 status: 401,
47 });
48 }
49
50 const needle = request.input('needle');
51
52 // Get results
53 let results;
54
55 if (needle === 'ferdi:custom') {
56 const dbResults = (await Recipe.all()).toJSON();
57 results = dbResults.map(recipe => ({
58 id: recipe.recipeId,
59 name: recipe.name,
60 ...JSON.parse(recipe.data),
61 }));
62 } else {
63 let remoteResults = [];
64 if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq
65 remoteResults = JSON.parse(await (await fetch(`${RECIPES_URL}/search?needle=${encodeURIComponent(needle)}`)).text());
66 }
67 const localResultsArray = (await Recipe.query().where('name', 'LIKE', `%${needle}%`).fetch()).toJSON();
68 const localResults = localResultsArray.map(recipe => ({
69 id: recipe.recipeId,
70 name: recipe.name,
71 ...JSON.parse(recipe.data),
72 }));
73
74 results = [
75 ...localResults,
76 ...remoteResults || [],
77 ];
78 }
79
80 return response.send(results);
81 }
82
83 // Download a recipe
84 async download({
85 response,
86 params,
87 }) {
88 // Validate user input
89 const validation = await validateAll(params, {
90 recipe: 'required|accepted',
91 });
92 if (validation.fails()) {
93 return response.status(401).send({
94 message: 'Please provide a recipe ID',
95 messages: validation.messages(),
96 status: 401,
97 });
98 }
99
100 const service = params.recipe;
101
102 // Check for invalid characters
103 if (/\.{1,}/.test(service) || /\/{1,}/.test(service)) {
104 return response.send('Invalid recipe name');
105 }
106
107 // Check if recipe exists in recipes folder
108 if (await Drive.exists(`${service}.tar.gz`)) {
109 return response.send(await Drive.get(`${service}.tar.gz`));
110 } if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq
111 return response.redirect(`${RECIPES_URL}/download/${service}`);
112 }
113 return response.status(400).send({
114 message: 'Recipe not found',
115 code: 'recipe-not-found',
116 });
117 }
118}
119
120module.exports = RecipeController;