PurayMoe: Fix video extractor (#966)

* PurayMoe: Fix video extractor and add a new config

* PurayMoe: Bump version
This commit is contained in:
Claudemirovsky
2022-10-22 06:22:58 -03:00
committed by GitHub
parent 7beefea8bf
commit aaf4c6af4c
3 changed files with 86 additions and 48 deletions

View File

@ -6,11 +6,8 @@ ext {
extName = 'Puray.moe'
pkgNameSuffix = 'pt.puraymoe'
extClass = '.PurayMoe'
extVersionCode = 3
extVersionCode = 4
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -4,6 +4,7 @@ import android.app.Application
import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.animeextension.pt.puraymoe.dto.AnimeDto
import eu.kanade.tachiyomi.animeextension.pt.puraymoe.dto.EpisodeDataDto
import eu.kanade.tachiyomi.animeextension.pt.puraymoe.dto.MinimalEpisodeDto
@ -29,7 +30,6 @@ import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.lang.Exception
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Locale
@ -80,7 +80,7 @@ class PurayMoe : ConfigurableAnimeSource, AnimeHttpSource() {
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
val seasonsList: SeasonListDto = getSeasonList(anime)
val showOnly = preferences.getString(CONF_SHOW_ONLY, null) ?: ""
val showOnly = preferences.getString(PREF_SHOW_ONLY_KEY, null) ?: ""
val dub_item = ANIME_TYPES_VALUES.elementAt(1)
val sub_item = ANIME_TYPES_VALUES.last()
var filteredSeasons = seasonsList.seasons.filter {
@ -118,9 +118,9 @@ class PurayMoe : ConfigurableAnimeSource, AnimeHttpSource() {
return episodesData.episodes.map {
val episode = SEpisode.create()
episode.name = "Temp $seasonNumber ($format) EP ${it.ep_number}: ${it.name}"
episode.episode_number = try {
episode.episode_number = runCatching {
it.ep_number.toFloat()
} catch (e: NumberFormatException) { 0F }
}.getOrNull() ?: 0F
episode.url = it.id.toString()
episode.date_upload = it.release_date.toDate()
episode
@ -129,15 +129,26 @@ class PurayMoe : ConfigurableAnimeSource, AnimeHttpSource() {
// ============================ Video Links =============================
override fun videoListRequest(episode: SEpisode): Request =
GET("$API_URL/episodios/${episode.url}/m3u8/mp4/")
override fun videoListRequest(episode: SEpisode): Request {
val url = "$API_URL/episodios/${episode.url}/m3u8"
val usePlaylist = preferences.getBoolean(PREF_USE_PLAYLIST_KEY, true)
return if (usePlaylist) GET(url) else GET("$url/mp4/")
}
override fun videoListParse(response: Response): List<Video> {
val episodeObject = response.parseAs<MinimalEpisodeDto>()
return episodeObject.streams!!.map {
val quality = "${it.quality.last()}p"
Video(it.url, quality, it.url)
}.toList()
val usePlaylist = preferences.getBoolean(PREF_USE_PLAYLIST_KEY, true)
return if (usePlaylist) {
client.newCall(GET(episodeObject.url))
.execute()
.toVideoList()
} else {
episodeObject.streams?.map {
val quality = "${it.quality.last()}p"
Video(it.url, quality, it.url)
} ?: emptyList<Video>()
}
}
// =============================== Search ===============================
@ -219,7 +230,7 @@ class PurayMoe : ConfigurableAnimeSource, AnimeHttpSource() {
override fun latestUpdatesParse(response: Response): AnimesPage {
val parsedData = response.parseAs<List<MinimalEpisodeDto>>()
val animes = parsedData.map(::getAnimeFromEpisode).toList()
val animes = parsedData.map(::getAnimeFromEpisode)
return AnimesPage(animes, false)
}
@ -234,25 +245,11 @@ class PurayMoe : ConfigurableAnimeSource, AnimeHttpSource() {
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val videoQualityPref = ListPreference(screen.context).apply {
key = CONF_PREFERRED_QUALITY
title = "Qualidade preferida"
entries = QUALITY_LIST
entryValues = QUALITY_LIST
setDefaultValue(QUALITY_LIST.last())
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = findIndexOfValue(selected)
val entry = entryValues[index] as String
preferences.edit().putString(key, entry).commit()
}
}
val showOnlyPref = ListPreference(screen.context).apply {
key = CONF_SHOW_ONLY
title = "Mostrar apenas episódios:"
entries = ANIME_TYPES
entryValues = ANIME_TYPES_VALUES
setDefaultValue(ANIME_TYPES_VALUES.first())
key = PREF_QUALITY_KEY
title = PREF_QUALITY_TITLE
entries = PREF_QUALITY_VALUES
entryValues = PREF_QUALITY_VALUES
setDefaultValue("720p")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
@ -262,8 +259,35 @@ class PurayMoe : ConfigurableAnimeSource, AnimeHttpSource() {
}
}
val showOnlyPref = ListPreference(screen.context).apply {
key = PREF_SHOW_ONLY_KEY
title = PREF_SHOW_ONLY_TITLE
entries = ANIME_TYPES_ENTRIES
entryValues = ANIME_TYPES_VALUES
setDefaultValue("")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = findIndexOfValue(selected)
val entry = entryValues[index] as String
preferences.edit().putString(key, entry).commit()
}
}
val usePlaylistPref = SwitchPreferenceCompat(screen.context).apply {
key = PREF_USE_PLAYLIST_KEY
title = PREF_USE_PLAYLIST_TITLE
setDefaultValue(true)
setOnPreferenceChangeListener { _, newValue ->
val checkValue = newValue as Boolean
preferences.edit().putBoolean(key, checkValue).commit()
}
}
screen.addPreference(videoQualityPref)
screen.addPreference(showOnlyPref)
screen.addPreference(usePlaylistPref)
}
// ============================= Utilities ==============================
@ -273,18 +297,29 @@ class PurayMoe : ConfigurableAnimeSource, AnimeHttpSource() {
return json.decodeFromString(responseBody)
}
private fun String.toDate(): Long {
return try {
DATE_FORMATTER.parse(this)?.time ?: 0L
} catch (e: ParseException) {
0L
private fun Response.toVideoList(): List<Video> {
val responseBody = body?.string().orEmpty()
val separator = "#EXT-X-STREAM-INF:"
return responseBody.substringAfter(separator).split(separator).map {
val quality = it.substringAfter("RESOLUTION=")
.substringAfter("x")
.substringBefore("\n")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
Video(videoUrl, quality, videoUrl)
}
}
private fun String.toDate(): Long {
return runCatching {
DATE_FORMATTER.parse(this)?.time ?: 0L
}.getOrNull() ?: 0L
}
private fun String.getId(): String = this.substringAfterLast("/")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString(CONF_PREFERRED_QUALITY, null)
val quality = preferences.getString(PREF_QUALITY_KEY, null)
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
@ -302,23 +337,28 @@ class PurayMoe : ConfigurableAnimeSource, AnimeHttpSource() {
}
companion object {
private const val API_URL = "https://api.puray.moe"
private const val ACCEPT_LANGUAGE = "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7"
private const val CONF_PREFERRED_QUALITY = "preferred_quality"
private const val CONF_SHOW_ONLY = "show_only"
private val DATE_FORMATTER by lazy {
SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
}
private val QUALITY_LIST = arrayOf(
private const val API_URL = "https://api.puray.moe"
private const val ACCEPT_LANGUAGE = "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7"
private const val PREF_QUALITY_KEY = "preferred_quality"
private const val PREF_QUALITY_TITLE = "Qualidade preferida"
private val PREF_QUALITY_VALUES = arrayOf(
"240p", "360p",
"480p", "720p", "1080p"
)
private val ANIME_TYPES = arrayOf("Todos", "Dublados", "Legendados")
private const val PREF_SHOW_ONLY_KEY = "show_only"
private const val PREF_SHOW_ONLY_TITLE = "Mostrar apenas episódios:"
private val ANIME_TYPES_ENTRIES = arrayOf("Todos", "Dublados", "Legendados")
private val ANIME_TYPES_VALUES = arrayOf("", "dub", "sub")
private const val PREF_USE_PLAYLIST_KEY = "use_m3u8_playlist"
private const val PREF_USE_PLAYLIST_TITLE = "Usar/Ativar playlist M3U8(HLS)"
const val PREFIX_SEARCH = "id:"
}
}

View File

@ -66,7 +66,8 @@ data class EpisodeDto(
data class MinimalEpisodeDto(
@SerialName("temporada")
val season: MinimalSeasonDto? = null,
val streams: List<VideoDto>? = null
val streams: List<VideoDto>? = null,
val url: String = ""
)
@Serializable