Merge pull request #134 from JasonHHouse/feature/better_title_handling

Feature/better title handling
This commit is contained in:
Jason House
2020-07-28 12:51:37 +09:00
committed by GitHub
27 changed files with 191 additions and 67 deletions

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>Gaps</artifactId>
<groupId>com.jasonhhouse</groupId>
<version>0.4.5</version>
<version>0.4.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -15,7 +15,7 @@
<dependency>
<groupId>com.jasonhhouse</groupId>
<artifactId>Plex</artifactId>
<version>0.4.5</version>
<version>0.4.6</version>
</dependency>
<dependency>

View File

@@ -20,7 +20,7 @@ RUN mkdir -p /usr/app && chmod 777 /usr/data
WORKDIR /usr/app
COPY GapsWeb/target/GapsWeb-0.4.5.jar /usr/app/gaps.jar
COPY GapsWeb/target/GapsWeb-0.4.6.jar /usr/app/gaps.jar
COPY start.sh /usr/app/

View File

@@ -22,7 +22,7 @@ RUN mkdir -p /usr/app && chmod 777 /usr/data
WORKDIR /usr/app
COPY GapsWeb/target/GapsWeb-0.4.5.jar /usr/app/gaps.jar
COPY GapsWeb/target/GapsWeb-0.4.6.jar /usr/app/gaps.jar
COPY start.sh /usr/app/

View File

@@ -22,7 +22,7 @@ RUN mkdir -p /usr/app && chmod 777 /usr/data
WORKDIR /usr/app
COPY GapsWeb/target/GapsWeb-0.4.5.jar /usr/app/gaps.jar
COPY GapsWeb/target/GapsWeb-0.4.6.jar /usr/app/gaps.jar
COPY start.sh /usr/app/

View File

@@ -2,8 +2,8 @@
<launch4jConfig>
<dontWrapJar>false</dontWrapJar>
<headerType>console</headerType>
<jar>/Users/jhouse/Code/Gaps/GapsWeb/target/GapsWeb-0.4.5.jar</jar>
<outfile>/Users/jhouse/Desktop/Gaps-v0.4.5.exe</outfile>
<jar>/Users/jhouse/Code/Gaps/GapsWeb/target/GapsWeb-0.4.6.jar</jar>
<outfile>/Users/jhouse/Desktop/Gaps-v0.4.6.exe</outfile>
<errTitle></errTitle>
<cmdLine></cmdLine>
<chdir>.</chdir>
@@ -28,16 +28,16 @@
<runtimeBits>64/32</runtimeBits>
</jre>
<versionInfo>
<fileVersion>0.4.5.0</fileVersion>
<fileVersion>0.4.6.0</fileVersion>
<txtFileVersion>Free Form</txtFileVersion>
<fileDescription>Gaps</fileDescription>
<copyright>2019</copyright>
<productVersion>0.4.5.0</productVersion>
<productVersion>0.4.6.0</productVersion>
<txtProductVersion>Free Form</txtProductVersion>
<productName>Gaps</productName>
<companyName></companyName>
<internalName>Gaps</internalName>
<originalFilename>Gaps-0.4.5.exe</originalFilename>
<originalFilename>Gaps-0.4.6.exe</originalFilename>
<trademarks></trademarks>
<language>ENGLISH_US</language>
</versionInfo>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>Gaps</artifactId>
<groupId>com.jasonhhouse</groupId>
<version>0.4.5</version>
<version>0.4.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -19,13 +19,13 @@
<dependency>
<groupId>com.jasonhhouse</groupId>
<artifactId>Core</artifactId>
<version>0.4.5</version>
<version>0.4.6</version>
</dependency>
<dependency>
<groupId>com.jasonhhouse</groupId>
<artifactId>Plex</artifactId>
<version>0.4.5</version>
<version>0.4.6</version>
</dependency>
<dependency>

View File

