Skip to content

Commit f53ed50

Browse files
committed
Include two endpoins for news in spanish and english
1 parent 08caaa6 commit f53ed50

File tree

20 files changed

+563
-141
lines changed

20 files changed

+563
-141
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ repositories {
2020

2121
dependencies {
2222
implementation(libs.bson)
23+
implementation(libs.rssparser)
2324
implementation(libs.ktor.client.cio)
2425
implementation(libs.logback.classic)
2526
implementation(libs.ktor.client.core)

gradle/libs.versions.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
[versions]
33
kotlin-version = "2.0.21"
44
ktor-version = "3.0.1"
5-
logback-version = "1.4.14"
5+
logback-version = "1.5.18"
66
mongo-version = "4.10.2"
7+
rss-version = "6.0.11"
78

89
[libraries]
910
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor-version" }
@@ -15,6 +16,7 @@ ktor-server-content-negotiation = { module = "io.ktor:ktor-server-content-negoti
1516
mongodb-driver-core = { module = "org.mongodb:mongodb-driver-core", version.ref = "mongo-version" }
1617
mongodb-driver-sync = { module = "org.mongodb:mongodb-driver-sync", version.ref = "mongo-version" }
1718
bson = { module = "org.mongodb:bson", version.ref = "mongo-version" }
19+
rssparser = { module = "com.prof18.rssparser:rssparser", version.ref = "rss-version" }
1820
ktor-server-netty = { module = "io.ktor:ktor-server-netty-jvm", version.ref = "ktor-version" }
1921
logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback-version" }
2022
ktor-server-config-yaml = { module = "io.ktor:ktor-server-config-yaml-jvm", version.ref = "ktor-version" }

src/main/kotlin/com/jeluchu/core/configuration/Routes.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.jeluchu.core.configuration
22

33
import com.jeluchu.features.anime.routes.animeEndpoints
4+
import com.jeluchu.features.news.routes.newsEndpoints
45
import com.jeluchu.features.rankings.routes.rankingsEndpoints
56
import com.jeluchu.features.schedule.routes.scheduleEndpoints
7+
import com.jeluchu.features.themes.routes.themesEndpoints
68
import com.mongodb.client.MongoDatabase
79
import io.ktor.server.application.*
810
import io.ktor.server.routing.*
@@ -12,7 +14,9 @@ fun Application.initRoutes(
1214
) = routing {
1315
route("api/v5") {
1416
initDocumentation()
17+
newsEndpoints(mongoDatabase)
1518
animeEndpoints(mongoDatabase)
19+
themesEndpoints(mongoDatabase)
1620
rankingsEndpoints(mongoDatabase)
1721
scheduleEndpoints(mongoDatabase)
1822
}

src/main/kotlin/com/jeluchu/core/extensions/CommonExtensions.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
11
package com.jeluchu.core.extensions
22

3+
import io.ktor.http.*
4+
import io.ktor.server.response.*
5+
import io.ktor.server.routing.*
36
import org.bson.Document
47
import java.text.SimpleDateFormat
58
import java.util.*
69

10+
fun RoutingCall.getIntSafeQueryParam(
11+
key: String,
12+
defaultValue: Int = 0
13+
) = request.queryParameters[key]?.toIntOrNull() ?: defaultValue
14+
15+
fun RoutingCall.getStringSafeQueryParam(
16+
key: String,
17+
defaultValue: String = ""
18+
) = request.queryParameters[key] ?: defaultValue
19+
20+
fun RoutingCall.getStringSafeParam(
21+
key: String,
22+
defaultValue: String = ""
23+
) = parameters[key] ?: defaultValue
24+
25+
fun RoutingCall.getIntSafeParam(
26+
key: String,
27+
defaultValue: Int = 0
28+
) = parameters[key]?.toIntOrNull() ?: defaultValue
29+
30+
suspend fun RoutingCall.badRequestError(message: String) = respond(HttpStatusCode.BadRequest, message)
31+
732
fun Document.getStringSafe(key: String, defaultValue: String = ""): String {
833
return try {
934
when (val value = this[key]) {
@@ -112,4 +137,10 @@ fun Document.getDocumentSafe(key: String): Document? {
112137
} catch (e: Exception) {
113138
null
114139
}
140+
}
141+
142+
fun String.parseRssDate(format: String = "dd/MM/yyyy"): String {
143+
val date = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US).parse(this)
144+
val outputDateFormat = SimpleDateFormat(format, Locale.US)
145+
return date?.let { outputDateFormat.format(it) }.orEmpty()
115146
}

src/main/kotlin/com/jeluchu/core/utils/Constants.kt

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,38 @@ package com.jeluchu.core.utils
22

33
object BaseUrls {
44
const val JIKAN = "https://api.jikan.moe/v4/"
5-
const val ANIME_FLV = "https://animeflv.ahmedrangel.com/api/"
5+
const val ANIME_THEMES = "https://api.animethemes.moe/"
6+
}
7+
8+
object RssUrls {
9+
// Spanish news
10+
const val SOMOSKUDASAI = "https://somoskudasai.com/feed/"
11+
const val MANGALATAM = "https://www.mangalatam.com/feeds/posts/default?alt=rss"
12+
const val CRUNCHYROLL = "https://cr-news-api-service.prd.crunchyrollsvc.com/v1/es-ES/rss"
13+
const val RAMENPARADOS = "https://ramenparados.com/feed/"
14+
const val ANMOSUGOI = "https://www.anmosugoi.com/feed/"
15+
16+
// English news
17+
const val OTAKUMODE = "https://otakumode.com/news/feed"
18+
const val MYANIMELIST = "https://myanimelist.net/rss/news.xml"
19+
const val HONEYSANIME = "https://honeysanime.com/feed/"
20+
const val ANIMEHUNCH = "https://animehunch.com/feed/"
21+
}
22+
23+
object RssSources {
24+
const val SOMOSKUDASAI = "Somos Kudasai"
25+
const val MANGALATAM = "MangaLatam"
26+
const val CRUNCHYROLL = "Crunchyroll"
27+
const val RAMENPARADOS = "Ramen para dos"
28+
const val ANMOSUGOI = "Anmo Sugoi"
29+
const val OTAKUMODE = "Tokyo Otaku Mode News"
30+
const val MYANIMELIST = "MyAnimeList"
31+
const val HONEYSANIME = "Honey's anime"
32+
const val ANIMEHUNCH = "My Anime For Life"
633
}
734

835
object Endpoints {
36+
const val ANIME = "anime"
937
const val SCHEDULES = "schedules"
1038
const val TOP_ANIME = "top/anime"
1139
const val TOP_MANGA = "top/manga"
@@ -15,7 +43,10 @@ object Endpoints {
1543
}
1644

1745
object Routes {
46+
const val ES = "/es"
47+
const val EN = "/en"
1848
const val TOP = "/top"
49+
const val NEWS = "/news"
1950
const val ANIME = "/anime"
2051
const val MANGA = "/manga"
2152
const val PEOPLE = "/people"
@@ -27,19 +58,25 @@ object Routes {
2758
const val TYPE = "/{type}"
2859
const val SEASON = "/{year}/{season}"
2960
const val DAY = "/{day}"
61+
const val THEMES = "/themes"
3062
}
3163

3264
object TimerKey {
3365
const val KEY = "key"
3466
const val SCHEDULE = "schedule"
3567
const val LAST_UPDATED = "lastUpdated"
3668
const val ANIME_TYPE = "anime_"
69+
const val THEMES = "themes_"
3770
const val LAST_EPISODES = "last_episodes"
3871
}
3972

4073
object Collections {
4174
const val TIMERS = "timers"
75+
const val NEWS_ES = "news_es"
76+
const val NEWS_EN = "news_en"
4277
const val SCHEDULES = "schedule"
78+
const val ANIME_THEMES = "anime_themes"
79+
const val ARTISTS_INDEX = "artists_index"
4380
const val ANIME_DETAILS = "anime_details"
4481
const val LAST_EPISODES = "last_episodes"
4582
const val ANIME_RANKING = "anime_ranking"

src/main/kotlin/com/jeluchu/features/anime/mappers/AnimeMappers.kt

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package com.jeluchu.features.anime.mappers
22

3+
import com.jeluchu.features.themes.models.anime.AnimeThemeEntry
34
import com.jeluchu.core.extensions.*
4-
import com.jeluchu.features.anime.models.lastepisodes.LastEpisodeData
55
import com.jeluchu.features.anime.models.anime.*
66
import com.jeluchu.features.anime.models.directory.AnimeTypeEntity
7+
import com.jeluchu.features.anime.models.lastepisodes.LastEpisodeData
78
import com.jeluchu.features.rankings.models.AnimeTopEntity
89
import com.jeluchu.features.rankings.models.CharacterTopEntity
910
import com.jeluchu.features.rankings.models.MangaTopEntity
1011
import com.jeluchu.features.rankings.models.PeopleTopEntity
1112
import com.jeluchu.features.schedule.models.DayEntity
13+
import com.jeluchu.features.themes.models.anime.Anime
14+
import com.jeluchu.features.themes.models.anime.AnimeVideoTheme
15+
import com.jeluchu.features.themes.models.anime.AnimesEntity
16+
import com.jeluchu.features.themes.models.anime.Video
1217
import org.bson.Document
1318
import java.time.ZonedDateTime
1419
import java.time.format.DateTimeFormatter
@@ -82,13 +87,6 @@ fun documentToAnimeBroadcast(doc: Document): AnimeBroadcast {
8287
)
8388
}
8489

85-
fun documentToAnimeSource(doc: Document): AnimeSource {
86-
return AnimeSource(
87-
id = doc.getStringSafe("id"),
88-
source = doc.getStringSafe("source")
89-
)
90-
}
91-
9290
fun documentToCharacter(doc: Document): Character {
9391
return Character(
9492
character = doc.getDocumentSafe("character")?.let { documentToIndividual(it) } ?: Individual(),
@@ -278,23 +276,69 @@ fun documentToCharacterTopEntity(doc: Document) = CharacterTopEntity(
278276
)
279277

280278
fun documentToAnimeTypeEntity(doc: Document) = AnimeTypeEntity(
281-
score = doc.getStringSafe("score"),
282-
malId = doc.getIntSafe("malId"),
283279
year = doc.getIntSafe("year"),
284-
season = doc.getStringSafe("season"),
280+
malId = doc.getIntSafe("malId"),
285281
type = doc.getStringSafe("type"),
282+
score = doc.getStringSafe("score"),
286283
title = doc.getStringSafe("title"),
287284
image = doc.getStringSafe("poster"),
288-
episodes = doc.getListSafe<Document>("episodes").size
285+
season = doc.getStringSafe("season")
289286
)
290287

291288
fun documentToAnimeDirectoryEntity(doc: Document) = AnimeTypeEntity(
292-
score = doc.getString("score"),
293-
malId = doc.getIntSafe("malId"),
294289
year = doc.getIntSafe("year"),
295-
season = doc.getStringSafe("season"),
290+
malId = doc.getIntSafe("malId"),
296291
type = doc.getStringSafe("type"),
292+
score = doc.getStringSafe("score"),
297293
title = doc.getStringSafe("title"),
298294
image = doc.getStringSafe("image"),
299-
episodes = doc.getListSafe<Document>("episodes").size
295+
season = doc.getStringSafe("season")
296+
)
297+
298+
299+
fun documentToAnimesEntity(doc: Document) = AnimesEntity(
300+
year = doc.getIntSafe("year"),
301+
slug = doc.getStringSafe("slug"),
302+
name = doc.getStringSafe("name"),
303+
image = doc.getStringSafe("image"),
304+
season = doc.getStringSafe("season")
305+
)
306+
307+
fun documentToAnimesThemeEntity(doc: Document) = Anime(
308+
year = doc.getIntSafe("year"),
309+
slug = doc.getStringSafe("slug"),
310+
name = doc.getStringSafe("name"),
311+
image = doc.getStringSafe("image"),
312+
season = doc.getStringSafe("season"),
313+
themes = doc.getListSafe<Document>("themes").map { documentToAnimeVideoTheme(it) }
314+
)
315+
316+
fun documentToAnimeVideoTheme(doc: Document) = AnimeVideoTheme(
317+
id = doc.getIntSafe("id"),
318+
slug = doc.getStringSafe("slug"),
319+
type = doc.getStringSafe("type"),
320+
sequence = doc.getIntSafe("sequence"),
321+
entries = doc.getListSafe<Document>("animethemeentries").map { documentToAnimeThemeEntry(it) }
322+
)
323+
324+
fun documentToAnimeThemeEntry(doc: Document) = AnimeThemeEntry(
325+
id = doc.getIntSafe("id"),
326+
nsfw = doc.getBooleanSafe("nsfw"),
327+
notes = doc.getStringSafe("notes"),
328+
spoiler = doc.getBooleanSafe("spoiler"),
329+
episodes = doc.getStringSafe("episodes"),
330+
videos = doc.getListSafe<Document>("videos").map { documentToVideo(it) }
331+
)
332+
333+
fun documentToVideo(doc: Document) = Video(
334+
nc = doc.getBooleanSafe("nc"),
335+
size = doc.getIntSafe("size"),
336+
link = doc.getStringSafe("link"),
337+
uncen = doc.getBooleanSafe("uncen"),
338+
source = doc.getStringSafe("source"),
339+
subbed = doc.getBooleanSafe("subbed"),
340+
lyrics = doc.getBooleanSafe("lyrics"),
341+
overlap = doc.getStringSafe("overlap"),
342+
filename = doc.getStringSafe("filename"),
343+
resolution = doc.getIntSafe("resolution")
300344
)

src/main/kotlin/com/jeluchu/features/anime/models/directory/AnimeTypeEntity.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import kotlinx.serialization.Serializable
66
data class AnimeTypeEntity(
77
val malId: Int? = 0,
88
val type: String? = "",
9-
val episodes: Int? = 0,
109
val year: Int? = 0,
1110
val season: String? = "",
1211
val title: String? = "",

0 commit comments

Comments
 (0)