Fix fetching video data and add new setting to filter by specific uploaders by ID (#462)
This commit is contained in:
parent
7b2afcf2ad
commit
7fcde32166
2 changed files with 102 additions and 20 deletions
|
@ -1,7 +1,7 @@
|
||||||
ext {
|
ext {
|
||||||
extName = 'Rule34Video'
|
extName = 'Rule34Video'
|
||||||
extClass = '.Rule34Video'
|
extClass = '.Rule34Video'
|
||||||
extVersionCode = 8
|
extVersionCode = 9
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.animeextension.en.rule34video
|
package eu.kanade.tachiyomi.animeextension.en.rule34video
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||||
|
@ -41,7 +43,21 @@ class Rule34Video : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================== Popular ===============================
|
// ============================== Popular ===============================
|
||||||
override fun popularAnimeRequest(page: Int) = GET("$baseUrl/latest-updates/$page/")
|
override fun popularAnimeRequest(page: Int): Request {
|
||||||
|
return if (preferences.getBoolean(PREF_UPLOADER_FILTER_ENABLED_KEY, false)) {
|
||||||
|
val uploaderId = preferences.getString(PREF_UPLOADER_ID_KEY, "") ?: ""
|
||||||
|
if (uploaderId.isNotBlank()) {
|
||||||
|
val url = "$baseUrl/members/$uploaderId/videos/?mode=async&function=get_block&block_id=list_videos_uploaded_videos&sort_by=&from_videos=$page"
|
||||||
|
Log.e("Rule34Video", "Loading popular videos from uploader ID: $uploaderId, page: $page, URL: $url")
|
||||||
|
GET(url)
|
||||||
|
} else {
|
||||||
|
Log.e("Rule34Video", "Uploader filter enabled but ID is blank, loading latest updates.")
|
||||||
|
GET("$baseUrl/latest-updates/$page/")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GET("$baseUrl/latest-updates/$page/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun popularAnimeSelector() = "div.item.thumb"
|
override fun popularAnimeSelector() = "div.item.thumb"
|
||||||
|
|
||||||
|
@ -102,21 +118,60 @@ class Rule34Video : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||||
|
|
||||||
// =========================== Anime Details ============================
|
// =========================== Anime Details ============================
|
||||||
override fun animeDetailsParse(document: Document) = SAnime.create().apply {
|
override fun animeDetailsParse(document: Document) = SAnime.create().apply {
|
||||||
title = document.selectFirst("h1.title_video")!!.text()
|
title = document.selectFirst("h1.title_video")?.text().toString()
|
||||||
val info = document.selectFirst("#tab_video_info")!!
|
|
||||||
author = info.select("div.label:contains(Artist:) + a").eachText().joinToString()
|
val infoRow = document.selectFirst("div.info.row")
|
||||||
|
val detailRows = document.select("div.row")
|
||||||
|
|
||||||
|
val artistElement = detailRows.select("div.col:has(div.label:contains(Artist)) a.item span.name").firstOrNull()
|
||||||
|
author = artistElement?.text().orEmpty()
|
||||||
|
|
||||||
description = buildString {
|
description = buildString {
|
||||||
info.selectFirst("div.label:contains(Description:) > em")?.text()?.also { append("$it\n") }
|
detailRows.select("div.row:has(div.label > em) > div.label > em").html()
|
||||||
info.selectFirst("i.icon-eye + span")?.text()?.also { append("\nViews : ${it.replace(" ", ",")}") }
|
.replace("<br>", "\n") // Ensure single <br> tags are followed by a newline
|
||||||
info.selectFirst("i.icon-clock + span")?.text()?.also { append("\nDuration : $it") }
|
.let { text ->
|
||||||
document.select("div.label:contains(Download) ~ a.tag_item")
|
append(text)
|
||||||
.eachText()
|
|
||||||
.joinToString { it.substringAfter(" ") }
|
|
||||||
.also { append("\nQuality : $it") }
|
|
||||||
}
|
}
|
||||||
genre = document.select("div.label:contains(Tags) ~ a.tag_item:not(:contains(Suggest))")
|
append("\n\n") // Add extra spacing
|
||||||
|
|
||||||
|
infoRow?.selectFirst("div.item_info:nth-child(1) > span")?.text()?.let {
|
||||||
|
append("Uploaded: $it\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
val artist = detailRows.select("div.col:has(div.label:contains(Artist)) a.item span.name")
|
||||||
.eachText()
|
.eachText()
|
||||||
.joinToString()
|
.joinToString()
|
||||||
|
if (artist.isNotEmpty()) {
|
||||||
|
append("Artists: $artist\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
val categories = detailRows.select("div.col:has(div.label:contains(Categories)) a.item span")
|
||||||
|
.eachText()
|
||||||
|
.joinToString()
|
||||||
|
if (categories.isNotEmpty()) {
|
||||||
|
append("Categories: $categories\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
val uploader = detailRows.select("div.col:has(div.label:contains(Uploaded by)) a.item").text()
|
||||||
|
if (uploader.isNotEmpty()) {
|
||||||
|
append("Uploader: $uploader\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
infoRow?.select("div.item_info:nth-child(2) > span")?.text()?.let {
|
||||||
|
val views = it.substringBefore(" ").replace(",", "")
|
||||||
|
append("Views: $views\n")
|
||||||
|
}
|
||||||
|
infoRow?.select("div.item_info:nth-child(3) > span")?.text()?.let { append("Duration: $it\n") }
|
||||||
|
document.select("div.row:has(div.label:contains(Download)) a.tag_item")
|
||||||
|
.eachText()
|
||||||
|
.joinToString { it.substringAfter(" ") }
|
||||||
|
.also { append("Quality: $it") }
|
||||||
|
}
|
||||||
|
|
||||||
|
genre = document.select("div.row_spacer:has(div.label:contains(Tags)) a.tag_item:not(:contains(Suggest))")
|
||||||
|
.eachText()
|
||||||
|
.joinToString()
|
||||||
|
|
||||||
status = SAnime.COMPLETED
|
status = SAnime.COMPLETED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +241,24 @@ class Rule34Video : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||||
|
|
||||||
// ============================== Settings ==============================
|
// ============================== Settings ==============================
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||||
|
SwitchPreferenceCompat(screen.context).apply {
|
||||||
|
key = PREF_UPLOADER_FILTER_ENABLED_KEY
|
||||||
|
title = "Filter by Uploader"
|
||||||
|
summary = "Load videos only from the specified uploader ID."
|
||||||
|
setDefaultValue(false)
|
||||||
|
}.also(screen::addPreference)
|
||||||
|
|
||||||
|
EditTextPreference(screen.context).apply {
|
||||||
|
key = PREF_UPLOADER_ID_KEY
|
||||||
|
title = "Uploader ID"
|
||||||
|
summary = "Enter the ID of the uploader (e.g., 98965). Requires \"Filter by Uploader\" to be enabled."
|
||||||
|
dialogTitle = "Enter Uploader ID"
|
||||||
|
var dependency = PREF_UPLOADER_FILTER_ENABLED_KEY
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
newValue?.toString().isNullOrBlank().not()
|
||||||
|
}
|
||||||
|
}.also(screen::addPreference)
|
||||||
|
|
||||||
ListPreference(screen.context).apply {
|
ListPreference(screen.context).apply {
|
||||||
key = PREF_QUALITY_KEY
|
key = PREF_QUALITY_KEY
|
||||||
title = PREF_QUALITY_TITLE
|
title = PREF_QUALITY_TITLE
|
||||||
|
@ -218,7 +291,12 @@ class Rule34Video : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||||
return tagList.toTypedArray()
|
return tagList.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
override fun getFilterList(): AnimeFilterList = if (preferences.getBoolean(PREF_UPLOADER_FILTER_ENABLED_KEY, false) &&
|
||||||
|
preferences.getString(PREF_UPLOADER_ID_KEY, "")?.isNotBlank() == true
|
||||||
|
) {
|
||||||
|
AnimeFilterList() // If uploader filter is enabled and ID is set, show no other filters
|
||||||
|
} else {
|
||||||
|
AnimeFilterList(
|
||||||
OrderFilter(),
|
OrderFilter(),
|
||||||
CategoryBy(),
|
CategoryBy(),
|
||||||
AnimeFilter.Separator(),
|
AnimeFilter.Separator(),
|
||||||
|
@ -226,6 +304,7 @@ class Rule34Video : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||||
TagFilter(),
|
TagFilter(),
|
||||||
TagSearch(tagsResults(tagDocument)),
|
TagSearch(tagsResults(tagDocument)),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private class TagFilter : AnimeFilter.Text("Click \"reset\" without any text to load all A-Z tags.", "")
|
private class TagFilter : AnimeFilter.Text("Click \"reset\" without any text to load all A-Z tags.", "")
|
||||||
|
|
||||||
|
@ -267,5 +346,8 @@ class Rule34Video : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||||
private const val PREF_QUALITY_TITLE = "Preferred quality"
|
private const val PREF_QUALITY_TITLE = "Preferred quality"
|
||||||
private const val PREF_QUALITY_DEFAULT = "1080p"
|
private const val PREF_QUALITY_DEFAULT = "1080p"
|
||||||
private val PREF_QUALITY_ENTRIES = arrayOf("2160p", "1080p", "720p", "480p", "360p")
|
private val PREF_QUALITY_ENTRIES = arrayOf("2160p", "1080p", "720p", "480p", "360p")
|
||||||
|
|
||||||
|
private const val PREF_UPLOADER_FILTER_ENABLED_KEY = "uploader_filter_enabled"
|
||||||
|
private const val PREF_UPLOADER_ID_KEY = "uploader_id"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue