From 98a384a110804b43410d000b824597aee65b17fb Mon Sep 17 00:00:00 2001 From: TrueDevProfile Date: Tue, 8 Sep 2020 14:48:14 +0400 Subject: [PATCH 1/3] feature: add tv shows --- readme.md | 4 +- .../model/deserializer/StringToEpisodes.kt | 36 ++++++++++++++++++ .../kinoposk/api/model/tvshow/ContextData.kt | 32 ++++++++++++++++ .../kinoposk/api/model/tvshow/Country.kt | 9 +++++ .../truedev/kinoposk/api/model/tvshow/Data.kt | 11 ++++++ .../kinoposk/api/model/tvshow/Episode.kt | 16 ++++++++ .../kinoposk/api/model/tvshow/Expectations.kt | 10 +++++ .../kinoposk/api/model/tvshow/Format.kt | 9 +++++ .../kinoposk/api/model/tvshow/Genre.kt | 11 ++++++ .../kinoposk/api/model/tvshow/Rating.kt | 10 +++++ .../kinoposk/api/model/tvshow/Season.kt | 11 ++++++ .../kinoposk/api/model/tvshow/TvShowExt.kt | 9 +++++ .../truedev/kinoposk/api/model/tvshow/Year.kt | 9 +++++ .../api/service/KPApiClientService.kt | 1 + .../api/service/KinopoiskApiService.kt | 37 ++++++++++++++++--- .../api/service/KinopoiskApiServiceTest.kt | 11 +++++- 16 files changed, 217 insertions(+), 9 deletions(-) create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/deserializer/StringToEpisodes.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/ContextData.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Country.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Data.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Episode.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Expectations.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Format.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Genre.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Rating.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Season.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/TvShowExt.kt create mode 100644 src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Year.kt diff --git a/readme.md b/readme.md index dd344cf..59da16f 100644 --- a/readme.md +++ b/readme.md @@ -33,7 +33,7 @@ or pom.xml build.gradle dependencies { - implementation 'com.github.TrueDevProfile:kinopoisk-api:0.2.0-beta.8' + implementation 'com.github.TrueDevProfile:kinopoisk-api:0.2.0' } or pom.xml @@ -41,7 +41,7 @@ or pom.xml com.github.TrueDevProfile kinopoisk-api - 0.2.0-beta.8 + 0.2.0 * After that you can use library's methods. E.g. to get film by kinopoisk id: diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/deserializer/StringToEpisodes.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/deserializer/StringToEpisodes.kt new file mode 100644 index 0000000..9e22c04 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/deserializer/StringToEpisodes.kt @@ -0,0 +1,36 @@ +package com.truedev.kinoposk.api.model.deserializer + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.ArrayNode +import com.truedev.kinoposk.api.model.tvshow.Episode +import java.time.LocalDate + +class StringToEpisodes : JsonDeserializer>() { + override fun deserialize(p: JsonParser, ctxt: DeserializationContext): List { + val node: Any = p.readValueAsTree() + + return (node as ArrayNode).toList() + .map { it.get("episode") } + .map { + try { + Episode( + id = it.get("id").asInt(), + seasonNumber = it.get("seasonNumber").asInt(), + episodeNumber = it.get("episodeNumber").asInt(), + name = it.get("name").asText().ifBlank { null }, + nameEng = it.get("nameEng").asText().ifBlank { null }, + synopsis = it.get("synopsis")?.asText(), + releaseDate = it.get("releaseDate") + ?.let { releaseDate -> LocalDate.parse(releaseDate.asText()) }, + dateAccuracy = it.get("dateAccuracy")?.asText() + ) + } catch (e: java.lang.NullPointerException) { + println(it) + throw RuntimeException() + } + } + } +} diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/ContextData.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/ContextData.kt new file mode 100644 index 0000000..d236620 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/ContextData.kt @@ -0,0 +1,32 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonProperty + +@JsonIgnoreProperties(ignoreUnknown = true) +data class ContextData( + val id: Int, + val slug: String?, + val title: String, + val originalTitle: String?, + val normalizedTitle: String?, + val year: Int, + val years: List = listOf(), + val rating: Rating, + val expectations: Expectations, + val currentRating: String, + // todo enum EXPECTATIONS,RATING + val type: String, + val serial: Boolean, + val shortFilm: Boolean, + val completed: Boolean, + val genres: List = listOf(), + val countries: List = listOf(), + val duration: Int, + val trailerId: Int, + val time: Int, + @JsonProperty(value = "fulltime") + val fullTime: Int, + @JsonProperty(value = "formats") + val format: Format +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Country.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Country.kt new file mode 100644 index 0000000..ba68069 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Country.kt @@ -0,0 +1,9 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Country( + val id: Int, + val name: String +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Data.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Data.kt new file mode 100644 index 0000000..b0a813b --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Data.kt @@ -0,0 +1,11 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Data( + val description: String?, + val downloadAvailable: Boolean, + val contextData: ContextData, + val seasons: List = listOf() +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Episode.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Episode.kt new file mode 100644 index 0000000..1447dd6 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Episode.kt @@ -0,0 +1,16 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import java.time.LocalDate + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Episode( + val id: Int, + val seasonNumber: Int, + val episodeNumber: Int, + val name: String?, + val nameEng: String?, + val synopsis: String?, + val releaseDate: LocalDate?, + val dateAccuracy: String? +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Expectations.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Expectations.kt new file mode 100644 index 0000000..00b3af4 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Expectations.kt @@ -0,0 +1,10 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Expectations( + val value: Double?, + val count: Int, + val ready: Boolean = false +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Format.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Format.kt new file mode 100644 index 0000000..d1ed2b7 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Format.kt @@ -0,0 +1,9 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Format( + val hasImax: Boolean, + val has3D: Boolean +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Genre.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Genre.kt new file mode 100644 index 0000000..d0939a0 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Genre.kt @@ -0,0 +1,11 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Genre( + val id: Int, + val name: String, + // translated genre + val slug: String +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Rating.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Rating.kt new file mode 100644 index 0000000..bf14847 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Rating.kt @@ -0,0 +1,10 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Rating( + val value: Double, + val count: Int, + val ready: Boolean = false +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Season.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Season.kt new file mode 100644 index 0000000..eb322b1 --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Season.kt @@ -0,0 +1,11 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.truedev.kinoposk.api.model.deserializer.StringToEpisodes +@JsonIgnoreProperties(ignoreUnknown = true) +data class Season( + val number: Int, + @JsonDeserialize(using = StringToEpisodes::class) + val episodes: List = listOf() +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/TvShowExt.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/TvShowExt.kt new file mode 100644 index 0000000..cc44b1f --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/TvShowExt.kt @@ -0,0 +1,9 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class TvShowExt( + val success: String, + val data: Data +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Year.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Year.kt new file mode 100644 index 0000000..34ce61a --- /dev/null +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/tvshow/Year.kt @@ -0,0 +1,9 @@ +package com.truedev.kinoposk.api.model.tvshow + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Year( + val start: Int, + val end: Int? +) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/service/KPApiClientService.kt b/src/main/kotlin/com/truedev/kinoposk/api/service/KPApiClientService.kt index 612e4b3..33d1dd8 100644 --- a/src/main/kotlin/com/truedev/kinoposk/api/service/KPApiClientService.kt +++ b/src/main/kotlin/com/truedev/kinoposk/api/service/KPApiClientService.kt @@ -32,6 +32,7 @@ internal class KPApiClientService(private val timeout: Int) { const val GET_NAVIGATOR_FILTERS = "navigatorFilters" const val GET_NAVIGATOR = "navigator" const val GET_DIGITAL = "/k/v1/films/releases/digital" + const val GET_TV_SHOW = "/k/v1/serial/" } fun request(url: String, path: String, clazz: Class): ResponseExt { diff --git a/src/main/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiService.kt b/src/main/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiService.kt index 7711f40..c5a7c86 100644 --- a/src/main/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiService.kt +++ b/src/main/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiService.kt @@ -16,6 +16,7 @@ import com.truedev.kinoposk.api.model.search.people.SearchPeopleResultExt import com.truedev.kinoposk.api.model.staff.StaffExt import com.truedev.kinoposk.api.model.top.TopExt import com.truedev.kinoposk.api.model.top.Type +import com.truedev.kinoposk.api.model.tvshow.TvShowExt import com.truedev.kinoposk.api.service.KPApiClientService.Companion.GET_BEST_FILMS_LIST import com.truedev.kinoposk.api.service.KPApiClientService.Companion.GET_DIGITAL import com.truedev.kinoposk.api.service.KPApiClientService.Companion.GET_FILM @@ -29,6 +30,7 @@ import com.truedev.kinoposk.api.service.KPApiClientService.Companion.GET_REVIEW_ import com.truedev.kinoposk.api.service.KPApiClientService.Companion.GET_SEARCH_FILM import com.truedev.kinoposk.api.service.KPApiClientService.Companion.GET_SEARCH_PEOPLE import com.truedev.kinoposk.api.service.KPApiClientService.Companion.GET_TOP +import com.truedev.kinoposk.api.service.KPApiClientService.Companion.GET_TV_SHOW import com.truedev.kinoposk.api.service.KPApiClientService.Companion.MAIN_API_URL import com.truedev.kinoposk.api.service.KPApiClientService.Companion.RELEASE_API_URL import java.lang.String.valueOf @@ -80,7 +82,11 @@ class KinopoiskApiService(timeout: Int = 15000) { fun getKPReviews(filmId: Int, page: Int = 1): ReviewListExt { require(filmId > 0) { "Film id should be more than 0" } require(page > 0) { "Page should be more than 0" } - return kpApiClientService.request(MAIN_API_URL, "$GET_REVIEWS?filmID=$filmId&page=$page", ReviewListExt::class.java) + return kpApiClientService.request( + MAIN_API_URL, + "$GET_REVIEWS?filmID=$filmId&page=$page", + ReviewListExt::class.java + ) .let { ReviewListExt(it.resultCode, it.message, it.response?.data) } } @@ -122,8 +128,10 @@ class KinopoiskApiService(timeout: Int = 15000) { require(page > 0) { "Page should be more than 0" } return kpApiClientService.request( MAIN_API_URL, - "$GET_SEARCH_FILM?keyword=${UrlEscapers.urlFragmentEscaper() - .escape(keyword.replace("[^a-zA-Zа-яА-Я0-9_]".toRegex(), " "))}&page=$page", + "$GET_SEARCH_FILM?keyword=${ + UrlEscapers.urlFragmentEscaper() + .escape(keyword.replace("[^a-zA-Zа-яА-Я0-9_]".toRegex(), " ")) + }&page=$page", SearchFimResultExt::class.java ).let { SearchFimResultExt(it.resultCode, it.message, it.response?.data) } } @@ -138,8 +146,10 @@ class KinopoiskApiService(timeout: Int = 15000) { require(page > 0) { "Page should be more than 0" } return kpApiClientService.request( MAIN_API_URL, - "$GET_SEARCH_PEOPLE?keyword=${UrlEscapers.urlFragmentEscaper() - .escape(keyword.replace("[^a-zA-Zа-яА-Я0-9_]".toRegex(), " "))}&page=$page", + "$GET_SEARCH_PEOPLE?keyword=${ + UrlEscapers.urlFragmentEscaper() + .escape(keyword.replace("[^a-zA-Zа-яА-Я0-9_]".toRegex(), " ")) + }&page=$page", SearchPeopleResultExt::class.java ).let { SearchPeopleResultExt(it.resultCode, it.message, it.response?.data) } } @@ -246,4 +256,21 @@ class KinopoiskApiService(timeout: Int = 15000) { ) } } + + /** + * This method retrieves tv show data (series, seasons and so on). + * + */ + fun getTvShowInfo(tvShowId: Int): TvShowExt { + require(tvShowId > 0) { "Tv show id should be more than 0" } + return kpApiClientService.request( + RELEASE_API_URL, "$GET_TV_SHOW$tvShowId", + TvShowExt::class.java + ).let { + TvShowExt( + it.response!!.success, + it.response.data + ) + } + } } diff --git a/src/test/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt b/src/test/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt index 65f20f1..4f77cf4 100644 --- a/src/test/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt +++ b/src/test/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt @@ -16,7 +16,7 @@ class KinopoiskApiServiceTest { @Test fun `test getFilmInfo will return valid film when id exists`() { - val filmInfo = kinopoiskApiService.getFilmInfo(843650) + val filmInfo = kinopoiskApiService.getFilmInfo(915196) assertEquals(843650, filmInfo.data?.filmID) assertNull(filmInfo.data?.seriesInfo) @@ -80,7 +80,7 @@ class KinopoiskApiServiceTest { @Test fun `test getKPPeopleDetailView will return valid data when id exists`() { - val kpPeopleDetailView = kinopoiskApiService.getKPPeopleDetailView(2162346) + val kpPeopleDetailView = kinopoiskApiService.getKPPeopleDetailView(10096) assertEquals(2162346, kpPeopleDetailView.data?.peopleID) } @@ -203,4 +203,11 @@ class KinopoiskApiServiceTest { assertTrue(kpDigital.data?.items!!.isNotEmpty()) assertTrue(kpDigital.data?.stats?.offset == 0) } + + @Test + fun `test getTvShowInfo will return empty data when id does not exist`() { + val tvShow = kinopoiskApiService.getTvShowInfo(922024) + + assertEquals(922024, tvShow.data.contextData.id) + } } From 7e9b32a9d76b4eb171913615ab48ef60c1122c7b Mon Sep 17 00:00:00 2001 From: TrueDevProfile Date: Tue, 8 Sep 2020 14:50:12 +0400 Subject: [PATCH 2/3] feature: add tv shows --- .../model/deserializer/StringToEpisodes.kt | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/com/truedev/kinoposk/api/model/deserializer/StringToEpisodes.kt b/src/main/kotlin/com/truedev/kinoposk/api/model/deserializer/StringToEpisodes.kt index 9e22c04..553bdbb 100644 --- a/src/main/kotlin/com/truedev/kinoposk/api/model/deserializer/StringToEpisodes.kt +++ b/src/main/kotlin/com/truedev/kinoposk/api/model/deserializer/StringToEpisodes.kt @@ -15,22 +15,17 @@ class StringToEpisodes : JsonDeserializer>() { return (node as ArrayNode).toList() .map { it.get("episode") } .map { - try { - Episode( - id = it.get("id").asInt(), - seasonNumber = it.get("seasonNumber").asInt(), - episodeNumber = it.get("episodeNumber").asInt(), - name = it.get("name").asText().ifBlank { null }, - nameEng = it.get("nameEng").asText().ifBlank { null }, - synopsis = it.get("synopsis")?.asText(), - releaseDate = it.get("releaseDate") - ?.let { releaseDate -> LocalDate.parse(releaseDate.asText()) }, - dateAccuracy = it.get("dateAccuracy")?.asText() - ) - } catch (e: java.lang.NullPointerException) { - println(it) - throw RuntimeException() - } + Episode( + id = it.get("id").asInt(), + seasonNumber = it.get("seasonNumber").asInt(), + episodeNumber = it.get("episodeNumber").asInt(), + name = it.get("name").asText().ifBlank { null }, + nameEng = it.get("nameEng").asText().ifBlank { null }, + synopsis = it.get("synopsis")?.asText(), + releaseDate = it.get("releaseDate") + ?.let { releaseDate -> LocalDate.parse(releaseDate.asText()) }, + dateAccuracy = it.get("dateAccuracy")?.asText() + ) } } } From c774579fdcca17643a12088c2af769b9e1b517b5 Mon Sep 17 00:00:00 2001 From: TrueDevProfile Date: Tue, 8 Sep 2020 14:52:00 +0400 Subject: [PATCH 3/3] feature: add tv shows --- .../truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt b/src/test/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt index 4f77cf4..ef0cf36 100644 --- a/src/test/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt +++ b/src/test/kotlin/com/truedev/kinoposk/api/service/KinopoiskApiServiceTest.kt @@ -16,7 +16,7 @@ class KinopoiskApiServiceTest { @Test fun `test getFilmInfo will return valid film when id exists`() { - val filmInfo = kinopoiskApiService.getFilmInfo(915196) + val filmInfo = kinopoiskApiService.getFilmInfo(843650) assertEquals(843650, filmInfo.data?.filmID) assertNull(filmInfo.data?.seriesInfo) @@ -80,7 +80,7 @@ class KinopoiskApiServiceTest { @Test fun `test getKPPeopleDetailView will return valid data when id exists`() { - val kpPeopleDetailView = kinopoiskApiService.getKPPeopleDetailView(10096) + val kpPeopleDetailView = kinopoiskApiService.getKPPeopleDetailView(2162346) assertEquals(2162346, kpPeopleDetailView.data?.peopleID) }