Finished restructuring and changed way of querying the API
This commit is contained in:
20
backend/src/main/spoonaccular/APIAuthentication.java
Normal file
20
backend/src/main/spoonaccular/APIAuthentication.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package spoonaccular;
|
||||||
|
|
||||||
|
import io.github.cdimascio.dotenv.Dotenv;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
public class APIAuthentication {
|
||||||
|
|
||||||
|
private static Dotenv dotenv = Dotenv.load();
|
||||||
|
|
||||||
|
private APIAuthentication(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Request.Builder addAuthHeaders(Request.Builder builder){
|
||||||
|
return builder
|
||||||
|
.get()
|
||||||
|
.addHeader("X-RapidAPI-Key", dotenv.get("X-RapidAPI-Key"))
|
||||||
|
.addHeader("X-RapidAPI-Host", dotenv.get("X-RapidAPI-Host"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,40 +1,61 @@
|
|||||||
package spoonaccular;
|
package spoonaccular;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.github.cdimascio.dotenv.Dotenv;
|
import io.github.cdimascio.dotenv.Dotenv;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import spoonaccular.models.recipe_by_ingredient.ExtendedRecipeByIngredient;
|
import spoonaccular.models.recipe_by_ingredient.ExtendedRecipeByIngredient;
|
||||||
import spoonaccular.models.recipe_by_ingredient.RecipeByIngredient;
|
import spoonaccular.models.recipe_by_ingredient.RecipeByIngredient;
|
||||||
import spoonaccular.models.recipe_information.Recipe;
|
import spoonaccular.models.recipe_information.Recipe;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class RecipeInformation {
|
public class RecipeInformation {
|
||||||
|
|
||||||
private final Dotenv dotenv;
|
private final Dotenv dotenv;
|
||||||
|
private final OkHttpClient client;
|
||||||
|
|
||||||
public RecipeInformation(){
|
public RecipeInformation(){
|
||||||
dotenv = Dotenv.load();
|
dotenv = Dotenv.load();
|
||||||
|
client = new OkHttpClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Recipe getRecipeFromId(int id) throws IOException {
|
public List<Recipe> getRecipeFromIds(List<Integer> ids) throws IOException {
|
||||||
String urlString = dotenv.get("SPOONACCULAR_API_URL") + "/recipes/" + id + "/information?apiKey="+dotenv.get("SPOONACCULAR_API_KEY")+"&includeNutrition=false";
|
String idsString = ids.stream().map(String::valueOf)
|
||||||
URL url = new URL(urlString);
|
.collect(Collectors.joining(","));
|
||||||
return new ObjectMapper().readValue(url, Recipe.class);
|
return new ObjectMapper().readValue(queryInformationBulk(idsString).body().string(), new TypeReference<>(){});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExtendedRecipeByIngredient getExtendedRecipeFromId(int id) throws IOException {
|
public List<ExtendedRecipeByIngredient> getExtendedRecipeFromIds(List<Integer> ids) throws IOException {
|
||||||
String urlString = dotenv.get("SPOONACCULAR_API_URL") + "/recipes/" + id + "/information?apiKey="+dotenv.get("SPOONACCULAR_API_KEY")+"&includeNutrition=false";
|
String idsString = ids.stream().map(String::valueOf)
|
||||||
URL url = new URL(urlString);
|
.collect(Collectors.joining(","));
|
||||||
return new ObjectMapper().readValue(url, ExtendedRecipeByIngredient.class);
|
return new ObjectMapper().readValue(queryInformationBulk(idsString).body().string(), new TypeReference<>() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExtendedRecipeByIngredient getRecepieByIngredientsExtended(RecipeByIngredient recipeByIngredient) throws IOException {
|
private Response queryInformationBulk(String idsString) throws IOException {
|
||||||
ExtendedRecipeByIngredient extendedRecipeByIngredient = getExtendedRecipeFromId(recipeByIngredient.getId());
|
Request request = APIAuthentication.addAuthHeaders(new Request.Builder()
|
||||||
extendedRecipeByIngredient.setMissedIngredients(recipeByIngredient.getMissedIngredients());
|
.url("https://" + dotenv.get("X-RapidAPI-Host") +
|
||||||
return extendedRecipeByIngredient;
|
"/recipes/informationBulk?ids=" + idsString))
|
||||||
|
.build();
|
||||||
|
return client.newCall(request).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedRecipeByIngredient> getRecepieByIngredientsExtended(List<RecipeByIngredient> recipeByIngredients) throws IOException {
|
||||||
|
List<Integer> ids = recipeByIngredients.stream().map(RecipeByIngredient::getId).toList();
|
||||||
|
List<ExtendedRecipeByIngredient> extendedRecipeByIngredients = getExtendedRecipeFromIds(ids);
|
||||||
|
Iterator<RecipeByIngredient> recipeByIngredientIterator = recipeByIngredients.iterator();
|
||||||
|
Iterator<ExtendedRecipeByIngredient> extendedRecipeByIngredientIterator = extendedRecipeByIngredients.iterator();
|
||||||
|
while(recipeByIngredientIterator.hasNext() && extendedRecipeByIngredientIterator.hasNext()){
|
||||||
|
extendedRecipeByIngredientIterator.next().addMissingInfo(recipeByIngredientIterator.next());
|
||||||
|
}
|
||||||
|
return extendedRecipeByIngredients;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
package spoonaccular;
|
package spoonaccular;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.github.cdimascio.dotenv.Dotenv;
|
import io.github.cdimascio.dotenv.Dotenv;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import spoonaccular.models.recipe_by_ingredient.ExtendedRecipeByIngredient;
|
||||||
import spoonaccular.models.recipe_by_ingredient.RecipeByIngredient;
|
import spoonaccular.models.recipe_by_ingredient.RecipeByIngredient;
|
||||||
import spoonaccular.models.recipe_information.Recipe;
|
import spoonaccular.models.recipe_information.Recipe;
|
||||||
import whattocook.models.Item;
|
import whattocook.models.Item;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.http.HttpClient;
|
|
||||||
import java.net.http.HttpRequest;
|
|
||||||
import java.net.http.HttpResponse;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -25,33 +25,50 @@ public class RecipeSearch {
|
|||||||
|
|
||||||
private final Random rnd;
|
private final Random rnd;
|
||||||
private final Dotenv dotenv;
|
private final Dotenv dotenv;
|
||||||
|
private final RecipeInformation recipeInformation;
|
||||||
|
|
||||||
|
private final OkHttpClient client;
|
||||||
|
|
||||||
public RecipeSearch(){
|
public RecipeSearch(){
|
||||||
rnd = new Random();
|
rnd = new Random();
|
||||||
dotenv = Dotenv.load();
|
dotenv = Dotenv.load();
|
||||||
|
recipeInformation = new RecipeInformation();
|
||||||
|
client = new OkHttpClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipeByIngredient[] getForIngridients(Iterable<Item> items, int number) throws java.io.IOException {
|
public List<ExtendedRecipeByIngredient> getForIngridients(Iterable<Item> items, int number) throws java.io.IOException {
|
||||||
List<String> itemNames = new LinkedList<>();
|
List<String> itemNames = new LinkedList<>();
|
||||||
items.forEach(item -> itemNames.add(item.getName()));
|
items.forEach(item -> itemNames.add(item.getName()));
|
||||||
String ingridients = String.join(",", itemNames);
|
String ingridients = String.join(",", itemNames);
|
||||||
String urlString = dotenv.get("SPOONACCULAR_API_URL") + "/recipes/findByIngredients?apiKey=" + dotenv.get("SPOONACCULAR_API_KEY") + "&ingredients=" + ingridients + "&ranking=" + dotenv.get("SPOONACCULAR_API_SEARCH_RANKING") + "&ignorePantry=" + IGNOREPANTRY + "&number=" + number;
|
|
||||||
URL url = new URL(urlString);
|
|
||||||
return new ObjectMapper().readValue(url, RecipeByIngredient[].class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecipeByIngredient getOneForIngridients(Iterable<Item> items, int number) throws IOException {
|
Request request =
|
||||||
return getForIngridients(items, number)[rnd.nextInt(number)];
|
APIAuthentication.addAuthHeaders(new Request.Builder()
|
||||||
}
|
.url("https://" + dotenv.get("X-RapidAPI-Host") +
|
||||||
|
"/recipes/findByIngredients?ingredients="
|
||||||
public Recipe[] getRandom(List<String> tags, int number) throws java.io.IOException, InterruptedException, JSONException {
|
+ ingridients + "&number=" + number + "&ignorePantry="
|
||||||
String tagString = String.join(",", tags);
|
+ IGNOREPANTRY + "&ranking=" + dotenv.get("X-RapidAPI-SearchRanking")))
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
|
||||||
.uri(URI.create(dotenv.get("SPOONACCULAR_API_URL") + "/recipes/random?apiKey=" + dotenv.get("SPOONACCULAR_API_KEY") + "&number=" + number + "&tags=" + tagString))
|
|
||||||
.method("GET", HttpRequest.BodyPublishers.noBody())
|
|
||||||
.build();
|
.build();
|
||||||
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
|
|
||||||
JSONObject jsonObject = new JSONObject(response.body());
|
Response response = client.newCall(request).execute();
|
||||||
return new ObjectMapper().readValue(jsonObject.getJSONArray("recipes").toString(), Recipe[].class);
|
String responseString = response.body().string();
|
||||||
|
|
||||||
|
List<RecipeByIngredient> recipeByIngredients = new ObjectMapper().readValue(responseString, new TypeReference<>(){});
|
||||||
|
return recipeInformation.getRecepieByIngredientsExtended(recipeByIngredients);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedRecipeByIngredient getOneForIngridients(Iterable<Item> items, int number) throws IOException {
|
||||||
|
return this.getForIngridients(items, number).get(rnd.nextInt(number));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Recipe> getRandom(List<String> tags, int number) throws java.io.IOException, JSONException {
|
||||||
|
String tagString = String.join(",", tags);
|
||||||
|
Request request = APIAuthentication.addAuthHeaders(new Request.Builder()
|
||||||
|
.url("https://" + dotenv.get("X-RapidAPI-Host") +
|
||||||
|
"/recipes/random?number=" + number + "&tags=" + tagString))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
JSONObject jsonObject = new JSONObject(response.body().string());
|
||||||
|
return new ObjectMapper().readValue(jsonObject.getJSONArray("recipes").toString(), new TypeReference<>(){});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,4 +56,10 @@ public class ExtendedRecipeByIngredient extends Recipe {
|
|||||||
this.usedIngredients = usedIngredients;
|
this.usedIngredients = usedIngredients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addMissingInfo(RecipeByIngredient recipeByIngredient){
|
||||||
|
this.setMissedIngredientCount(recipeByIngredient.getMissedIngredientCount());
|
||||||
|
this.setUsedIngredientCount(recipeByIngredient.getUsedIngredientCount());
|
||||||
|
this.setMissedIngredients(recipeByIngredient.getMissedIngredients());
|
||||||
|
this.setUsedIngredients(recipeByIngredient.getUsedIngredients());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,18 +3,17 @@ package whattocook.controller;
|
|||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import spoonaccular.RecipeInformation;
|
import spoonaccular.RecipeInformation;
|
||||||
import spoonaccular.RecipeSearch;
|
import spoonaccular.RecipeSearch;
|
||||||
import spoonaccular.models.recipe_by_ingredient.ExtendedRecipeByIngredient;
|
import spoonaccular.models.recipe_by_ingredient.ExtendedRecipeByIngredient;
|
||||||
import spoonaccular.models.recipe_by_ingredient.RecipeByIngredient;
|
|
||||||
import spoonaccular.models.recipe_information.Recipe;
|
import spoonaccular.models.recipe_information.Recipe;
|
||||||
import whattocook.repositories.ItemRepository;
|
import whattocook.repositories.ItemRepository;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@RestController()
|
@RestController()
|
||||||
@RequestMapping(path = "recipe")
|
@RequestMapping(path = "recipe")
|
||||||
@@ -29,24 +28,18 @@ public class SpoonacularController {
|
|||||||
private RecipeSearch recipeSearch;
|
private RecipeSearch recipeSearch;
|
||||||
|
|
||||||
@GetMapping("/forFridge")
|
@GetMapping("/forFridge")
|
||||||
public RecipeByIngredient[] getForFridge() throws IOException {
|
public List<ExtendedRecipeByIngredient> getForFridge() throws IOException {
|
||||||
return recipeSearch.getForIngridients(itemRepository.findAll(), nextRecepies);
|
return recipeSearch.getForIngridients(itemRepository.findAll(), nextRecepies);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/random")
|
@GetMapping("/random")
|
||||||
public Recipe[] getRandom() throws IOException, InterruptedException, JSONException {
|
public List<Recipe> getRandom() throws IOException, InterruptedException, JSONException {
|
||||||
return recipeSearch.getRandom(new LinkedList<>(), nextRecepies);
|
return recipeSearch.getRandom(new LinkedList<>(), nextRecepies);
|
||||||
//when user has food preferences apply instead of linked list.
|
//when user has food preferences apply instead of linked list.
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/oneFridge")
|
@GetMapping("/oneFridge")
|
||||||
public ExtendedRecipeByIngredient getOneFridge() throws IOException {
|
public ExtendedRecipeByIngredient getOneFridge() throws IOException {
|
||||||
RecipeByIngredient recipe = recipeSearch.getOneForIngridients(itemRepository.findAll(), nextRecepiesForOneRandom);
|
return recipeSearch.getOneForIngridients(itemRepository.findAll(), nextRecepiesForOneRandom);
|
||||||
return recipeInformation.getRecepieByIngredientsExtended(recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/info/{id}")
|
|
||||||
public Recipe getInfo(@PathVariable int id) throws IOException {
|
|
||||||
return recipeInformation.getRecipeFromId(id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ dependencies {
|
|||||||
// https://mvnrepository.com/artifact/com.h2database/h2
|
// https://mvnrepository.com/artifact/com.h2database/h2
|
||||||
implementation group: 'com.h2database', name: 'h2', version: '1.3.148'
|
implementation group: 'com.h2database', name: 'h2', version: '1.3.148'
|
||||||
|
|
||||||
|
// okhttp
|
||||||
|
implementation("com.squareup.okhttp3:okhttp:4.10.0")
|
||||||
|
|
||||||
// lombok
|
// lombok
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
compileOnly 'org.projectlombok:lombok:1.18.24'
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||||
|
|||||||
Reference in New Issue
Block a user