Skip to content

Commit 47ebd3b

Browse files
committed
✨ Added user to detail ✨
1 parent 80c882e commit 47ebd3b

File tree

9 files changed

+321
-60
lines changed

9 files changed

+321
-60
lines changed

src/main/kotlin/club/anifox/backend/controller/anime/AnimeController.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,10 @@ class AnimeController {
129129
@GetMapping("/{url}")
130130
@Operation(summary = "detail anime")
131131
fun getAnimeDetails(
132+
@RequestHeader(value = "Authorization", required = false) token: String?,
132133
@PathVariable url: String,
133134
): AnimeDetail {
134-
return animeService.getAnimeDetails(url)
135+
return animeService.getAnimeDetails(token, url)
135136
}
136137

137138
@GetMapping("/{url}/statistics")

src/main/kotlin/club/anifox/backend/domain/enums/user/StatusFavourite.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,32 @@
11
package club.anifox.backend.domain.enums.user
22

33
import io.swagger.v3.oas.annotations.media.Schema
4+
import kotlinx.serialization.SerialName
5+
import kotlinx.serialization.Serializable
46

7+
@Serializable
58
@Schema(description = "Anime favourite status")
69
enum class StatusFavourite(val jsonKey: String) {
10+
@SerialName("plan_to_watch")
711
@Schema(description = "Plan to watch", example = "plan_to_watch")
812
InPlan("plan_to_watch"),
913

14+
@SerialName("watching")
1015
@Schema(description = "Currently watching", example = "watching")
1116
Watching("watching"),
1217

18+
@SerialName("completed")
1319
@Schema(description = "Finished watching", example = "completed")
1420
Completed("completed"),
1521

22+
@SerialName("dropped")
1623
@Schema(description = "Dropped watching", example = "dropped")
1724
Dropped("dropped"),
1825

26+
@SerialName("on_hold")
1927
@Schema(description = "Put on hold", example = "on_hold")
20-
OnHold("on_hold");
28+
OnHold("on_hold"),
29+
;
2130

2231
override fun toString(): String {
2332
return jsonKey

src/main/kotlin/club/anifox/backend/domain/mappers/anime/detail/AnimeDetail.kt

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import club.anifox.backend.domain.mappers.anime.toAnimeTranslation
44
import club.anifox.backend.domain.mappers.anime.toGenre
55
import club.anifox.backend.domain.mappers.anime.toStudio
66
import club.anifox.backend.domain.model.anime.AnimeImages
7+
import club.anifox.backend.domain.model.anime.AnimeUserStats
78
import club.anifox.backend.domain.model.anime.detail.AnimeDetail
9+
import club.anifox.backend.domain.model.anime.detail.AnimeDetailDefault
10+
import club.anifox.backend.domain.model.anime.detail.AnimeDetailWithUser
811
import club.anifox.backend.jpa.entity.anime.AnimeTable
912

10-
fun AnimeTable.toAnimeDetail(): AnimeDetail {
11-
return AnimeDetail(
13+
fun AnimeTable.toAnimeDetailDefault(): AnimeDetailDefault {
14+
return AnimeDetailDefault(
1215
url = url,
1316
title = title,
1417
image = AnimeImages(large = images.large, medium = images.medium, cover = images.cover),
@@ -36,3 +39,43 @@ fun AnimeTable.toAnimeDetail(): AnimeDetail {
3639
translations = translations.toList().map { it.toAnimeTranslation() },
3740
)
3841
}
42+
43+
fun AnimeTable.toAnimeDetailWithUser(userStats: AnimeUserStats): AnimeDetailWithUser {
44+
return AnimeDetailWithUser(
45+
url = url,
46+
title = title,
47+
image = AnimeImages(large = images.large, medium = images.medium, cover = images.cover),
48+
studio = studios.toList().map { it.toStudio() },
49+
season = season,
50+
description = description,
51+
titleOther = titleOther,
52+
titleEnglish = titleEn.toList(),
53+
titleJapan = titleJapan.toList(),
54+
synonyms = synonyms,
55+
nextEpisode = nextEpisode,
56+
year = year,
57+
releasedOn = releasedOn,
58+
airedOn = airedOn,
59+
type = type,
60+
rating = totalRating,
61+
shikimoriRating = shikimoriRating,
62+
episodes = episodesCount,
63+
episodesAired = episodesAired,
64+
playerLink = playerLink,
65+
genres = genres.toList().map { it.toGenre() },
66+
status = status,
67+
ratingMpa = ratingMpa,
68+
minimalAge = minimalAge,
69+
translations = translations.toList().map { it.toAnimeTranslation() },
70+
user = userStats,
71+
)
72+
}
73+
74+
// Универсальный маппер, который можно использовать в сервисе
75+
fun AnimeTable.toAnimeDetail(userStats: AnimeUserStats? = null): AnimeDetail {
76+
return if (userStats != null) {
77+
toAnimeDetailWithUser(userStats)
78+
} else {
79+
toAnimeDetailDefault()
80+
}
81+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package club.anifox.backend.domain.model.anime
2+
3+
import club.anifox.backend.domain.enums.user.StatusFavourite
4+
import kotlinx.serialization.EncodeDefault
5+
import kotlinx.serialization.ExperimentalSerializationApi
6+
import kotlinx.serialization.SerialName
7+
import kotlinx.serialization.Serializable
8+
9+
@Serializable
10+
data class AnimeUserStats
11+
@OptIn(ExperimentalSerializationApi::class)
12+
constructor(
13+
@SerialName("is_fav")
14+
@EncodeDefault
15+
val isFavourite: Boolean = false,
16+
@SerialName("list")
17+
@EncodeDefault
18+
val list: StatusFavourite? = null,
19+
@SerialName("rating")
20+
@EncodeDefault
21+
val rating: Int? = null,
22+
)

src/main/kotlin/club/anifox/backend/domain/model/anime/detail/AnimeDetail.kt

Lines changed: 166 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,52 +8,191 @@ import club.anifox.backend.domain.enums.anime.AnimeType
88
import club.anifox.backend.domain.model.anime.AnimeGenre
99
import club.anifox.backend.domain.model.anime.AnimeImages
1010
import club.anifox.backend.domain.model.anime.AnimeStudio
11+
import club.anifox.backend.domain.model.anime.AnimeUserStats
1112
import club.anifox.backend.domain.model.anime.translation.AnimeTranslation
13+
import club.anifox.backend.util.serializer.AnimeDetailSerializer
1214
import club.anifox.backend.util.serializer.LocalDateSerializer
1315
import club.anifox.backend.util.serializer.LocalDateTimeSerializer
16+
import kotlinx.serialization.EncodeDefault
17+
import kotlinx.serialization.ExperimentalSerializationApi
18+
import kotlinx.serialization.Polymorphic
1419
import kotlinx.serialization.SerialName
1520
import kotlinx.serialization.Serializable
1621
import kotlinx.serialization.UseSerializers
1722
import java.time.LocalDate
1823
import java.time.LocalDateTime
1924

25+
@Serializable(with = AnimeDetailSerializer::class)
26+
@Polymorphic
27+
@SerialName("without_type")
28+
sealed interface AnimeDetail {
29+
var title: String
30+
var image: AnimeImages
31+
32+
@SerialName("player_link")
33+
val playerLink: String?
34+
val url: String
35+
36+
val type: AnimeType
37+
38+
@SerialName("rating_mpa")
39+
val ratingMpa: String
40+
41+
@SerialName("minimal_age")
42+
val minimalAge: Int
43+
val rating: Double?
44+
45+
@SerialName("shikimori_rating")
46+
val shikimoriRating: Double
47+
val year: Int
48+
val status: AnimeStatus
49+
val season: AnimeSeason
50+
51+
@SerialName("episodes")
52+
val episodes: Int?
53+
54+
@SerialName("episodes_aired")
55+
val episodesAired: Int?
56+
57+
@SerialName("next_episode_on")
58+
val nextEpisode: LocalDateTime?
59+
60+
@SerialName("released_on")
61+
val releasedOn: LocalDate?
62+
63+
@SerialName("aired_on")
64+
val airedOn: LocalDate
65+
val description: String?
66+
67+
@SerialName("other_title")
68+
val titleOther: List<String>?
69+
70+
@SerialName("english")
71+
val titleEnglish: List<String>?
72+
73+
@SerialName("japanese")
74+
val titleJapan: List<String>?
75+
val synonyms: List<String>?
76+
val studio: List<AnimeStudio>
77+
val genres: List<AnimeGenre>
78+
val translations: List<AnimeTranslation>?
79+
}
80+
81+
@Serializable
82+
@SerialName("default")
83+
data class AnimeDetailDefault(
84+
override var title: String = "",
85+
override var image: AnimeImages = AnimeImages(),
86+
@SerialName("player_link")
87+
override val playerLink: String? = "",
88+
override val url: String = "",
89+
override val type: AnimeType,
90+
@SerialName("rating_mpa")
91+
override val ratingMpa: String = "",
92+
@SerialName("minimal_age")
93+
override val minimalAge: Int = 0,
94+
override val rating: Double? = 0.0,
95+
@SerialName("shikimori_rating")
96+
override val shikimoriRating: Double = 0.0,
97+
override val year: Int = 0,
98+
override val status: AnimeStatus,
99+
override val season: AnimeSeason,
100+
@SerialName("episodes")
101+
override val episodes: Int? = 0,
102+
@SerialName("episodes_aired")
103+
override val episodesAired: Int? = 0,
104+
@SerialName("next_episode_on")
105+
override val nextEpisode: LocalDateTime? = LocalDateTime.now(),
106+
@SerialName("released_on")
107+
override val releasedOn: LocalDate? = LocalDate.now(),
108+
@SerialName("aired_on")
109+
override val airedOn: LocalDate = LocalDate.now(),
110+
override val description: String? = "",
111+
@SerialName("other_title")
112+
override val titleOther: List<String>? = listOf(),
113+
@SerialName("english")
114+
override val titleEnglish: List<String>? = listOf(),
115+
@SerialName("japanese")
116+
override val titleJapan: List<String>? = listOf(),
117+
override val synonyms: List<String>? = listOf(),
118+
override val studio: List<AnimeStudio> = listOf(),
119+
override val genres: List<AnimeGenre> = listOf(),
120+
override val translations: List<AnimeTranslation>? = listOf(),
121+
) : AnimeDetail
122+
20123
@Serializable
21-
data class AnimeDetail(
22-
var title: String = "",
23-
var image: AnimeImages = AnimeImages(),
124+
@SerialName("with_user")
125+
data class AnimeDetailWithUser
126+
@OptIn(ExperimentalSerializationApi::class)
127+
constructor(
128+
override var title: String = "",
129+
override var image: AnimeImages = AnimeImages(),
24130
@SerialName("player_link")
25-
val playerLink: String? = "",
26-
val url: String = "",
27-
val type: AnimeType,
131+
override val playerLink: String? = "",
132+
override val url: String = "",
133+
override val type: AnimeType,
28134
@SerialName("rating_mpa")
29-
val ratingMpa: String = "",
135+
override val ratingMpa: String = "",
30136
@SerialName("minimal_age")
31-
val minimalAge: Int = 0,
32-
val rating: Double? = 0.0,
137+
override val minimalAge: Int = 0,
138+
override val rating: Double? = 0.0,
33139
@SerialName("shikimori_rating")
34-
val shikimoriRating: Double = 0.0,
35-
val year: Int = 0,
36-
val status: AnimeStatus,
37-
val season: AnimeSeason,
140+
override val shikimoriRating: Double = 0.0,
141+
override val year: Int = 0,
142+
override val status: AnimeStatus,
143+
override val season: AnimeSeason,
38144
@SerialName("episodes")
39-
val episodes: Int? = 0,
145+
override val episodes: Int? = 0,
40146
@SerialName("episodes_aired")
41-
val episodesAired: Int? = 0,
147+
override val episodesAired: Int? = 0,
42148
@SerialName("next_episode_on")
43-
val nextEpisode: LocalDateTime? = LocalDateTime.now(),
149+
override val nextEpisode: LocalDateTime? = LocalDateTime.now(),
44150
@SerialName("released_on")
45-
val releasedOn: LocalDate? = LocalDate.now(),
151+
override val releasedOn: LocalDate? = LocalDate.now(),
46152
@SerialName("aired_on")
47-
val airedOn: LocalDate = LocalDate.now(),
48-
val description: String? = "",
153+
override val airedOn: LocalDate = LocalDate.now(),
154+
override val description: String? = "",
49155
@SerialName("other_title")
50-
val titleOther: List<String>? = listOf(),
156+
override val titleOther: List<String>? = listOf(),
51157
@SerialName("english")
52-
val titleEnglish: List<String>? = listOf(),
158+
override val titleEnglish: List<String>? = listOf(),
53159
@SerialName("japanese")
54-
val titleJapan: List<String>? = listOf(),
55-
val synonyms: List<String>? = listOf(),
56-
val studio: List<AnimeStudio> = listOf(),
57-
val genres: List<AnimeGenre> = listOf(),
58-
val translations: List<AnimeTranslation>? = listOf(),
59-
)
160+
override val titleJapan: List<String>? = listOf(),
161+
override val synonyms: List<String>? = listOf(),
162+
override val studio: List<AnimeStudio> = listOf(),
163+
override val genres: List<AnimeGenre> = listOf(),
164+
override val translations: List<AnimeTranslation>? = listOf(),
165+
@EncodeDefault
166+
val user: AnimeUserStats? = null,
167+
) : AnimeDetail
168+
169+
// Extension function для конвертации
170+
fun AnimeDetailDefault.withUser(userStats: AnimeUserStats = AnimeUserStats()) =
171+
AnimeDetailWithUser(
172+
title = this.title,
173+
image = this.image,
174+
playerLink = this.playerLink,
175+
url = this.url,
176+
type = this.type,
177+
ratingMpa = this.ratingMpa,
178+
minimalAge = this.minimalAge,
179+
rating = this.rating,
180+
shikimoriRating = this.shikimoriRating,
181+
year = this.year,
182+
status = this.status,
183+
season = this.season,
184+
episodes = this.episodes,
185+
episodesAired = this.episodesAired,
186+
nextEpisode = this.nextEpisode,
187+
releasedOn = this.releasedOn,
188+
airedOn = this.airedOn,
189+
description = this.description,
190+
titleOther = this.titleOther,
191+
titleEnglish = this.titleEnglish,
192+
titleJapan = this.titleJapan,
193+
synonyms = this.synonyms,
194+
studio = this.studio,
195+
genres = this.genres,
196+
translations = this.translations,
197+
user = userStats,
198+
)

src/main/kotlin/club/anifox/backend/domain/repository/anime/AnimeRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ interface AnimeRepository {
3030

3131
fun getAnimeTranslations(): List<AnimeTranslationTable>
3232

33-
fun getAnimeDetails(url: String): AnimeDetail
33+
fun getAnimeDetails(token: String?, url: String): AnimeDetail
3434

3535
fun getAnimeSimilar(page: Int, limit: Int, url: String): List<AnimeLight>
3636

src/main/kotlin/club/anifox/backend/service/anime/AnimeService.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,11 @@ class AnimeService : AnimeRepository {
8787
)
8888
}
8989

90-
override fun getAnimeDetails(url: String): AnimeDetail {
91-
return animeCommonComponent.getAnimeByUrl(url)
90+
override fun getAnimeDetails(
91+
token: String?,
92+
url: String,
93+
): AnimeDetail {
94+
return animeCommonComponent.getAnimeByUrl(token, url)
9295
}
9396

9497
override fun getAnimeStatistics(url: String): AnimeStatistics {

0 commit comments

Comments
 (0)