fix: 修复tvcat.cc选择器和播放页URL提取
- 详情页: sourceSelector/episodeGroupSelector置空,强制走fallback正确提取剧集 - 播放页: 新增fetchPlayUrlFromApi方法,通过/_fetch_p/ API获取m3u8直链 - PlayerActivity: extractFromPlayPage返回空时尝试API获取,失败再用WebView
This commit is contained in:
@@ -258,11 +258,16 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
playWithExoPlayer(directUrl)
|
playWithExoPlayer(directUrl)
|
||||||
} else if (iframeUrl != null) {
|
} else if (iframeUrl != null) {
|
||||||
playWithWebView(iframeUrl)
|
playWithWebView(iframeUrl)
|
||||||
|
} else {
|
||||||
|
val apiUrl = videoExtractor.fetchPlayUrlFromApi(ep.playUrl, config.baseUrl)
|
||||||
|
if (apiUrl != null) {
|
||||||
|
playWithExoPlayer(apiUrl)
|
||||||
} else {
|
} else {
|
||||||
playWithWebView(ep.playUrl)
|
playWithWebView(ep.playUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun savePlayHistory(episodeName: String?) {
|
private fun savePlayHistory(episodeName: String?) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ data class SitePreset(
|
|||||||
categorySelector = ".text-muted",
|
categorySelector = ".text-muted",
|
||||||
dateSelector = "",
|
dateSelector = "",
|
||||||
episodeSelector = "li.list-inline-item a",
|
episodeSelector = "li.list-inline-item a",
|
||||||
sourceSelector = "h2",
|
sourceSelector = "",
|
||||||
sourceEpisodeGroupSelector = "ul.list-unstyled",
|
sourceEpisodeGroupSelector = "",
|
||||||
iframeSelector = "iframe",
|
iframeSelector = "iframe",
|
||||||
videoSelector = "video source, video[src]"
|
videoSelector = "video source, video[src]"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package com.videoapp.tv.engine
|
|||||||
import com.videoapp.tv.data.SiteConfig
|
import com.videoapp.tv.data.SiteConfig
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.json.JSONObject
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
data class Episode(
|
data class Episode(
|
||||||
val title: String,
|
val title: String,
|
||||||
@@ -90,4 +92,30 @@ class VideoExtractor {
|
|||||||
Pair(null, null)
|
Pair(null, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun fetchPlayUrlFromApi(
|
||||||
|
playUrl: String,
|
||||||
|
baseUrl: String
|
||||||
|
): String? = withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val pattern = Regex("""(\d+)/ep(\d+)""")
|
||||||
|
val match = pattern.find(playUrl) ?: return@withContext null
|
||||||
|
val videoId = match.groupValues[1]
|
||||||
|
val epNum = match.groupValues[2]
|
||||||
|
val apiUrl = "${baseUrl.trimEnd('/')}/_fetch_p/$videoId/ep$epNum"
|
||||||
|
val conn = URL(apiUrl).openConnection()
|
||||||
|
conn.setRequestProperty("User-Agent", "Mozilla/5.0")
|
||||||
|
conn.setRequestProperty("Referer", playUrl)
|
||||||
|
conn.connectTimeout = 15000
|
||||||
|
conn.readTimeout = 15000
|
||||||
|
val json = conn.getInputStream().bufferedReader().use { it.readText() }
|
||||||
|
val obj = JSONObject(json)
|
||||||
|
val playcfgs = obj.getJSONArray("playcfgs")
|
||||||
|
if (playcfgs.length() > 0) {
|
||||||
|
playcfgs.getJSONObject(0).getString("url")
|
||||||
|
} else null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user