feat(en/aniplay): new provider pahe implemented (somewhat) #590

Merged
JosefFStraka merged 2 commits from aniplay into main 2025-01-25 20:18:38 -06:00
3 changed files with 105 additions and 21 deletions

View file

@ -2,7 +2,7 @@ ext {
extName = 'AniPlay'
extClass = '.AniPlay'
themePkg = 'anilist'
overrideVersionCode = 7
overrideVersionCode = 8
}
apply from: "$rootDir/common.gradle"

View file

@ -248,22 +248,29 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
when (extra.source.lowercase()) {
"yuki" -> {
val data = sourcesString.parseAs<VideoSourceResponseYuki>()
return processEpisodeDataYuki(
EpisodeDataYuki(
source = extra.source,
language = language,
response = data,
response = sourcesString.parseAs<VideoSourceResponseYuki>(),
),
)
}
"pahe" -> {
return processEpisodeDataPahe(
EpisodeDataPahe(
source = extra.source,
language = language,
response = sourcesString.parseAs<VideoSourceResponsePahe>(),
),
)
}
else -> {
val data = sourcesString.parseAs<VideoSourceResponse>()
return processEpisodeData(
EpisodeData(
source = extra.source,
language = language,
response = data,
response = sourcesString.parseAs<VideoSourceResponse>(),
),
)
}
@ -301,6 +308,36 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
return emptyList()
}
private fun processEpisodeDataPahe(episodeData: EpisodeDataPahe): List<Video> {
val defaultSource = episodeData.response.sources?.firstOrNull {
it.quality in listOf("default", "auto")
} ?: return emptyList()
val subtitles = episodeData.response.subtitles
?.filter { it.lang?.lowercase() != "thumbnails" }
?.filter { it.url.isNullOrEmpty().not() }
?.map { Track(it.url ?: throw Exception("To be null or not to be"), it.lang ?: "Unk") }
?: emptyList()
val serverName = getServerName(episodeData.source)
val typeName = when {
subtitles.isNotEmpty() -> "SoftSub"
else -> getTypeName(episodeData.language)
}
try {
return playlistUtils.extractFromHls(
playlistUrl = defaultSource.url,
videoNameGen = { quality -> "$serverName - $quality - $typeName" },
subtitleList = subtitles,
)
} catch (e: Exception) {
Log.e("AniPlay", "processEpisodeDataPahe extractFromHls Error (\"$serverName - $typeName\"): $e")
}
return emptyList()
}
private fun processEpisodeData(episodeData: EpisodeData): List<Video> {
val defaultSource = episodeData.response.sources?.firstOrNull {
it.quality in listOf("default", "auto")
@ -508,8 +545,8 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
private const val PREF_DOMAIN_DEFAULT = "aniplaynow.live"
private const val PREF_SERVER_KEY = "server"
private val PREF_SERVER_ENTRIES = arrayOf("Kuro", "Anya", "Yuki")
private val PREF_SERVER_ENTRY_VALUES = arrayOf("kuro", "anya", "yuki")
private val PREF_SERVER_ENTRIES = arrayOf("Kuro", "Anya", "Yuki", "Pahe")
private val PREF_SERVER_ENTRY_VALUES = arrayOf("kuro", "anya", "yuki", "pahe")
private const val PREF_SERVER_DEFAULT = "kuro"
private const val PREF_QUALITY_KEY = "quality"

View file

@ -21,6 +21,14 @@ data class EpisodeListResponse(
)
}
// Provider else
@Serializable
data class EpisodeData(
val source: String,
val language: String,
val response: VideoSourceResponse,
)
@Serializable
data class VideoSourceResponse(
val sources: List<Source>?,
@ -39,6 +47,14 @@ data class VideoSourceResponse(
)
}
// Provider Yuki
@Serializable
data class EpisodeDataYuki(
val source: String,
val language: String,
val response: VideoSourceResponseYuki,
)
@Serializable
data class VideoSourceResponseYuki(
val sources: List<Source>?,
@ -61,6 +77,51 @@ data class VideoSourceResponseYuki(
)
}
// Provider Pahe
@Serializable
data class EpisodeDataPahe(
val source: String,
val language: String,
val response: VideoSourceResponsePahe,
)
@Serializable
data class VideoSourceResponsePahe(
val sources: List<Source>?,
val audio: List<Audio>?,
val intro: Timestamp?,
val outro: Timestamp?,
val subtitles: List<Subtitle>?,
) {
@Serializable
data class Source(
val url: String,
val quality: String?,
)
@Serializable
data class Audio(
val file: String,
val label: String?,
val kind: String?,
val default: Boolean?,
)
@Serializable
data class Timestamp(
val start: Int?,
val end: Int?,
)
@Serializable
data class Subtitle(
val url: String?,
val lang: String?,
)
}
// Extra
@Serializable
data class EpisodeExtra(
val source: String,
@ -68,17 +129,3 @@ data class EpisodeExtra(
val episodeId: String,
val hasDub: Boolean,
)
@Serializable
data class EpisodeData(
val source: String,
val language: String,
val response: VideoSourceResponse,
)
@Serializable
data class EpisodeDataYuki(
val source: String,
val language: String,
val response: VideoSourceResponseYuki,
)