mirror of
https://github.com/NiciDieNase/chaosflix
synced 2024-11-26 06:00:25 +00:00
add API for VOC-Eventcalender
This commit is contained in:
parent
bd77a7bc22
commit
66c1221005
11 changed files with 133 additions and 6 deletions
|
@ -26,6 +26,7 @@ android {
|
||||||
|
|
||||||
buildConfigField "String", "STREAMING_API_BASE_URL", "\"https://streaming.media.ccc.de\""
|
buildConfigField "String", "STREAMING_API_BASE_URL", "\"https://streaming.media.ccc.de\""
|
||||||
buildConfigField "String", "STREAMING_API_OFFERS_PATH", "\"/streams/v2.json\""
|
buildConfigField "String", "STREAMING_API_OFFERS_PATH", "\"/streams/v2.json\""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|
|
@ -47,3 +47,27 @@ open class SingletonHolder2<out T, in A, in B>(creator: (A, B) -> T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class SingletonHolder3<out T, in A, in B, in C>(creator: (A, B, C) -> T) {
|
||||||
|
private var creator: ((A, B, C) -> T)? = creator
|
||||||
|
@Volatile private var instance: T? = null
|
||||||
|
|
||||||
|
fun getInstance(arg1: A, arg2: B, arg3: C): T {
|
||||||
|
val i = instance
|
||||||
|
if (i != null) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
return synchronized(this) {
|
||||||
|
val i2 = instance
|
||||||
|
if (i2 != null) {
|
||||||
|
i2
|
||||||
|
} else {
|
||||||
|
val created = creator!!(arg1, arg2, arg3)
|
||||||
|
instance = created
|
||||||
|
creator = null
|
||||||
|
created
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package de.nicidienase.chaosflix.common.mediadata.entities.eventinfo
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import de.nicidienase.chaosflix.common.mediadata.entities.eventinfo.dto.VocEventDto
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
data class EventInfo(
|
||||||
|
val name: String,
|
||||||
|
val location: String,
|
||||||
|
val streaming: Boolean?,
|
||||||
|
val startDate: Date,
|
||||||
|
val endDate: Date
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun fromVocEventDto(dto: VocEventDto): EventInfo? {
|
||||||
|
return if(dto.name == null
|
||||||
|
|| dto.location == null
|
||||||
|
|| dto.startDate == null
|
||||||
|
|| dto.endDate == null
|
||||||
|
) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
||||||
|
val startDate = dateFormat.parse(dto.startDate)
|
||||||
|
val endDate = dateFormat.parse(dto.endDate)
|
||||||
|
EventInfo(dto.name, dto.location, dto.streaming, startDate, endDate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package de.nicidienase.chaosflix.common.mediadata.entities.eventinfo.dto
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
data class EventInfoWrapperDto(
|
||||||
|
@SerializedName("voc_events") val events: Map<String, VocEventDto>,
|
||||||
|
@SerializedName("voc_events_count") val eventsCount: CountInfo
|
||||||
|
)
|
||||||
|
|
||||||
|
data class CountInfo(
|
||||||
|
val all: Int,
|
||||||
|
val with_streaming: Int,
|
||||||
|
val without_streaming: Int,
|
||||||
|
val undefined_streaming: Int
|
||||||
|
)
|
|
@ -0,0 +1,25 @@
|
||||||
|
package de.nicidienase.chaosflix.common.mediadata.entities.eventinfo.dto
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
data class VocEventDto(
|
||||||
|
val name: String?,
|
||||||
|
@SerializedName("short_name")
|
||||||
|
val shortName: String?,
|
||||||
|
val location: String?,
|
||||||
|
@SerializedName("start_date")
|
||||||
|
val startDate: String?, // Date: YYYY-MM-DD
|
||||||
|
@SerializedName("end_date")
|
||||||
|
val endDate: String?, // Date: YYYY-MM-DD
|
||||||
|
val description: String?,
|
||||||
|
@SerializedName("voc_wiki_path")
|
||||||
|
val vocWikiPath: String?,
|
||||||
|
val streaming: Boolean?,
|
||||||
|
@SerializedName("planing_status")
|
||||||
|
val planingStatus: String?,
|
||||||
|
val cases: List<String>?,
|
||||||
|
val buildup: String?, // Date: YYYY-MM-DD
|
||||||
|
val teardown: String? // Date: YYYY-MM-DD
|
||||||
|
)
|
|
@ -4,6 +4,7 @@ import android.os.Build
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import de.nicidienase.chaosflix.BuildConfig
|
import de.nicidienase.chaosflix.BuildConfig
|
||||||
import de.nicidienase.chaosflix.common.SingletonHolder2
|
import de.nicidienase.chaosflix.common.SingletonHolder2
|
||||||
|
import de.nicidienase.chaosflix.common.SingletonHolder3
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
|
@ -12,7 +13,7 @@ import okhttp3.OkHttpClient
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
class ApiFactory private constructor(apiUrl: String, cache: File? = null) {
|
class ApiFactory private constructor(apiUrl: String, eventInfoUrl: String, cache: File? = null) {
|
||||||
|
|
||||||
private val chaosflixUserAgent: String by lazy { buildUserAgent() }
|
private val chaosflixUserAgent: String by lazy { buildUserAgent() }
|
||||||
private val gsonConverterFactory: GsonConverterFactory by lazy { GsonConverterFactory.create(Gson()) }
|
private val gsonConverterFactory: GsonConverterFactory by lazy { GsonConverterFactory.create(Gson()) }
|
||||||
|
@ -39,13 +40,23 @@ class ApiFactory private constructor(apiUrl: String, cache: File? = null) {
|
||||||
.create(RecordingApi::class.java)
|
.create(RecordingApi::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
val streamingApi: StreamingApi by lazy { Retrofit.Builder()
|
val streamingApi: StreamingApi by lazy {
|
||||||
|
Retrofit.Builder()
|
||||||
.baseUrl(BuildConfig.STREAMING_API_BASE_URL)
|
.baseUrl(BuildConfig.STREAMING_API_BASE_URL)
|
||||||
.client(client)
|
.client(client)
|
||||||
.addConverterFactory(gsonConverterFactory)
|
.addConverterFactory(gsonConverterFactory)
|
||||||
.build()
|
.build()
|
||||||
.create(StreamingApi::class.java) }
|
.create(StreamingApi::class.java) }
|
||||||
|
|
||||||
|
val eventInfoApi: EventInfoApi by lazy {
|
||||||
|
Retrofit.Builder()
|
||||||
|
.baseUrl(eventInfoUrl)
|
||||||
|
.client(client)
|
||||||
|
.addConverterFactory(gsonConverterFactory)
|
||||||
|
.build()
|
||||||
|
.create(EventInfoApi::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
private val useragentInterceptor: Interceptor = Interceptor { chain ->
|
private val useragentInterceptor: Interceptor = Interceptor { chain ->
|
||||||
val requestWithUseragent = chain.request().newBuilder()
|
val requestWithUseragent = chain.request().newBuilder()
|
||||||
.header("User-Agent", chaosflixUserAgent)
|
.header("User-Agent", chaosflixUserAgent)
|
||||||
|
@ -53,7 +64,7 @@ class ApiFactory private constructor(apiUrl: String, cache: File? = null) {
|
||||||
return@Interceptor chain.proceed(requestWithUseragent)
|
return@Interceptor chain.proceed(requestWithUseragent)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : SingletonHolder2<ApiFactory, String, File?>(::ApiFactory) {
|
companion object : SingletonHolder3<ApiFactory, String, String, File?>(::ApiFactory) {
|
||||||
|
|
||||||
private const val DEFAULT_TIMEOUT = 30L
|
private const val DEFAULT_TIMEOUT = 30L
|
||||||
private const val CACHE_SIZE = 1024L * 5 // 5MB
|
private const val CACHE_SIZE = 1024L * 5 // 5MB
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package de.nicidienase.chaosflix.common.mediadata.network
|
||||||
|
|
||||||
|
import de.nicidienase.chaosflix.common.mediadata.entities.eventinfo.dto.EventInfoWrapperDto
|
||||||
|
import retrofit2.http.GET
|
||||||
|
|
||||||
|
interface EventInfoApi {
|
||||||
|
|
||||||
|
@GET("/eventkalender/events.json")
|
||||||
|
suspend fun getVocEvents(): EventInfoWrapperDto
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,10 @@ import kotlinx.coroutines.SupervisorJob
|
||||||
|
|
||||||
class ViewModelFactory private constructor(context: Context) : ViewModelProvider.Factory {
|
class ViewModelFactory private constructor(context: Context) : ViewModelProvider.Factory {
|
||||||
|
|
||||||
val apiFactory = ApiFactory.getInstance(context.resources.getString(R.string.recording_url), context.cacheDir)
|
val apiFactory = ApiFactory.getInstance(
|
||||||
|
context.resources.getString(R.string.recording_url),
|
||||||
|
context.resources.getString(R.string.event_info_url),
|
||||||
|
context.cacheDir)
|
||||||
|
|
||||||
private val supervisorJob = SupervisorJob()
|
private val supervisorJob = SupervisorJob()
|
||||||
private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO + supervisorJob)
|
private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO + supervisorJob)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="recording_url" translatable="false">https://api.media.ccc.de</string>
|
<string name="recording_url" translatable="false">https://api.media.ccc.de</string>
|
||||||
<string name="streaming_url" translatable="false">https://streaming.media.ccc.de</string>
|
<string name="streaming_url" translatable="false">https://streaming.media.ccc.de</string>
|
||||||
|
<string name="event_info_url" translatable="false">https://c3voc.de</string>
|
||||||
|
|
||||||
<string name="about_beta_url" translatable="false">https://play.google.com/apps/testing/de.nicidienase.chaosflix</string>
|
<string name="about_beta_url" translatable="false">https://play.google.com/apps/testing/de.nicidienase.chaosflix</string>
|
||||||
<string name="about_voctocat_url" translatable="false">https://morr.cc/voctocat/</string>
|
<string name="about_voctocat_url" translatable="false">https://morr.cc/voctocat/</string>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
class ChaosflixUtilTest {
|
class ChaosflixUtilTest {
|
||||||
|
|
||||||
val api = ApiFactory.getInstance("https://api.media.ccc.de", null).recordingApi
|
val api = ApiFactory.getInstance("https://api.media.ccc.de","https://c3voc.de", null).recordingApi
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGPN19() = genericTest("gpn19", false)
|
fun testGPN19() = genericTest("gpn19", false)
|
||||||
|
|
|
@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
class RecordingServiceTest {
|
class RecordingServiceTest {
|
||||||
|
|
||||||
private val apiFactory = ApiFactory.getInstance("https://api.media.ccc.de", null)
|
private val apiFactory = ApiFactory.getInstance("https://api.media.ccc.de","https://c3voc.de", null)
|
||||||
private val api = apiFactory.recordingApi
|
private val api = apiFactory.recordingApi
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
Loading…
Reference in a new issue