@@ -26,6 +26,7 @@ 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.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -56,7 +57,7 @@ public class LibraryController {
}
}
@GetMapping
@GetMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView getLibraries() {
LOGGER.info("getLibraries()");
@@ -100,7 +101,8 @@ public class LibraryController {
return modelAndView;
}
@GetMapping(path = "{machineIdentifier}/{key}")
@GetMapping(path = "{machineIdentifier}/{key}",
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Payload> getLibraries(@PathVariable("machineIdentifier") final String machineIdentifier, @PathVariable("key") final Integer key) {
LOGGER.info("getLibraries( " + machineIdentifier + ", " + key + " )");

View File

@@ -19,6 +19,7 @@ import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@@ -42,7 +43,8 @@ public class PlexMovieListController {
this.plexQuery = plexQuery;
}
@GetMapping(value = "/movies/{machineIdentifier}/{key}")
@GetMapping(value = "/movies/{machineIdentifier}/{key}",
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<List<Movie>> getPlexMovies(@PathVariable("machineIdentifier") final String machineIdentifier, @PathVariable("key") final Integer key) {
LOGGER.info("getPlexMovies( " + machineIdentifier + ", " + key + " )");

View File

@@ -21,6 +21,7 @@ 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.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -44,7 +45,8 @@ public class RSSController {
this.gapsService = gapsService;
}
@GetMapping(path = "/rss/{machineIdentifier}/{libraryKey}")
@GetMapping(path = "/rss/{machineIdentifier}/{libraryKey}",
produces = MediaType.APPLICATION_JSON_VALUE)
public String getRss(@PathVariable("machineIdentifier") String machineIdentifier, @PathVariable("libraryKey") Integer libraryKey) {
LOGGER.info("getRss( " + machineIdentifier + ", " + libraryKey + " )");

View File

@@ -16,18 +16,21 @@ import com.jasonhhouse.gaps.Payload;
import com.jasonhhouse.gaps.PlexLibrary;
import com.jasonhhouse.gaps.PlexServer;
import com.jasonhhouse.gaps.service.IoService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
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.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
@@ -57,7 +60,7 @@ public class RecommendedController {
this.gapsSearch = gapsSearch;
}
@GetMapping
@GetMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView getRecommended() {
LOGGER.info("getRecommended()");
@@ -82,7 +85,8 @@ public class RecommendedController {
return modelAndView;
}
@GetMapping(path = "{machineIdentifier}/{key}")
@GetMapping(path = "{machineIdentifier}/{key}",
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Payload> getRecommended(@PathVariable("machineIdentifier") final String machineIdentifier, @PathVariable("key") final Integer key) {
LOGGER.info("getRecommended( " + machineIdentifier + ", " + key + " )");
@@ -107,33 +111,14 @@ public class RecommendedController {
return ResponseEntity.ok().body(payload);
}
private List<String> buildUrls(Movie[] movies) {
LOGGER.info("buildUrls( " + Arrays.toString(movies) + " ) ");
List<String> urls = new ArrayList<>();
for (Movie movie : movies) {
if (movie.getTvdbId() != -1) {
urls.add("https://www.themoviedb.org/movie/" + movie.getTvdbId());
continue;
}
if (StringUtils.isNotEmpty(movie.getImdbId())) {
urls.add("https://www.imdb.com/title/" + movie.getImdbId() + "/");
continue;
}
urls.add(null);
}
return urls;
}
/**
* Start Gaps searching for missing movies
*
* @param machineIdentifier plex server id
* @param key plex library key
*/
@PutMapping(value = "/find/{machineIdentifier}/{key}")
@PutMapping(value = "/find/{machineIdentifier}/{key}",
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(value = HttpStatus.OK)
public void putFindRecommencedMovies(@PathVariable("machineIdentifier") final String machineIdentifier, @PathVariable("key") final Integer key) {
LOGGER.info("putFindRecommencedMovies( " + machineIdentifier + ", " + key + " )");

View File

@@ -424,7 +424,7 @@ public class GapsSearchService implements GapsSearch {
if (collection.has("parts")) {
JsonNode parts = collection.get("parts");
parts.iterator().forEachRemaining(jsonNode -> {
String title = jsonNode.get("title").asText().replaceAll(":", "");
String title = jsonNode.get("title").asText().replaceAll("[<>`~\\[\\]()*&^%$#@!|{}.,?\\-_=+:;]", "");
int year = -1;
if(jsonNode.has("year")) {
year = jsonNode.get("year").asInt(-1);
@@ -465,7 +465,7 @@ public class GapsSearchService implements GapsSearch {
for (JsonNode part : parts) {
int tvdbId = part.get("id").asInt();
//Files can't have : so need to remove to find matches correctly
String title = part.get("title").asText().replaceAll(":", "");
String title = part.get("title").asText().replaceAll("[<>`~\\[\\]()*&^%$#@!|{}.,?\\-_=+:;]", "");
int year;
try {
if (part.has("release_date") && StringUtils.isNotEmpty(part.get("release_date").asText())) {

View File

@@ -38,4 +38,4 @@ 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.4.5
version: 0.4.6

View File

@@ -78,7 +78,7 @@
<img src="/images/final-2.svg" alt="Gaps Logo" style="width:50%;height:50%;" class="center">
<h3 class="top-margin">About</h3>
<h4 class="top-margin text-primary">v0.4.5</h4>
<h4 class="top-margin text-primary">v0.4.6</h4>
<p class="text-muted">Gaps searches through your Plex Server. It then queries
for known

View File

@@ -155,7 +155,7 @@
<div class="container">
<div class="row">
<div class="col l6 s12">
<h5 class="white-text">Gaps v0.4.5/h5>
<h5 class="white-text">Gaps v0.4.6/h5>
</div>
</div>
</div>

View File

@@ -77,7 +77,7 @@
<div class="container bottom-margin">
<img src="/images/final-2.svg" alt="Gaps Logo" style="width:50%;height:50%;" class="center">
<h3 class="top-margin">v0.4.5</h3>
<h3 class="top-margin">v0.4.6</h3>
<p class="text-muted">Gaps searches through your Plex Server. It then queries
for known

View File

@@ -78,6 +78,11 @@
<img src="/images/final-2.svg" alt="Gaps Logo" style="width:50%;height:50%;" class="center">
<h3 class="top-margin">Updates</h3>
<h4 class="top-margin text-primary">v0.4.6</h4>
<ul class="text-muted">
<li>Safer checking of titles as strings</li>
</ul>
<h4 class="top-margin text-primary">v0.4.5</h4>
<ul class="text-muted">
<li>Fixed bug that some movies wouldn't match correctly in their collection</li>

View File

@@ -13,5 +13,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.4.5
version: 0.4.6
loginEnabled: false

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>Gaps</artifactId>
<groupId>com.jasonhhouse</groupId>
<version>0.4.5</version>
<version>0.4.6</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -1,5 +1,5 @@
#!/bin/bash
VERSION=0.4.5
VERSION=0.4.6
DOCKER_LATEST="housewrecker/gaps:latest"
JAR_VERSION="GapsWeb/target/GapsWeb-$VERSION.jar"
ZIP_VERSION="Gaps-$VERSION.zip"

View File

@@ -1,5 +1,5 @@
#!/bin/bash
VERSION="0.4.5"
VERSION="0.4.6"
DOCKER_LATEST="housewrecker/gaps:v$VERSION"
JAR_VERSION="GapsWeb/target/GapsWeb-$VERSION.jar"
ZIP_VERSION="Gaps-$VERSION.zip"

View File

@@ -9,7 +9,7 @@ describe('Verify About Page', function () {
.should('have.text', 'About');
cy.get('.container > :nth-child(3)')
.should('have.text', 'v0.4.5');
.should('have.text', 'v0.4.6');
cy.get('.container > :nth-child(6)')
.should('have.text', 'Software');

View File

@@ -0,0 +1,59 @@
import {nuke, redLibraryBefore, searchPlexForMovies, spyOnAddEventListener} from "../common";
describe('Library API', function () {
it('Get bad library', () => {
cy.request('/libraries/abc/123')
.then((resp) => {
cy.log(resp.body);
const result = resp.body;
expect(result.code).to.eq(41);
});
})
before(nuke);
before(redLibraryBefore);
it('Get library Red - Saw', () => {
searchSawLibrary(cy);
cy.request('/libraries/721fee4db63634b88ed699f8b0a16d7682a7a0d9/2')
.then((resp) => {
cy.log(resp.body);
const result = resp.body;
expect(result.code).to.eq(40);
});
})
});
describe('Plex Movie List API', function () {
beforeEach(nuke)
beforeEach(redLibraryBefore);
it('Get library Red - Saw', () => {
cy.request('/plex/movies/721fee4db63634b88ed699f8b0a16d7682a7a0d9/2')
.then((resp) => {
cy.log(resp.body);
const result = resp.body;
expect(result).to.have.lengthOf(1);
expect(result[0].imdbId).to.eq("tt0387564");
});
})
it('Get library Red - Saw', () => {
cy.request('/libraries/ABC/123')
.then((resp) => {
cy.log(resp.body);
const result = resp.body;
//expect(result).to.have.lengthOf(0);
});
})
});
function searchSawLibrary(cy) {
cy.visit('/libraries', {onBeforeLoad: spyOnAddEventListener});
searchPlexForMovies(cy);
cy.visit('/recommended', {onBeforeLoad: spyOnAddEventListener});
}

View File

@@ -0,0 +1,36 @@
import {nuke, redLibraryBefore, searchPlexForMovies, spyOnAddEventListener} from "../common";
describe('Recommended API', function () {
it('Get Bad recommended', () => {
cy.request('/recommended/a/2')
.then((resp) => {
cy.log(resp.body);
const result = resp.body;
expect(result.code).to.eq(41);
});
})
before(nuke);
before(redLibraryBefore);
it('Get library Red - Saw', () => {
searchSawLibrary(cy);
cy.request('/libraries/721fee4db63634b88ed699f8b0a16d7682a7a0d9/2')
.then((resp) => {
cy.log(resp.body);
const result = resp.body;
expect(result.code).to.eq(40);
});
})
});
function searchSawLibrary(cy) {
cy.visit('/libraries', {onBeforeLoad: spyOnAddEventListener});
searchPlexForMovies(cy);
cy.visit('/recommended', {onBeforeLoad: spyOnAddEventListener});
}

View File

@@ -0,0 +1,41 @@
import {nuke, redLibraryBefore, searchPlexForMovies, spyOnAddEventListener} from "../common";
describe('Searched RSS', function () {
before(nuke)
before(redLibraryBefore);
it('Get full RSS for Red', () => {
searchSawLibrary(cy);
cy.get('#dropdownMenuLink')
.click();
cy.get('[data-key="2"]')
.click();
cy.get('.card-body > .btn')
.click();
cy.wait(5000);
cy.get('#movies_info')
.should('have.text', 'Showing 1 to 7 of 7 entries');
cy.visit('/rssCheck', {onBeforeLoad: spyOnAddEventListener});
cy.request('/rss/721fee4db63634b88ed699f8b0a16d7682a7a0d9/2')
.then((resp) => {
const result = resp.body;
expect(result).to.have.lengthOf(7);
expect(result[0].imdb_id).to.eq('tt3348730')
});
})
});
function searchSawLibrary(cy) {
cy.visit('/libraries', {onBeforeLoad: spyOnAddEventListener});
searchPlexForMovies(cy);
cy.visit('/recommended', {onBeforeLoad: spyOnAddEventListener});
}

18
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "gaps",
"version": "0.4.5",
"version": "0.4.6",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -826,9 +826,9 @@
}
},
"cypress": {
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-4.10.0.tgz",
"integrity": "sha512-eFv1WPp4zFrAgZ6mwherBGVsTpHvay/hEF5F7U7yfAkTxsUQn/ZG/LdX67fIi3bKDTQXYzFv/CvywlQSeug8Bg==",
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-4.11.0.tgz",
"integrity": "sha512-6Yd598+KPATM+dU1Ig0g2hbA+R/o1MAKt0xIejw4nZBVLSplCouBzqeKve6XsxGU6n4HMSt/+QYsWfFcoQeSEw==",
"dev": true,
"requires": {
"@cypress/listr-verbose-renderer": "0.4.1",
@@ -855,7 +855,7 @@
"is-installed-globally": "0.3.2",
"lazy-ass": "1.6.0",
"listr": "0.14.3",
"lodash": "4.17.15",
"lodash": "4.17.19",
"log-symbols": "3.0.0",
"minimist": "1.2.5",
"moment": "2.26.0",
@@ -868,14 +868,6 @@
"untildify": "4.0.0",
"url": "0.11.0",
"yauzl": "2.10.0"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
}
}
},
"dashdash": {

View File

@@ -1,6 +1,6 @@
{
"name": "gaps",
"version": "0.4.5",
"version": "0.4.6",
"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.",
"main": "/",
"dependencies": {
@@ -10,7 +10,7 @@
"uglify-js": "^3.10.0"
},
"devDependencies": {
"cypress": "^4.10.0"
"cypress": "^4.11.0"
},
"scripts": {
"e2e": "cypress open",

View File

@@ -16,7 +16,7 @@
</parent>
<groupId>com.jasonhhouse</groupId>
<artifactId>Gaps</artifactId>
<version>0.4.5</version>
<version>0.4.6</version>
<name>Gaps</name>
<description>Demo project for Spring Boot</description>