85 lines
3.2 KiB
Kotlin
85 lines
3.2 KiB
Kotlin
|
|
package com.videoapp.tv.engine
|
||
|
|
|
||
|
|
import com.videoapp.tv.data.SearchResult
|
||
|
|
import com.videoapp.tv.data.SiteConfig
|
||
|
|
import kotlinx.coroutines.Dispatchers
|
||
|
|
import kotlinx.coroutines.withContext
|
||
|
|
import org.jsoup.Connection
|
||
|
|
import org.jsoup.Jsoup
|
||
|
|
|
||
|
|
class NativeSearch : SearchStrategy {
|
||
|
|
|
||
|
|
override fun getName() = "NativeSearch"
|
||
|
|
|
||
|
|
override suspend fun search(
|
||
|
|
keyword: String,
|
||
|
|
config: SiteConfig,
|
||
|
|
onResult: suspend (List<SearchResult>) -> Unit,
|
||
|
|
onError: suspend (String) -> Unit
|
||
|
|
) {
|
||
|
|
try {
|
||
|
|
val results = withContext(Dispatchers.IO) {
|
||
|
|
val url = config.getFullSearchUrl()
|
||
|
|
val connection: Connection = Jsoup.connect(url)
|
||
|
|
.data(config.keywordParam, keyword)
|
||
|
|
.timeout(15000)
|
||
|
|
|
||
|
|
config.extraParams.forEach { (key, value) ->
|
||
|
|
connection.data(key, value)
|
||
|
|
}
|
||
|
|
|
||
|
|
val method = config.searchMethod.uppercase()
|
||
|
|
val doc = if (method == "GET") {
|
||
|
|
connection.get()
|
||
|
|
} else {
|
||
|
|
connection.post()
|
||
|
|
}
|
||
|
|
|
||
|
|
val items = doc.select(config.resultSelector)
|
||
|
|
val resultsList = mutableListOf<SearchResult>()
|
||
|
|
|
||
|
|
for (item in items) {
|
||
|
|
try {
|
||
|
|
val titleEl = item.selectFirst(config.titleSelector) ?: continue
|
||
|
|
val linkEl = item.selectFirst(config.linkSelector)
|
||
|
|
val coverEl = item.selectFirst(config.coverSelector)
|
||
|
|
val categoryEl = item.selectFirst(config.categorySelector)
|
||
|
|
val dateEl = item.selectFirst(config.dateSelector)
|
||
|
|
|
||
|
|
val title = titleEl.text().trim()
|
||
|
|
val detailUrl = linkEl?.attr("href")?.trim() ?: ""
|
||
|
|
val coverUrl = coverEl?.attr("src")?.trim() ?: ""
|
||
|
|
val category = categoryEl?.text()?.trim() ?: ""
|
||
|
|
val date = dateEl?.text()?.trim() ?: ""
|
||
|
|
|
||
|
|
if (title.isNotEmpty() && detailUrl.isNotEmpty()) {
|
||
|
|
resultsList.add(
|
||
|
|
SearchResult(
|
||
|
|
title = title,
|
||
|
|
coverUrl = if (coverUrl.startsWith("http")) coverUrl
|
||
|
|
else config.baseUrl.trimEnd('/') + "/" + coverUrl.trimStart('/'),
|
||
|
|
detailUrl = if (detailUrl.startsWith("http")) detailUrl
|
||
|
|
else config.baseUrl.trimEnd('/') + "/" + detailUrl.trimStart('/'),
|
||
|
|
category = category,
|
||
|
|
date = date
|
||
|
|
)
|
||
|
|
)
|
||
|
|
}
|
||
|
|
} catch (e: Exception) {
|
||
|
|
// skip malformed items
|
||
|
|
}
|
||
|
|
}
|
||
|
|
resultsList
|
||
|
|
}
|
||
|
|
|
||
|
|
if (results.isEmpty()) {
|
||
|
|
onError("未找到结果")
|
||
|
|
} else {
|
||
|
|
onResult(results)
|
||
|
|
}
|
||
|
|
} catch (e: Exception) {
|
||
|
|
onError("NativeSearch 失败: ${e.message}")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|