From 8aeef90590095a455e2323d70ba8ccae032f4276 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Thu, 7 Mar 2024 20:53:31 +0100 Subject: [PATCH] =?utf8?q?=E2=9C=A8=20Add=20movie=20descriptions=20to=20ne?= =?utf8?q?w=20movies=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../rhynodge/filters/webpages/savoy/Movie.java | 20 +++++++-- .../filters/webpages/savoy/MovieExtractor.kt | 2 +- .../rhynodge/filters/webpages/savoy/MovieState.kt | 10 +++-- .../filters/webpages/savoy/MovieExtractorTest.java | 15 ++++++- .../filters/webpages/savoy/MovieStateTest.kt | 47 +++++++++++++--------- 5 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/Movie.java b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/Movie.java index 5e831d8..8d9f1f6 100644 --- a/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/Movie.java +++ b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/savoy/Movie.java @@ -23,15 +23,23 @@ public class Movie { private final String imageUrl; @JsonProperty + private final String description; + + @JsonProperty private final List performances = new ArrayList<>(); public Movie() { - this("", ""); + this("", "", ""); } public Movie(String name, String imageUrl) { + this(name, imageUrl, ""); + } + + public Movie(String name, String imageUrl, String description) { this.name = name; this.imageUrl = imageUrl; + this.description = description; } public String getName() { @@ -42,6 +50,10 @@ public class Movie { return imageUrl; } + public String getDescription() { + return description; + } + public List getPerformances() { return performances; } @@ -52,12 +64,12 @@ public class Movie { @Override public String toString() { - return format("%s (%s, %s)", name, imageUrl, performances.stream().map(link -> String.format("%s: %s", link.getTime(), link.getLink())).collect(Collectors.joining(", "))); + return format("%s (%s, %s, %s)", name, imageUrl, description, performances.stream().map(link -> String.format("%s: %s", link.getTime(), link.getLink())).collect(Collectors.joining(", "))); } @Override public int hashCode() { - return Objects.hash(name, imageUrl, performances); + return Objects.hash(name, imageUrl, description, performances); } @Override @@ -65,7 +77,7 @@ public class Movie { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Movie movie = (Movie) o; - return Objects.equals(name, movie.name) && Objects.equals(imageUrl, movie.imageUrl) && Objects.equals(performances, movie.performances); + return Objects.equals(name, movie.name) && Objects.equals(imageUrl, movie.imageUrl) && Objects.equals(description, movie.description) && Objects.equals(performances, movie.performances); } } diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractor.kt b/src/main/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractor.kt index a87d639..39c3ab8 100644 --- a/src/main/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractor.kt +++ b/src/main/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractor.kt @@ -25,7 +25,7 @@ class MovieExtractor { .replace("&l;", "<") .replace("&g;", ">") - private fun JsonNode.extractMovie() = Movie(get("name").asText(), get("poster").get("original").asText().fixImageUrl()).apply { + private fun JsonNode.extractMovie() = Movie(get("name").asText(), get("poster").get("original").asText().fixImageUrl(), get("description_long").asText()).apply { this@extractMovie.get("performances") .map { performance -> val begin = LocalDateTime.parse(performance.get("begin").asText(), dateFormat) diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieState.kt b/src/main/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieState.kt index 0d01b20..fa8a9c0 100644 --- a/src/main/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieState.kt +++ b/src/main/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieState.kt @@ -37,10 +37,11 @@ class MovieState(@JsonProperty val movies: Collection, val newMovies: Col +"html { font-family: 'Recursive Sans Linear Static', Roboto, serif; }" +"section.new-movies > .label { font-family: Impact, sans-serif; background-color: black; padding: 0.5ex; font-size: 200%; color: #ffffee; font-weight: bold; }" +"section.new-movies ul { padding: 0; margin: 0; }" - +"section.new-movies li.movie { list-style: none; width: 250px; height: 353px; display: inline-block; position: relative; margin: 1ex 1ex 1ex 0ex; }" - +"section.new-movies li.movie img { width: 100%; height: 100%; display: block; position: absolute; z-index: -1; }" - +"section.new-movies li.movie .text { color: white; text-shadow: 2px 2px black; font-weight: bold; font-size: 150%; display: flex; flex-direction: column; justify-content: end; width: 100%; height: 100%; }" + +"section.new-movies li.movie { list-style: none; display: grid; margin: 1ex 1ex 1ex 0ex; grid-template-rows: 353px; grid-template-columns: 250px auto; }" + +"section.new-movies li.movie img { grid-area: 1/1/2/2 }" + +"section.new-movies li.movie .text { color: white; text-shadow: 2px 2px black; font-weight: bold; font-size: 150%; display: flex; flex-direction: column; justify-content: end; grid-area: 1/1/2/2; }" +"section.new-movies li.movie .text .name { padding: 1ex; font-size: 120%; }" + +"section.new-movies li.movie .description { padding: 1ex; }" +"section.daily-programmes ol { padding: 0; }" +"section.daily-programmes li { list-style: none; }" @@ -71,6 +72,9 @@ class MovieState(@JsonProperty val movies: Collection, val newMovies: Col +(movie.name) } } + div("description") { + +movie.description + } } } } diff --git a/src/test/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractorTest.java b/src/test/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractorTest.java index 63c642a..2b5988e 100644 --- a/src/test/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractorTest.java +++ b/src/test/java/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieExtractorTest.java @@ -19,7 +19,7 @@ import java.util.Optional; import static java.time.LocalDateTime.of; import static java.util.Optional.empty; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.*; import static org.jsoup.Jsoup.parse; /** @@ -47,6 +47,7 @@ public class MovieExtractorTest { public void moviesAreLocated() throws IOException { assertThat(movies, containsInAnyOrder( movie("All of Us Strangers", "https://cdn.premiumkino.de/movie/2809/db0e5c3ed02ba7fe4afa3b12aabb611f.jpg", + allOf(startsWith("Sich neu verlieben, durch eine Zeitschleife"), endsWith("Quelle: disney-content.de")), performance(of(2024, 2, 9, 16, 15), "2D OV", "https://savoy.premiumkino.de/vorstellung/all-of-us-strangers/20240209/1615/HkKdhlHMvtfSMy1fqYYtYuVdgGIKtnT7i7ddY5jzRfY~"), performance(of(2024, 2, 10, 22, 15), "2D OV", "https://savoy.premiumkino.de/vorstellung/all-of-us-strangers/20240210/2215/znWqm8FQUNSbrODY_A0jw8Au2nW6uSqbFE7Co8UgQv0~"), performance(of(2024, 2, 11, 20, 15), "2D OV", "https://savoy.premiumkino.de/vorstellung/all-of-us-strangers/20240211/2015/I642oTHBKpy7sz2RULHIQK6cykSCPi57_c0TApiKbUk~"), @@ -55,6 +56,7 @@ public class MovieExtractorTest { performance(of(2024, 2, 14, 14, 30), "2D OV", "https://savoy.premiumkino.de/vorstellung/all-of-us-strangers/20240214/1430/VZhgxh4PZutWWlLPEAe9dfOUJkB3sLnXzWoduICJYTk~") ), movie("Dune", "https://cdn.premiumkino.de/movie/3261/bcc70cb1cc4559731b6fd547d0f5cee1.jpg", + allOf(startsWith(""Dune" erzählt die packende Geschichte"), endsWith("Quelle: mediapass.warnerbros.com")), performance(of(2024, 2, 9, 19, 0), "2D OV", "https://savoy.premiumkino.de/vorstellung/dune/20240209/1900/o9jDuan4yyxaW7-Jg3hCJpiAM4CLZei8J2IX-O5-hA0~"), performance(of(2024, 2, 10, 15, 30), "2D OV", "https://savoy.premiumkino.de/vorstellung/dune/20240210/1530/jXbZnYD8R5djVnj3Ojjcsc9qdSJ0JBMVhn7PeP88HyY~"), performance(of(2024, 2, 11, 13, 30), "2D OV", "https://savoy.premiumkino.de/vorstellung/dune/20240211/1330/aJmlM8wOaGl_jtuWDvWG9TF7RR1zRpNrSZeArCBhn90~"), @@ -62,6 +64,7 @@ public class MovieExtractorTest { performance(of(2024, 2, 13, 17, 0), "2D OV", "https://savoy.premiumkino.de/vorstellung/dune/20240213/1700/QCphOtH-WrZ2tRbENwaxXPskrN2gH3I8dHR0Y5L3l0Y~") ), movie("SAVOY Sneak-Preview", "https://cdn.premiumkino.de/movie/5617/33dc4c74b4cca5cf4585b4cadfc38ec4.png", + allOf(startsWith("Wir zeigen unsere OV-Sneak freitagabends"), endsWith("Logenpreis 1,- Euro Ermäßigung. ")), performance(of(2024, 2, 9, 22, 30), "2D OV", "https://savoy.premiumkino.de/vorstellung/sneak-preview/20240209/2230/GtYBcOR_Jy7a8xDxwwPHI0wfY_v_Ep2P6rV0w4wJ7SM~"), performance(of(2024, 2, 16, 22, 0), "2D OV", "https://savoy.premiumkino.de/vorstellung/sneak-preview/20240216/2200/ZRC7iir9Hu8nIpH1PsiA_UDvckcj7yGqgMEYXHAs9Qw~") ), @@ -150,6 +153,11 @@ public class MovieExtractorTest { @SafeVarargs private Matcher movie(String name, String imageUrl, Triple... presentationTimesTypesAndLinks) { + return movie(name, imageUrl, anything(), presentationTimesTypesAndLinks); + } + + @SafeVarargs + private Matcher movie(String name, String imageUrl, Matcher descriptionMatcher, Triple... presentationTimesTypesAndLinks) { return new TypeSafeDiagnosingMatcher() { @Override protected boolean matchesSafely(Movie movie, Description mismatchDescription) { @@ -161,6 +169,10 @@ public class MovieExtractorTest { mismatchDescription.appendText("image URL is ").appendValue(movie.getImageUrl()); return false; } + if (!descriptionMatcher.matches(movie.getDescription())) { + descriptionMatcher.describeMismatch(movie.getDescription(), mismatchDescription); + return false; + } List performances = new ArrayList<>(movie.getPerformances()); if (performances.size() != presentationTimesTypesAndLinks.length) { mismatchDescription.appendText("has ").appendValue(performances.size()).appendText(" presentations"); @@ -190,6 +202,7 @@ public class MovieExtractorTest { @Override public void describeTo(Description description) { description.appendText("movie with name ").appendValue(name); + description.appendText(", description ").appendDescriptionOf(descriptionMatcher); description.appendText(" and ").appendValue(presentationTimesTypesAndLinks.length).appendText(" presentations"); } }; diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieStateTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieStateTest.kt index 857bd03..77ff2d3 100644 --- a/src/test/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieStateTest.kt +++ b/src/test/kotlin/net/pterodactylus/rhynodge/filters/webpages/savoy/MovieStateTest.kt @@ -9,6 +9,7 @@ import org.hamcrest.Matchers.empty import org.hamcrest.Matchers.equalTo import org.hamcrest.Matchers.not import org.jsoup.Jsoup +import org.jsoup.nodes.Element import org.jsoup.nodes.TextNode import org.junit.Test import java.time.LocalDateTime @@ -19,9 +20,9 @@ class MovieStateTest { fun `summary contains date of earliest movie`() { val movieState = MovieState( setOf( - Movie("1", "").apply { addPerformance(Performance(LocalDateTime.of(2024, 2, 12, 18, 45), "", "")) }, - Movie("2", "").apply { addPerformance(Performance(LocalDateTime.of(2024, 3, 12, 15, 30), "", "")) }, - Movie("3", "").apply { addPerformance(Performance(LocalDateTime.of(2024, 2, 11, 21, 15), "", "")) } + Movie("1", "", "").apply { addPerformance(Performance(LocalDateTime.of(2024, 2, 12, 18, 45), "", "")) }, + Movie("2", "", "").apply { addPerformance(Performance(LocalDateTime.of(2024, 3, 12, 15, 30), "", "")) }, + Movie("3", "", "").apply { addPerformance(Performance(LocalDateTime.of(2024, 2, 11, 21, 15), "", "")) } ), emptySet() ) assertThat(movieState.output(Reaction("", null, null, null)).summary(), containsString("2024-02-11")) @@ -34,7 +35,7 @@ class MovieStateTest { @Test fun `movie state with a new movie is triggered`() { - assertThat(MovieState(emptySet(), setOf(Movie("1", ""))).triggered(), equalTo(true)) + assertThat(MovieState(emptySet(), setOf(Movie("1", "", ""))).triggered(), equalTo(true)) } @Test @@ -47,15 +48,23 @@ class MovieStateTest { @Test fun `html output does contain a section for new movie if there are new movies`() { - val movieState = MovieState(emptySet(), setOf(Movie("1", ""), Movie("2", ""))) + val movieState = MovieState(emptySet(), setOf(Movie("1", "", ""), Movie("2", "", ""))) val output = movieState.output(Reaction("", null, null, null)) val document = Jsoup.parse(output.text("text/html")) assertThat(document.select("section.new-movies"), not(empty())) } @Test + fun `new movies section contains description of movies`() { + val movieState = MovieState(emptySet(), setOf(Movie("1", "", "Movie 1 is cool."), Movie("2", "", "Movie 2 is bad."))) + val output = movieState.output(Reaction("", null, null, null)) + val document = Jsoup.parse(output.text("text/html")) + assertThat(document.select("section.new-movies .description").map(Element::text), contains("Movie 1 is cool.", "Movie 2 is bad.")) + } + + @Test fun `new movies section contains the titles of all new movies`() { - val movieState = MovieState(emptySet(), setOf(Movie("New Movie", ""), Movie("Even Newer Movie", ""))) + val movieState = MovieState(emptySet(), setOf(Movie("New Movie", "", ""), Movie("Even Newer Movie", "", ""))) val output = movieState.output(Reaction("", null, null, null)) val document = Jsoup.parse(output.text("text/html")) assertThat(document.select("section.new-movies li.movie .name").textNodes().map(TextNode::text), containsInAnyOrder("New Movie", "Even Newer Movie")) @@ -73,10 +82,10 @@ class MovieStateTest { fun `html output contains a section for each day with a movie`() { val movieState = MovieState( setOf( - movie("Movie 1", "", "20240212-1845", "20240213-1330", "20240214-1815"), - movie("Movie 2", "", "20240212-2030", "20240213-1745", "20240214-1430"), - movie("Movie 3", "", "20240213-2015", "20240214-1730"), - movie("Movie 4", "", "20240216-1000"), + movie("Movie 1", "", "", "20240212-1845", "20240213-1330", "20240214-1815"), + movie("Movie 2", "", "", "20240212-2030", "20240213-1745", "20240214-1430"), + movie("Movie 3", "", "", "20240213-2015", "20240214-1730"), + movie("Movie 4", "", "", "20240216-1000"), ), emptySet() ) val output = movieState.output(Reaction("", null, null, null)) @@ -89,13 +98,13 @@ class MovieStateTest { fun `html output contains the correct movies within each day`() { val movieState = MovieState( setOf( - movie("Movie 1", "https://cdn.premiumkino.de/movie/3047/81c49774d7828a898ae1d525ffd135af_w300.jpg", "20240212-1845", "20240213-1330", "20240214-1815"), - movie("Movie 2", "https://cdn.premiumkino.de/movie/1066/aba09af737677ff6a15676ae588098b1_w300.jpg", "20240212-2030", "20240213-1745", "20240214-1430"), - movie("Movie 3", "https://cdn.premiumkino.de/movie/7300/14d1b21dee51a82a7b096ca282bf01c8_w300.png", "20240213-2015", "20240214-1730"), - movie("Movie 4", "https://cdn.premiumkino.de/movie/6080/cef2b33483d2898ddb472c955c58ea20_w300.jpg", "20240216-1000"), + movie("Movie 1", "https://cdn.premiumkino.de/movie/3047/81c49774d7828a898ae1d525ffd135af_w300.jpg", "", "20240212-1845", "20240213-1330", "20240214-1815"), + movie("Movie 2", "https://cdn.premiumkino.de/movie/1066/aba09af737677ff6a15676ae588098b1_w300.jpg", "", "20240212-2030", "20240213-1745", "20240214-1430"), + movie("Movie 3", "https://cdn.premiumkino.de/movie/7300/14d1b21dee51a82a7b096ca282bf01c8_w300.png", "", "20240213-2015", "20240214-1730"), + movie("Movie 4", "https://cdn.premiumkino.de/movie/6080/cef2b33483d2898ddb472c955c58ea20_w300.jpg", "", "20240216-1000"), ), setOf( - movie("Movie 1", "https://cdn.premiumkino.de/movie/3047/81c49774d7828a898ae1d525ffd135af_w300.jpg", "20240212-1845", "20240213-1330", "20240214-1815"), - movie("Movie 2", "https://cdn.premiumkino.de/movie/1066/aba09af737677ff6a15676ae588098b1_w300.jpg", "20240212-1845", "20240213-1330", "20240214-1815") + movie("Movie 1", "https://cdn.premiumkino.de/movie/3047/81c49774d7828a898ae1d525ffd135af_w300.jpg", "", "20240212-1845", "20240213-1330", "20240214-1815"), + movie("Movie 2", "https://cdn.premiumkino.de/movie/1066/aba09af737677ff6a15676ae588098b1_w300.jpg", "", "20240212-1845", "20240213-1330", "20240214-1815") ) ) val output = movieState.output(Reaction("", null, null, null)) @@ -112,7 +121,7 @@ class MovieStateTest { fun `html output contains the correct release type for movies`() { val movieState = MovieState( setOf( - movie("Movie 1", "https://cdn.premiumkino.de/movie/3047/81c49774d7828a898ae1d525ffd135af_w300.jpg", "20240212-1845" to "2D OV", "20240213-1330" to "2D", "20240214-1815" to "2D OmeU"), + movie("Movie 1", "https://cdn.premiumkino.de/movie/3047/81c49774d7828a898ae1d525ffd135af_w300.jpg", "", "20240212-1845" to "2D OV", "20240213-1330" to "2D", "20240214-1815" to "2D OmeU"), ), setOf() ) val output = movieState.output(Reaction("", null, null, null)) @@ -136,10 +145,10 @@ private fun dateTime(dateTimeString: String) = LocalDateTime.of( dateTimeString.substring(11..12).toInt(), ) -private fun movie(name: String, imageUrl: String, vararg times: String) = Movie(name, imageUrl).apply { +private fun movie(name: String, imageUrl: String, description: String = "", vararg times: String) = Movie(name, imageUrl, description).apply { times.map(::dateTime).map { Performance(it, "", "https://link/$it") }.forEach(this::addPerformance) } -private fun movie(name: String, imageUrl: String, vararg timesAndTypes: Pair) = Movie(name, imageUrl).apply { +private fun movie(name: String, imageUrl: String, description: String = "", vararg timesAndTypes: Pair) = Movie(name, imageUrl, description).apply { timesAndTypes.map { Performance(it.first.let(::dateTime), it.second, "https://link/${it.first}") }.forEach(this::addPerformance) } -- 2.7.4