2021-07-17 13:15:14 +02:00
/ * *
* Teapod
*
2022-01-02 17:59:23 +01:00
* Copyright 2020 - 2022 < seil0 @mosad . xyz >
2021-07-17 13:15:14 +02:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston ,
* MA 02110 - 1301 , USA .
*
* /
2021-07-10 23:37:16 +02:00
package org.mosad.teapod.util.tmdb
2022-03-05 20:41:39 +01:00
import android.util.Log
import io.ktor.client.*
import io.ktor.client.call.*
2022-08-19 18:15:37 +02:00
import io.ktor.client.plugins.contentnegotiation.*
2022-03-05 20:41:39 +01:00
import io.ktor.client.request.*
import io.ktor.client.statement.*
2022-08-19 18:15:37 +02:00
import io.ktor.serialization.kotlinx.json.*
2022-03-05 20:41:39 +01:00
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.invoke
import kotlinx.serialization.SerializationException
2021-12-31 16:03:15 +01:00
import kotlinx.serialization.json.Json
2022-03-06 18:43:02 +01:00
import org.mosad.teapod.preferences.Preferences
2021-12-31 16:03:15 +01:00
import org.mosad.teapod.util.concatenate
2021-07-10 23:37:16 +02:00
2021-07-17 13:15:14 +02:00
/ * *
* Controller for tmdb api integration .
* Data types are in TMDBDataTypes . For the type definitions see :
* https : //developers.themoviedb.org/3/getting-started/introduction
*
* /
2021-07-10 23:37:16 +02:00
class TMDBApiController {
2022-03-05 20:41:39 +01:00
private val classTag = javaClass . name
2021-07-10 23:37:16 +02:00
2022-03-05 20:41:39 +01:00
private val client = HttpClient {
2022-08-19 18:15:37 +02:00
install ( ContentNegotiation ) {
json ( Json {
ignoreUnknownKeys = true
} )
2022-03-05 20:41:39 +01:00
}
}
2021-12-31 16:03:15 +01:00
2021-07-10 23:37:16 +02:00
private val apiUrl = " https://api.themoviedb.org/3 "
private val apiKey = " de959cf9c07a08b5ca7cb51cda9a40c2 "
companion object {
const val imageUrl = " https://image.tmdb.org/t/p/w500 "
}
2022-03-05 20:41:39 +01:00
private suspend inline fun < reified T > request (
2021-12-31 16:03:15 +01:00
endpoint : String ,
2022-03-05 20:41:39 +01:00
parameters : List < Pair < String , Any ? > > = emptyList ( )
) : T = coroutineScope {
2021-12-31 16:03:15 +01:00
val path = " $apiUrl $endpoint "
2022-03-06 18:43:02 +01:00
val params = concatenate (
listOf ( " api_key " to apiKey , " language " to Preferences . preferredLocale . language ) ,
parameters
)
2021-12-31 16:03:15 +01:00
// TODO handle FileNotFoundException
return @coroutineScope ( Dispatchers . IO ) {
2022-03-05 20:41:39 +01:00
val response : HttpResponse = client . get ( path ) {
params . forEach {
parameter ( it . first , it . second )
}
}
2021-12-31 16:03:15 +01:00
2022-08-19 18:15:37 +02:00
response . body < T > ( )
2021-12-31 16:03:15 +01:00
}
}
2021-07-17 13:15:14 +02:00
/ * *
2022-01-02 17:51:45 +01:00
* Search for a movie in tmdb
* @param query The query text ( movie title )
* @return A TMDBSearch < TMDBSearchResultMovie > object , or
* NoneTMDBSearchMovie if nothing was found
2021-07-17 13:15:14 +02:00
* /
2022-01-02 17:51:45 +01:00
suspend fun searchMovie ( query : String ) : TMDBSearch < TMDBSearchResultMovie > {
2021-12-31 16:03:15 +01:00
val searchEndpoint = " /search/multi "
val parameters = listOf ( " query " to query , " include_adult " to false )
2021-07-10 23:37:16 +02:00
2022-03-05 20:41:39 +01:00
return try {
request ( searchEndpoint , parameters )
} catch ( ex : SerializationException ) {
Log . e ( classTag , " SerializationException in searchMovie(), with query = $query . " , ex )
NoneTMDBSearchMovie
}
2022-01-02 17:51:45 +01:00
}
/ * *
* Search for a tv show in tmdb
* @param query The query text ( tv show title )
* @return A TMDBSearch < TMDBSearchResultTVShow > object , or
* NoneTMDBSearchTVShow if nothing was found
* /
suspend fun searchTVShow ( query : String ) : TMDBSearch < TMDBSearchResultTVShow > {
val searchEndpoint = " /search/tv "
val parameters = listOf ( " query " to query , " include_adult " to false )
2022-03-05 20:41:39 +01:00
return try {
request ( searchEndpoint , parameters )
} catch ( ex : SerializationException ) {
Log . e ( classTag , " SerializationException in searchTVShow(), with query = $query . " , ex )
NoneTMDBSearchTVShow
}
2021-07-10 23:37:16 +02:00
}
2021-07-17 13:15:14 +02:00
/ * *
* Get details for a movie from tmdb
* @param movieId The tmdb ID of the movie
2021-12-31 16:03:15 +01:00
* @return A TMDBMovie object , or NoneTMDBMovie if not found
2021-07-17 13:15:14 +02:00
* /
2021-12-31 16:03:15 +01:00
suspend fun getMovieDetails ( movieId : Int ) : TMDBMovie {
val movieEndpoint = " /movie/ $movieId "
// TODO is FileNotFoundException handling needed?
2022-03-05 20:41:39 +01:00
return try {
request ( movieEndpoint )
} catch ( ex : SerializationException ) {
Log . e ( classTag , " SerializationException in getMovieDetails(), with movieId = $movieId . " , ex )
NoneTMDBMovie
}
2021-07-10 23:37:16 +02:00
}
2021-07-17 13:15:14 +02:00
/ * *
* Get details for a tv show from tmdb
* @param tvId The tmdb ID of the tv show
2021-12-31 16:03:15 +01:00
* @return A TMDBTVShow object , or NoneTMDBTVShow if not found
2021-07-17 13:15:14 +02:00
* /
2021-12-31 16:03:15 +01:00
suspend fun getTVShowDetails ( tvId : Int ) : TMDBTVShow {
val tvShowEndpoint = " /tv/ $tvId "
// TODO is FileNotFoundException handling needed?
2022-03-05 20:41:39 +01:00
return try {
request ( tvShowEndpoint )
} catch ( ex : SerializationException ) {
Log . e ( classTag , " SerializationException in getTVShowDetails(), with tvId = $tvId . " , ex )
NoneTMDBTVShow
}
2021-07-10 23:37:16 +02:00
}
2021-12-31 16:03:15 +01:00
@Suppress ( " unused " )
2021-07-17 13:15:14 +02:00
/ * *
* Get details for a tv show season from tmdb
* @param tvId The tmdb ID of the tv show
* @param seasonNumber The tmdb season number
2021-12-31 16:03:15 +01:00
* @return A TMDBTVSeason object , or NoneTMDBTVSeason if not found
2021-07-17 13:15:14 +02:00
* /
2021-12-31 16:03:15 +01:00
suspend fun getTVSeasonDetails ( tvId : Int , seasonNumber : Int ) : TMDBTVSeason {
val tvShowSeasonEndpoint = " /tv/ $tvId /season/ $seasonNumber "
// TODO is FileNotFoundException handling needed?
2022-03-05 20:41:39 +01:00
return try {
request ( tvShowSeasonEndpoint )
} catch ( ex : SerializationException ) {
Log . e ( classTag , " SerializationException in getTVSeasonDetails(), with tvId = $tvId , seasonNumber = $seasonNumber . " , ex )
NoneTMDBTVSeason
}
2021-07-10 23:37:16 +02:00
}
2021-12-31 16:03:15 +01:00
}