From d8d58f9fb6ebe1cfbe47f37c4d76eef5d78cb87a Mon Sep 17 00:00:00 2001 From: Jason House Date: Sun, 5 Jan 2020 15:50:53 +0900 Subject: [PATCH] Removing Gaps object Switching URL creation from web to backend v0.1.1 --- Core/pom.xml | 2 +- .../main/java/com/jasonhhouse/gaps/Gaps.java | 159 ------------- .../java/com/jasonhhouse/gaps/GapsSearch.java | 2 +- Dockerfile.no-ssl | 4 +- Dockerfile.ssl | 4 +- GapsWeb/pom.xml | 4 +- .../gaps/controller/SearchController.java | 67 +----- .../gaps/service/GapsSearchService.java | 213 +++++------------- .../gaps/service/GapsServiceImpl.java | 15 +- .../validator/PlexLibrariesValidator.java | 2 +- GapsWeb/src/main/resources/application.yaml | 4 +- .../main/resources/static/js/plexMovieList.js | 22 -- .../src/main/resources/templates/folder.html | 2 +- .../src/main/resources/templates/index.html | 2 +- .../gaps/GapsSearchServiceTest.java | 42 +--- dockerBuild.sh | 10 +- pom.xml | 2 +- 17 files changed, 108 insertions(+), 448 deletions(-) delete mode 100644 Core/src/main/java/com/jasonhhouse/gaps/Gaps.java diff --git a/Core/pom.xml b/Core/pom.xml index 18aeff0..79c50e1 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -5,7 +5,7 @@ Gaps com.jasonhhouse - 0.1.0 + 0.1.1 4.0.0 diff --git a/Core/src/main/java/com/jasonhhouse/gaps/Gaps.java b/Core/src/main/java/com/jasonhhouse/gaps/Gaps.java deleted file mode 100644 index d406a38..0000000 --- a/Core/src/main/java/com/jasonhhouse/gaps/Gaps.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2020 Jason H House - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package com.jasonhhouse.gaps; - -import java.util.List; -import java.util.Objects; - -public class Gaps { - - private String movieDbApiKey; - - private Boolean writeToFile; - - private String movieDbListId; - - private Boolean searchFromPlex; - - private Integer connectTimeout; - - private Integer writeTimeout; - - private Integer readTimeout; - - private List movieUrls; - - private Boolean searchFromFolder; - - public Gaps() { - } - - public Gaps(String movieDbApiKey, Boolean writeToFile, String movieDbListId, Boolean searchFromPlex, Integer connectTimeout, Integer writeTimeout, Integer readTimeout, List movieUrls, Boolean searchFromFolder) { - this.movieDbApiKey = movieDbApiKey; - this.writeToFile = writeToFile; - this.movieDbListId = movieDbListId; - this.searchFromPlex = searchFromPlex; - this.connectTimeout = connectTimeout; - this.writeTimeout = writeTimeout; - this.readTimeout = readTimeout; - this.movieUrls = movieUrls; - this.searchFromFolder = searchFromFolder; - } - - public String getMovieDbApiKey() { - return movieDbApiKey; - } - - public void setMovieDbApiKey(String movieDbApiKey) { - this.movieDbApiKey = movieDbApiKey; - } - - public Boolean getWriteToFile() { - return writeToFile; - } - - public void setWriteToFile(Boolean writeToFile) { - this.writeToFile = writeToFile; - } - - public String getMovieDbListId() { - return movieDbListId; - } - - public void setMovieDbListId(String movieDbListId) { - this.movieDbListId = movieDbListId; - } - - public Boolean getSearchFromPlex() { - return searchFromPlex; - } - - public void setSearchFromPlex(Boolean searchFromPlex) { - this.searchFromPlex = searchFromPlex; - } - - public Integer getConnectTimeout() { - return connectTimeout; - } - - public void setConnectTimeout(Integer connectTimeout) { - this.connectTimeout = connectTimeout; - } - - public Integer getWriteTimeout() { - return writeTimeout; - } - - public void setWriteTimeout(Integer writeTimeout) { - this.writeTimeout = writeTimeout; - } - - public Integer getReadTimeout() { - return readTimeout; - } - - public void setReadTimeout(Integer readTimeout) { - this.readTimeout = readTimeout; - } - - public List getMovieUrls() { - return movieUrls; - } - - public void setMovieUrls(List movieUrls) { - this.movieUrls = movieUrls; - } - - public Boolean getSearchFromFolder() { - return searchFromFolder; - } - - public void setSearchFromFolder(Boolean searchFromFolder) { - this.searchFromFolder = searchFromFolder; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Gaps gaps = (Gaps) o; - return Objects.equals(movieDbApiKey, gaps.movieDbApiKey) && - Objects.equals(writeToFile, gaps.writeToFile) && - Objects.equals(movieDbListId, gaps.movieDbListId) && - Objects.equals(searchFromPlex, gaps.searchFromPlex) && - Objects.equals(connectTimeout, gaps.connectTimeout) && - Objects.equals(writeTimeout, gaps.writeTimeout) && - Objects.equals(readTimeout, gaps.readTimeout) && - Objects.equals(movieUrls, gaps.movieUrls) && - Objects.equals(searchFromFolder, gaps.searchFromFolder); - } - - @Override - public int hashCode() { - return Objects.hash(movieDbApiKey, writeToFile, movieDbListId, searchFromPlex, connectTimeout, writeTimeout, readTimeout, movieUrls, searchFromFolder); - } - - @Override - public String toString() { - return "Gaps{" + - "movieDbApiKey='" + movieDbApiKey + '\'' + - ", writeToFile=" + writeToFile + - ", movieDbListId='" + movieDbListId + '\'' + - ", searchFromPlex=" + searchFromPlex + - ", connectTimeout=" + connectTimeout + - ", writeTimeout=" + writeTimeout + - ", readTimeout=" + readTimeout + - ", movieUrls=" + movieUrls + - ", searchFromFolder=" + searchFromFolder + - '}'; - } - -} diff --git a/Core/src/main/java/com/jasonhhouse/gaps/GapsSearch.java b/Core/src/main/java/com/jasonhhouse/gaps/GapsSearch.java index af8ebcc..596e659 100644 --- a/Core/src/main/java/com/jasonhhouse/gaps/GapsSearch.java +++ b/Core/src/main/java/com/jasonhhouse/gaps/GapsSearch.java @@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull; public interface GapsSearch { - void run(@NotNull Gaps gaps); + void run(); @NotNull Integer getTotalMovieCount(); diff --git a/Dockerfile.no-ssl b/Dockerfile.no-ssl index f0f44ae..4b80ab7 100644 --- a/Dockerfile.no-ssl +++ b/Dockerfile.no-ssl @@ -12,6 +12,6 @@ RUN mkdir -p /usr/app WORKDIR /usr/app -COPY GapsWeb/target/GapsWeb-0.1.0.jar /usr/app/ +COPY GapsWeb/target/GapsWeb-0.1.1.jar /usr/app/ -ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=no-ssl", "GapsWeb-0.1.0.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=no-ssl", "GapsWeb-0.1.1.jar"] \ No newline at end of file diff --git a/Dockerfile.ssl b/Dockerfile.ssl index 284a8f5..726e745 100644 --- a/Dockerfile.ssl +++ b/Dockerfile.ssl @@ -12,6 +12,6 @@ RUN mkdir -p /usr/app WORKDIR /usr/app -COPY GapsWeb/target/GapsWeb-0.1.0.jar /usr/app/ +COPY GapsWeb/target/GapsWeb-0.1.1.jar /usr/app/ -ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=ssl", "GapsWeb-0.1.0.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=ssl", "GapsWeb-0.1.1.jar"] \ No newline at end of file diff --git a/GapsWeb/pom.xml b/GapsWeb/pom.xml index 3937da3..7bdcfb9 100644 --- a/GapsWeb/pom.xml +++ b/GapsWeb/pom.xml @@ -5,7 +5,7 @@ Gaps com.jasonhhouse - 0.1.0 + 0.1.1 4.0.0 @@ -19,7 +19,7 @@ com.jasonhhouse Core - 0.1.0 + 0.1.1 diff --git a/GapsWeb/src/main/java/com/jasonhhouse/gaps/controller/SearchController.java b/GapsWeb/src/main/java/com/jasonhhouse/gaps/controller/SearchController.java index ddc773d..33e9c20 100644 --- a/GapsWeb/src/main/java/com/jasonhhouse/gaps/controller/SearchController.java +++ b/GapsWeb/src/main/java/com/jasonhhouse/gaps/controller/SearchController.java @@ -9,21 +9,15 @@ */ package com.jasonhhouse.gaps.controller; -import com.jasonhhouse.gaps.Gaps; import com.jasonhhouse.gaps.GapsSearch; -import com.jasonhhouse.gaps.Movie; +import com.jasonhhouse.gaps.GapsService; import com.jasonhhouse.gaps.service.IoService; -import java.util.List; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; @@ -54,67 +48,14 @@ public class SearchController { * Main REST call to start Gaps searching for missing movies * * @param gaps Needs the gaps object to get started with Plex information and TMDB key - * @return All missing movies with their release year and collections associated to them */ @RequestMapping(value = "startSearching", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) - public void postStartSearching(@RequestBody Gaps gaps) { - LOGGER.info("postStartSearching( " + gaps + " )"); + public void postStartSearching() { + LOGGER.info("postStartSearching( )"); ioService.migrateJsonSeedFileIfNeeded(); - //Error checking - if (StringUtils.isEmpty(gaps.getMovieDbApiKey())) { - String reason = "Missing Movie DB Api Key. This field is required for Gaps."; - LOGGER.error(reason); - - Exception e = new IllegalArgumentException(); - throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, reason, e); - } - - if (BooleanUtils.isNotTrue(gaps.getSearchFromPlex()) && BooleanUtils.isNotTrue(gaps.getSearchFromFolder())) { - String reason = "Must search from Plex and/or folders. One or both of these fields is required for Gaps."; - LOGGER.error(reason); - - Exception e = new IllegalArgumentException(); - throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, reason, e); - } - - if (BooleanUtils.isNotFalse(gaps.getSearchFromPlex())) { - if (CollectionUtils.isEmpty(gaps.getMovieUrls())) { - String reason = "Missing Plex movie collection urls. This field is required to search from Plex."; - LOGGER.error(reason); - - Exception e = new IllegalArgumentException(); - throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, reason, e); - } else { - for (String url : gaps.getMovieUrls()) { - if (url == null) { - String reason = "Found null Plex movie collection url. This field is required to search from Plex."; - LOGGER.error(reason); - Exception e = new IllegalArgumentException(); - throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, reason, e); - } - } - } - } - - //Fill in default values if missing - if (gaps.getWriteTimeout() == null) { - LOGGER.info("Missing write timeout. Setting default to 180 seconds."); - gaps.setWriteTimeout(180); - } - - if (gaps.getConnectTimeout() == null) { - LOGGER.info("Missing connect timeout. Setting default to 180 seconds."); - gaps.setConnectTimeout(180); - } - - if (gaps.getReadTimeout() == null) { - LOGGER.info("Missing read timeout. Setting default to 180 seconds."); - gaps.setReadTimeout(180); - } - - gapsSearch.run(gaps); + gapsSearch.run(); } } diff --git a/GapsWeb/src/main/java/com/jasonhhouse/gaps/service/GapsSearchService.java b/GapsWeb/src/main/java/com/jasonhhouse/gaps/service/GapsSearchService.java index 7c5ca82..c552f4f 100644 --- a/GapsWeb/src/main/java/com/jasonhhouse/gaps/service/GapsSearchService.java +++ b/GapsWeb/src/main/java/com/jasonhhouse/gaps/service/GapsSearchService.java @@ -15,14 +15,14 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeType; -import com.jasonhhouse.gaps.Gaps; import com.jasonhhouse.gaps.GapsSearch; +import com.jasonhhouse.gaps.GapsService; import com.jasonhhouse.gaps.Movie; +import com.jasonhhouse.gaps.PlexLibrary; import com.jasonhhouse.gaps.SearchCancelledException; import com.jasonhhouse.gaps.SearchResults; import com.jasonhhouse.gaps.UrlGenerator; import java.io.ByteArrayInputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -31,6 +31,7 @@ import java.time.LocalDate; import java.time.Year; import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; @@ -40,6 +41,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -53,7 +55,6 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.StopWatch; import org.jetbrains.annotations.NotNull; @@ -108,9 +109,12 @@ public class GapsSearchService implements GapsSearch { private final IoService ioService; + private final GapsService gapsService; + @Autowired - public GapsSearchService(@Qualifier("real") UrlGenerator urlGenerator, SimpMessagingTemplate template, IoService ioService) { + public GapsSearchService(@Qualifier("real") UrlGenerator urlGenerator, SimpMessagingTemplate template, IoService ioService, GapsService gapsService) { this.template = template; + this.gapsService = gapsService; this.ownedMovies = new HashSet<>(); this.searched = new HashSet<>(); this.recommended = new HashSet<>(); @@ -126,8 +130,8 @@ public class GapsSearchService implements GapsSearch { @Override @Async - public void run(@NotNull Gaps gaps) { - LOGGER.info("run( " + gaps + " )"); + public void run() { + LOGGER.info("run( )"); searched.clear(); ownedMovies.clear(); @@ -138,43 +142,27 @@ public class GapsSearchService implements GapsSearch { searchedMovieCount.set(0); cancelSearch.set(false); - if (isGapsPropertyValid(gaps)) { - String reason = "No search property defined. Must search from at least one type: Folder or Plex"; - cancelSearch.set(true); - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, reason); - } - - defaultValues(gaps); - try { - String sessionId = null; - // Get TMDB Authorization from user, - // requires user input so needs to be done early before user walks away - if (StringUtils.isNotEmpty(gaps.getMovieDbListId())) { - sessionId = getTmdbAuthorization(gaps); - } - - if (BooleanUtils.isTrue(gaps.getSearchFromPlex())) { - findAllPlexMovies(gaps); - } else { - LOGGER.info("Not searching from Plex"); - } - //ToDo - /*if (properties.getFolder().getSearchFromFolder()) { - findAllFolderMovies(); - }*/ + String sessionId = null; +// // Get TMDB Authorization from user, +// // requires user input so needs to be done early before user walks away + //if (StringUtils.isNotEmpty(gaps.getMovieDbListId())) { + // sessionId = getTmdbAuthorization(gaps); + //} + + findAllPlexMovies(); StopWatch watch = new StopWatch(); watch.start(); - searchForMovies(gaps); + searchForMovies(); watch.stop(); System.out.println("Time Elapsed: " + TimeUnit.MILLISECONDS.toSeconds(watch.getTime()) + " seconds."); System.out.println("Times used TVDB ID: " + tempTvdbCounter); - if (StringUtils.isNotEmpty(gaps.getMovieDbListId())) { - createTmdbList(gaps, sessionId); - } + /*if (StringUtils.isNotEmpty(gaps.getMovieDbListId())) { + createTmdbList(sessionId); + }*/ } catch (SearchCancelledException e) { String reason = "Search cancelled"; @@ -185,9 +173,7 @@ public class GapsSearchService implements GapsSearch { cancelSearch.set(true); } - if (gaps.getWriteToFile()) { - ioService.writeToFile(recommended); - } + ioService.writeToFile(recommended); //Always write to log ioService.writeRecommendedToFile(recommended); @@ -196,28 +182,6 @@ public class GapsSearchService implements GapsSearch { template.convertAndSend("/finishedSearching", true); } - private boolean isGapsPropertyValid(Gaps gaps) { - return BooleanUtils.isNotTrue(gaps.getSearchFromPlex()) && BooleanUtils.isNotTrue(gaps.getSearchFromFolder()); - } - - private void defaultValues(Gaps gaps) { - if (gaps.getConnectTimeout() == null) { - gaps.setConnectTimeout(180); - } - - if (gaps.getReadTimeout() == null) { - gaps.setReadTimeout(180); - } - - if (gaps.getWriteTimeout() == null) { - gaps.setWriteTimeout(180); - } - - if (gaps.getWriteToFile() == null) { - gaps.setWriteToFile(true); - } - } - @NotNull @Override public Integer getTotalMovieCount() { @@ -251,78 +215,10 @@ public class GapsSearchService implements GapsSearch { return !cancelSearch.get(); } - private void findAllFolderMovies() { - //ToDo - /*if (CollectionUtils.isEmpty(properties.getFolder().getFolders())) { - LOGGER.error("folders property cannot be empty when searchFromFolder is true"); - return; - } - - if (CollectionUtils.isEmpty(properties.getFolder().getMovieFormats())) { - LOGGER.error("movie formats property cannot be empty when searchFromFolder is true"); - return; - } - - for (String strFolder : properties.getFolder().getFolders()) { - File folder = new File(strFolder); - searchFolders(folder); - }*/ - - } - - private void searchFolders(File folder) { - //ToDo - /*if (!folder.exists()) { - LOGGER.warn("Folder in folders property does not exist: " + folder); - return; - } - - if (!folder.isDirectory()) { - LOGGER.warn("Folder in folders property is not a directory: " + folder); - return; - } - - File[] files = folder.listFiles(); - if (files == null) { - LOGGER.warn("Folder in folders property is empty: " + folder); - return; - } - - for (File file : files) { - if (file.isDirectory() && properties.getFolder().getRecursive()) { - searchFolders(file); - continue; - } - - String extension = FilenameUtils.getExtension(file.toString()); - - if (properties.getFolder().getMovieFormats().contains(extension)) { - String fullMovie = FilenameUtils.getBaseName(file.toString()); - Pattern pattern = Pattern.compile(properties.getFolder().getYearRegex()); - Matcher matcher = pattern.matcher(fullMovie); - - if (!matcher.find()) { - LOGGER.warn("No regex matches found for " + fullMovie); - continue; - } - - String year = matcher.group(matcher.groupCount()).replaceAll("[)(]", ""); - String title = fullMovie.substring(0, fullMovie.indexOf(" (")); - - Movie movie = new Movie(-1, title, Integer.parseInt(year), ""); - ownedMovies.add(movie); - } else { - LOGGER.warn("Skipping file " + file); - } - - - }*/ - } - /** * Using TMDB api (V3), get access to user list and add recommended movies to */ - private @Nullable String getTmdbAuthorization(@NotNull Gaps gaps) { + private @Nullable String getTmdbAuthorization() { // Create the request_token request OkHttpClient client = new OkHttpClient(); @@ -333,7 +229,7 @@ public class GapsSearchService implements GapsSearch { .addPathSegment("authentication") .addPathSegment("token") .addPathSegment("new") - .addQueryParameter("api_key", gaps.getMovieDbApiKey()) + .addQueryParameter("api_key", gapsService.getPlexSearch().getMovieDbApiKey()) .build(); MediaType mediaType = MediaType.parse("application/octet-stream"); @@ -370,7 +266,7 @@ public class GapsSearchService implements GapsSearch { .addPathSegment("authentication") .addPathSegment("session") .addPathSegment("new") - .addQueryParameter("api_key", gaps.getMovieDbApiKey()) + .addQueryParameter("api_key", gapsService.getPlexSearch().getMovieDbApiKey()) .build(); // Create the sesssion ID for MovieDB using the approved token @@ -395,7 +291,8 @@ public class GapsSearchService implements GapsSearch { /** * Using TMDB api (V3), get access to user list and add recommended movies to */ - private void createTmdbList(@NotNull Gaps gaps, @Nullable String sessionId) { + //ToDo + /* private void createTmdbList(@Nullable String sessionId) { OkHttpClient client; MediaType mediaType = MediaType.parse("application/json"); RequestBody body; @@ -436,20 +333,22 @@ public class GapsSearchService implements GapsSearch { } } LOGGER.info(counter + " Movies added to list. \nList located at: https://www.themoviedb.org/list/" + gaps.getMovieDbListId()); - } + }*/ /** * Connect to plex via the URL and parse all of the movies from the returned XML creating a HashSet of movies the * user has. */ - private void findAllPlexMovies(@NotNull Gaps gaps) throws SearchCancelledException { - LOGGER.info("findAllPlexMovies( " + gaps + " )"); + private void findAllPlexMovies() throws SearchCancelledException { + LOGGER.info("findAllPlexMovies( )"); OkHttpClient client = new OkHttpClient.Builder() - .connectTimeout(gaps.getConnectTimeout(), TimeUnit.SECONDS) - .writeTimeout(gaps.getWriteTimeout(), TimeUnit.SECONDS) - .readTimeout(gaps.getReadTimeout(), TimeUnit.SECONDS) + .connectTimeout(180, TimeUnit.SECONDS) + .writeTimeout(180, TimeUnit.SECONDS) + .readTimeout(180, TimeUnit.SECONDS) .build(); - List urls = gaps.getMovieUrls(); + + + List urls = generatePlexUrls(); if (CollectionUtils.isEmpty(urls)) { LOGGER.info("No URLs added to plexMovieUrls. Check your application.yaml file if needed."); @@ -567,11 +466,11 @@ public class GapsSearchService implements GapsSearch { * optimize some network calls, we add movies found in a collection and in plex to our already searched list, so we * don't re-query collections again and again. */ - private void searchForMovies(@NotNull Gaps gaps) throws SearchCancelledException { + private void searchForMovies() throws SearchCancelledException { LOGGER.info("Searching for Movie Collections..."); OkHttpClient client = new OkHttpClient(); - if (StringUtils.isEmpty(gaps.getMovieDbApiKey())) { + if (StringUtils.isEmpty(gapsService.getPlexSearch().getMovieDbApiKey())) { LOGGER.error("No MovieDb Key added to movieDbApiKey. Need to submit movieDbApiKey on each request."); return; } @@ -601,19 +500,19 @@ public class GapsSearchService implements GapsSearch { if (movie.getTvdbId() != -1 && movie.getCollectionId() != -1) { LOGGER.debug("Used Collection ID to get " + movie.getName()); tempTvdbCounter.incrementAndGet(); - handleCollection(gaps, movie, client); + handleCollection(movie, client); continue; } else if (movie.getTvdbId() != -1) { LOGGER.debug("Used TVDB ID to get " + movie.getName()); tempTvdbCounter.incrementAndGet(); - searchMovieDetails(gaps, movie, client); + searchMovieDetails(movie, client); continue; } else if (StringUtils.isNotBlank(movie.getImdbId())) { LOGGER.debug("Used 'find' to search for " + movie.getName()); - searchMovieUrl = urlGenerator.generateFindMovieUrl(gaps.getMovieDbApiKey(), URLEncoder.encode(movie.getImdbId(), "UTF-8")); + searchMovieUrl = urlGenerator.generateFindMovieUrl(gapsService.getPlexSearch().getMovieDbApiKey(), URLEncoder.encode(movie.getImdbId(), "UTF-8")); } else { LOGGER.debug("Used 'search' to search for " + movie.getName()); - searchMovieUrl = urlGenerator.generateSearchMovieUrl(gaps.getMovieDbApiKey(), URLEncoder.encode(movie.getName(), "UTF-8"), String.valueOf(movie.getYear())); + searchMovieUrl = urlGenerator.generateSearchMovieUrl(gapsService.getPlexSearch().getMovieDbApiKey(), URLEncoder.encode(movie.getName(), "UTF-8"), String.valueOf(movie.getYear())); } Request request = new Request.Builder() @@ -670,7 +569,7 @@ public class GapsSearchService implements GapsSearch { everyMovie.add(newMovie); } - searchMovieDetails(gaps, movie, client); + searchMovieDetails(movie, client); } catch (JsonProcessingException e) { LOGGER.error("Error parsing movie " + movie + ". " + e.getMessage()); LOGGER.error("URL: " + searchMovieUrl); @@ -703,8 +602,8 @@ public class GapsSearchService implements GapsSearch { } } - private void searchMovieDetails(Gaps gaps, Movie movie, OkHttpClient client) { - HttpUrl movieDetailUrl = urlGenerator.generateMovieDetailUrl(gaps.getMovieDbApiKey(), String.valueOf(movie.getImdbId())); + private void searchMovieDetails(Movie movie, OkHttpClient client) { + HttpUrl movieDetailUrl = urlGenerator.generateMovieDetailUrl(gapsService.getPlexSearch().getMovieDbApiKey(), String.valueOf(movie.getImdbId())); Request request = new Request.Builder() .url(movieDetailUrl) @@ -748,15 +647,15 @@ public class GapsSearchService implements GapsSearch { everyMovie.add(newMovie); } - handleCollection(gaps, movie, client); + handleCollection(movie, client); } catch (IOException e) { LOGGER.error("Error getting movie details " + movie, e); } } - private void handleCollection(Gaps gaps, Movie movie, OkHttpClient client) { - HttpUrl collectionUrl = urlGenerator.generateCollectionUrl(gaps.getMovieDbApiKey(), String.valueOf(movie.getCollectionId())); + private void handleCollection(Movie movie, OkHttpClient client) { + HttpUrl collectionUrl = urlGenerator.generateCollectionUrl(gapsService.getPlexSearch().getMovieDbApiKey(), String.valueOf(movie.getCollectionId())); Request request = new Request.Builder() .url(collectionUrl) @@ -839,7 +738,7 @@ public class GapsSearchService implements GapsSearch { sendEmptySearchUpdate(); } else if (!searched.contains(movieFromCollection) && year != 0 && year < Year.now().getValue()) { // Get recommended Movie details from MovieDB API - HttpUrl movieDetailUrl = urlGenerator.generateMovieDetailUrl(gaps.getMovieDbApiKey(), String.valueOf(movieFromCollection.getTvdbId())); + HttpUrl movieDetailUrl = urlGenerator.generateMovieDetailUrl(gapsService.getPlexSearch().getMovieDbApiKey(), String.valueOf(movieFromCollection.getTvdbId())); Request newReq = new Request.Builder() .url(movieDetailUrl) @@ -939,4 +838,16 @@ public class GapsSearchService implements GapsSearch { } } + + private List generatePlexUrls() { + LOGGER.info(gapsService.getPlexSearch().getLibraries().toString()); + List urls = gapsService.getPlexSearch() + .getLibraries() + .stream() + .filter(PlexLibrary::getSelected) + .map(plexLibrary -> "http://" + gapsService.getPlexSearch().getAddress() + ":" + gapsService.getPlexSearch().getPort() + "/library/sections/" + plexLibrary.getKey() + "/all/?X-Plex-Token=" + gapsService.getPlexSearch().getPlexToken()) + .collect(Collectors.toList()); + LOGGER.info("URLS: " + urls.size()); + return urls; + } } diff --git a/GapsWeb/src/main/java/com/jasonhhouse/gaps/service/GapsServiceImpl.java b/GapsWeb/src/main/java/com/jasonhhouse/gaps/service/GapsServiceImpl.java index a945d3b..81e1531 100644 --- a/GapsWeb/src/main/java/com/jasonhhouse/gaps/service/GapsServiceImpl.java +++ b/GapsWeb/src/main/java/com/jasonhhouse/gaps/service/GapsServiceImpl.java @@ -13,8 +13,6 @@ package com.jasonhhouse.gaps.service; import com.jasonhhouse.gaps.GapsService; import com.jasonhhouse.gaps.PlexLibrary; import com.jasonhhouse.gaps.PlexSearch; -import com.jasonhhouse.gaps.controller.PlexMovieListController; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -43,7 +41,18 @@ public class GapsServiceImpl implements GapsService { @Override public void updateLibrarySelections(@NotNull List plexLibraries) { LOGGER.info("updateLibrarySelections( " + plexLibraries + " )"); - getPlexSearch().getLibraries().addAll(plexLibraries.stream().filter(PlexLibrary::getSelected).collect(Collectors.toList())); + LOGGER.info("BEFORE:" + getPlexSearch().getLibraries().toString()); + for (PlexLibrary plexLibrary : plexLibraries) { + int index = getPlexSearch().getLibraries().indexOf(plexLibrary); + LOGGER.info("Index of plexLibrary: " + index + " - " + plexLibrary); + if (index == -1) { + getPlexSearch().getLibraries().add(plexLibrary); + } else { + getPlexSearch().getLibraries().get(index).setSelected(plexLibrary.getSelected()); + } + + } + LOGGER.info("AFTER:" + getPlexSearch().getLibraries().toString()); } @Override diff --git a/GapsWeb/src/main/java/com/jasonhhouse/gaps/validator/PlexLibrariesValidator.java b/GapsWeb/src/main/java/com/jasonhhouse/gaps/validator/PlexLibrariesValidator.java index 4f8d654..8c3f617 100644 --- a/GapsWeb/src/main/java/com/jasonhhouse/gaps/validator/PlexLibrariesValidator.java +++ b/GapsWeb/src/main/java/com/jasonhhouse/gaps/validator/PlexLibrariesValidator.java @@ -51,7 +51,7 @@ public class PlexLibrariesValidator implements Validator { } if (plexLibrary.getSelected() == null) { - errors.rejectValue("libraries", "plexLibrary.selected().empty"); + plexLibrary.setSelected(false); } } diff --git a/GapsWeb/src/main/resources/application.yaml b/GapsWeb/src/main/resources/application.yaml index e0a90f3..92f7da6 100644 --- a/GapsWeb/src/main/resources/application.yaml +++ b/GapsWeb/src/main/resources/application.yaml @@ -47,7 +47,7 @@ info: app: name: Gaps description: Gaps searches through your Plex Server or local folders for all movies, then queries for known movies in the same collection. If those movies don't exist in your library, Gaps will recommend getting those movies, legally of course. - version: 0.1.0 + version: 0.1.1 --- spring: @@ -79,5 +79,5 @@ info: app: name: Gaps description: Gaps searches through your Plex Server or local folders for all movies, then queries for known movies in the same collection. If those movies don't exist in your library, Gaps will recommend getting those movies, legally of course. - version: 0.1.0 + version: 0.1.1 diff --git a/GapsWeb/src/main/resources/static/js/plexMovieList.js b/GapsWeb/src/main/resources/static/js/plexMovieList.js index bd3bc1e..ff09157 100644 --- a/GapsWeb/src/main/resources/static/js/plexMovieList.js +++ b/GapsWeb/src/main/resources/static/js/plexMovieList.js @@ -129,31 +129,9 @@ function search() { searchTitle.text("Searching for Movies"); searchDescription.text("Gaps is looking through your Plex libraries. This could take a while so just sit tight, and we'll find all the missing movies for you."); - const plexSearch = JSON.parse($('#plexSearch').val()); - - let plexMovieUrls = []; - - plexSearch.libraries.forEach(function (library) { - let data = { - 'X-Plex-Token': plexSearch.plexToken - }; - - let encoded = encodeQueryData(data); - let plexMovieUrl = `http://${plexSearch.address}:${plexSearch.port}/library/sections/${library.key}/all/?${encoded}`; - plexMovieUrls.push(plexMovieUrl); - }); - - const gaps = { - movieDbApiKey: plexSearch.movieDbApiKey, - writeToFile: true, - searchFromPlex: true, - movieUrls: plexMovieUrls - }; - $.ajax({ type: "POST", url: "startSearching", - data: JSON.stringify(gaps), contentType: "application/json" }); diff --git a/GapsWeb/src/main/resources/templates/folder.html b/GapsWeb/src/main/resources/templates/folder.html index 7d1bd48..b675784 100644 --- a/GapsWeb/src/main/resources/templates/folder.html +++ b/GapsWeb/src/main/resources/templates/folder.html @@ -155,7 +155,7 @@
-
Gaps v0.1.0
+
Gaps v0.1.1
diff --git a/GapsWeb/src/main/resources/templates/index.html b/GapsWeb/src/main/resources/templates/index.html index 5a28a8c..8cf8744 100644 --- a/GapsWeb/src/main/resources/templates/index.html +++ b/GapsWeb/src/main/resources/templates/index.html @@ -39,7 +39,7 @@

Welcome to Gaps

-

v0.1.0

+

v0.1.1

Gaps searches through your Plex Server. It then queries for known diff --git a/GapsWeb/src/test/java/com/jasonhhouse/gaps/GapsSearchServiceTest.java b/GapsWeb/src/test/java/com/jasonhhouse/gaps/GapsSearchServiceTest.java index 2551158..16b0841 100644 --- a/GapsWeb/src/test/java/com/jasonhhouse/gaps/GapsSearchServiceTest.java +++ b/GapsWeb/src/test/java/com/jasonhhouse/gaps/GapsSearchServiceTest.java @@ -29,10 +29,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest(classes = GapsApplication.class) class GapsSearchServiceTest { - private final Gaps gaps = new Gaps(); private GapsUrlGeneratorTest gapsUrlGeneratorTest; private GapsSearchService gapsSearch; + @Mock + private GapsService gapsService; + @Mock private IoService ioService; @@ -40,7 +42,7 @@ class GapsSearchServiceTest { void setup() throws Exception { gapsUrlGeneratorTest = new GapsUrlGeneratorTest(); SimpMessagingTemplate template = new SimpMessagingTemplate((message, l) -> true); - gapsSearch = new GapsSearchService(gapsUrlGeneratorTest, template, ioService); + gapsSearch = new GapsSearchService(gapsUrlGeneratorTest, template, ioService, gapsService); // Create a MockWebServer. These are lean enough that you can create a new // instance for every unit test. @@ -68,14 +70,13 @@ class GapsSearchServiceTest { @Test void emptyGapsProperty() { Assertions.assertThrows(ResponseStatusException.class, () -> { - gapsSearch.run(gaps); + gapsSearch.run(); }, "Should throw exception when not searching from folder and Plex"); } @Test void searchPlexGapsEmptyOtherwise() throws Exception { - gaps.setSearchFromPlex(true); - gapsSearch.run(gaps); + gapsSearch.run(); List recommended = gapsSearch.getRecommendedMovies(); Assertions.assertEquals(recommended.size(), 0, "Shouldn't have found any movies"); @@ -133,11 +134,7 @@ class GapsSearchServiceTest { List movieUrls = new ArrayList<>(); movieUrls.add(GapsUrlGeneratorTest.PLEX_EMPTY_URL); - gaps.setMovieUrls(movieUrls); - gaps.setSearchFromPlex(true); - gaps.setWriteToFile(false); - - Assertions.assertThrows(ResponseStatusException.class, () -> gapsSearch.run(gaps), "Should throw exception that the body was empty"); + Assertions.assertThrows(ResponseStatusException.class, () -> gapsSearch.run(), "Should throw exception that the body was empty"); } @Test @@ -147,11 +144,7 @@ class GapsSearchServiceTest { List movieUrls = new ArrayList<>(); movieUrls.add(GapsUrlGeneratorTest.NO_MOVIE_PLEX_URL); - gaps.setMovieUrls(movieUrls); - gaps.setSearchFromPlex(true); - gaps.setWriteToFile(false); - - gapsSearch.run(gaps); + gapsSearch.run(); List recommended = gapsSearch.getRecommendedMovies(); Assertions.assertEquals(recommended.size(), 0, "Shouldn't have found any movies"); @@ -164,11 +157,7 @@ class GapsSearchServiceTest { List movieUrls = new ArrayList<>(); movieUrls.add(GapsUrlGeneratorTest.EMPTY_MOVIE_PLEX_URL); - gaps.setMovieUrls(movieUrls); - gaps.setSearchFromPlex(true); - gaps.setWriteToFile(false); - - Assertions.assertThrows(ResponseStatusException.class, () -> gapsSearch.run(gaps), "Should throw exception that the title was missing from the video element"); + Assertions.assertThrows(ResponseStatusException.class, () -> gapsSearch.run(), "Should throw exception that the title was missing from the video element"); } @@ -179,11 +168,7 @@ class GapsSearchServiceTest { List movieUrls = new ArrayList<>(); movieUrls.add(GapsUrlGeneratorTest.PLEX_WITH_GUID_URL); - gaps.setMovieUrls(movieUrls); - gaps.setSearchFromPlex(true); - gaps.setWriteToFile(false); - - gapsSearch.run(gaps); + gapsSearch.run(); assertEquals(gapsSearch.getTotalMovieCount(), 1, "Should have found exactly one movie"); } @@ -193,12 +178,7 @@ class GapsSearchServiceTest { List movieUrls = new ArrayList<>(); movieUrls.add(GapsUrlGeneratorTest.PLEX_MOVIE_URL); - - gaps.setMovieUrls(movieUrls); - gaps.setSearchFromPlex(true); - gaps.setWriteToFile(false); - - gapsSearch.run(gaps); + gapsSearch.run(); assertEquals(gapsSearch.getTotalMovieCount(), 1, "Should have found exactly one movie"); } diff --git a/dockerBuild.sh b/dockerBuild.sh index f52c2c9..c245bc5 100755 --- a/dockerBuild.sh +++ b/dockerBuild.sh @@ -1,5 +1,5 @@ -mvn clean install -docker build -f Dockerfile.ssl -t housewrecker/gaps:latest . -docker push housewrecker/gaps:latest -docker build -f Dockerfile.no-ssl -t housewrecker/gaps:latest-no-ssl . -docker push housewrecker/gaps:latest-no-ssl \ No newline at end of file +mvn clean install -DskipTests +docker build -f Dockerfile.ssl -t housewrecker/gaps:v0.1.1 . +docker push housewrecker/gaps:v0.1.1 +docker build -f Dockerfile.no-ssl -t housewrecker/gaps:v0.1.1-no-ssl . +docker push housewrecker/gaps:v0.1.1-no-ssl \ No newline at end of file diff --git a/pom.xml b/pom.xml index f8db3cc..900c9b0 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ com.jasonhhouse Gaps - 0.1.0 + 0.1.1 Gaps Demo project for Spring Boot