Compare commits
No commits in common. "multiThread" and "bd" have entirely different histories.
multiThrea
...
bd
|
|
@ -1,80 +1,27 @@
|
|||
name: Spider Jar Gen CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "multiThread" ]
|
||||
workflow_dispatch:
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'jetbrains'
|
||||
cache: gradle
|
||||
|
||||
- name: Grant execute permission to gradlew
|
||||
run: chmod +x ./gradlew
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew app:buildCustomSpiderJar
|
||||
|
||||
|
||||
- name: Add & Commit
|
||||
uses: EndBug/add-and-commit@v9.1.4
|
||||
with:
|
||||
default_author: github_actions
|
||||
message: 'update spider jar and json'
|
||||
add: "['./jar/custom_spider.jar', './jar/custom_spider.jar.md5','./json/index.json']"
|
||||
|
||||
- name: upload json
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||
with:
|
||||
# ftp server
|
||||
server: ftpupload.net
|
||||
# ftp username
|
||||
username: mseet_40633048
|
||||
# ftp password
|
||||
password: ${{ secrets.FTP_PWD }}
|
||||
# Server port to connect to (read your web hosts docs)
|
||||
port: 21
|
||||
# protocol to deploy with - ftp, ftps, or ftps-legacy
|
||||
protocol: ftp
|
||||
# Folder to upload from, must end with trailing slash /
|
||||
local-dir: ${{ github.workspace }}/json/
|
||||
# Path to upload to on the server. Must end with trailing slash /
|
||||
server-dir: htdocs/json/
|
||||
# Deletes ALL contents of server-dir, even items in excluded with exclude argument
|
||||
dangerous-clean-slate: true
|
||||
exclude: |
|
||||
**/js/**
|
||||
|
||||
- name: upload jar
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||
with:
|
||||
# ftp server
|
||||
server: ftpupload.net
|
||||
# ftp username
|
||||
username: mseet_40633048
|
||||
# ftp password
|
||||
password: ${{ secrets.FTP_PWD }}
|
||||
# Server port to connect to (read your web hosts docs)
|
||||
port: 21
|
||||
# protocol to deploy with - ftp, ftps, or ftps-legacy
|
||||
protocol: ftp
|
||||
# Folder to upload from, must end with trailing slash /
|
||||
local-dir: ${{ github.workspace }}/jar/
|
||||
# Path to upload to on the server. Must end with trailing slash /
|
||||
server-dir: htdocs/jar/
|
||||
# Deletes ALL contents of server-dir, even items in excluded with exclude argument
|
||||
dangerous-clean-slate: true
|
||||
|
||||
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 21
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'adopt'
|
||||
cache: gradle
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./build.bat ec
|
||||
|
||||
- name: Update spider jar
|
||||
uses: EndBug/add-and-commit@v7
|
||||
with:
|
||||
default_author: github_actions
|
||||
message: 'update spider jar'
|
||||
add: "['./jar/custom_spider.jar', './jar/custom_spider.jar.md5']"
|
||||
|
|
|
|||
123
app/build.gradle
123
app/build.gradle
|
|
@ -96,128 +96,5 @@ dependencies {
|
|||
// implementation(ext: 'aar', name: 'quickjs', group: 'fongmi', version: 'release')
|
||||
// api 'wang.harlon.quickjs:wrapper-android:2.0.0'
|
||||
|
||||
task buildCustomSpiderJar {
|
||||
doLast {
|
||||
def workDir = file("${projectDir}").parentFile
|
||||
def spiderJarDir = file("$workDir/jar/spider.jar")
|
||||
def smaliOutputDir = file("$workDir/jar/Smali_classes")
|
||||
def customSpiderJar = file("$workDir/jar/custom_spider.jar")
|
||||
def baksmaliJar = file("$workDir/jar/3rd/baksmali-2.5.2.jar")
|
||||
def apktoolJar = file("$workDir/jar/3rd/apktool_2.4.1.jar")
|
||||
def classesDex = file("$workDir/app/build/intermediates/dex/release/minifyReleaseWithR8/classes.dex")
|
||||
def indexJsonFile = file("$workDir/json/index.json")
|
||||
|
||||
// 删除旧文件
|
||||
if (customSpiderJar.exists()) {
|
||||
customSpiderJar.delete()
|
||||
}
|
||||
if (smaliOutputDir.exists()) {
|
||||
delete(smaliOutputDir)
|
||||
}
|
||||
|
||||
// 使用 baksmali 反编译 classes.dex
|
||||
javaexec {
|
||||
main = "-jar"
|
||||
args = [
|
||||
baksmaliJar.absolutePath,
|
||||
"d",
|
||||
classesDex.absolutePath,
|
||||
"-o",
|
||||
smaliOutputDir.absolutePath
|
||||
]
|
||||
}
|
||||
|
||||
// 删除 spider.jar 中的旧目录
|
||||
def targetDirs = [
|
||||
file("$spiderJarDir/smali/com/github/catvod/spider"),
|
||||
file("$spiderJarDir/smali/com/github/catvod/parser"),
|
||||
file("$spiderJarDir/smali/com/github/catvod/js")
|
||||
]
|
||||
targetDirs.each { dir ->
|
||||
if (dir.exists()) {
|
||||
delete(dir)
|
||||
}
|
||||
}
|
||||
|
||||
// 创建目标目录(如果不存在)
|
||||
def targetBaseDir = file("$spiderJarDir/smali/com/github/catvod")
|
||||
if (!targetBaseDir.exists()) {
|
||||
targetBaseDir.mkdirs()
|
||||
}
|
||||
|
||||
// 移动反编译后的目录
|
||||
def sourceDirs = [
|
||||
file("$smaliOutputDir/com/github/catvod/spider"),
|
||||
file("$smaliOutputDir/com/github/catvod/parser"),
|
||||
file("$smaliOutputDir/com/github/catvod/js")
|
||||
]
|
||||
def targetPaths = [
|
||||
file("$targetBaseDir/spider"),
|
||||
file("$targetBaseDir/parser"),
|
||||
file("$targetBaseDir/js")
|
||||
]
|
||||
|
||||
sourceDirs.eachWithIndex { src, idx ->
|
||||
if (src.exists()) {
|
||||
copy {
|
||||
from src
|
||||
into targetPaths[idx]
|
||||
}
|
||||
delete(src)
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 apktool 打包
|
||||
javaexec {
|
||||
main = "-jar"
|
||||
args = [
|
||||
apktoolJar.absolutePath,
|
||||
"b",
|
||||
spiderJarDir.absolutePath,
|
||||
"-c"
|
||||
]
|
||||
}
|
||||
|
||||
// 移动生成的 dex.jar 到 custom_spider.jar
|
||||
def distJar = file("$spiderJarDir/dist/dex.jar")
|
||||
if (distJar.exists()) {
|
||||
copy {
|
||||
from distJar
|
||||
into file("$workDir/jar")
|
||||
rename "dex.jar", "custom_spider.jar"
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 MD5 校验文件
|
||||
def md5File = file("$workDir/jar/custom_spider.jar.md5")
|
||||
def md5 = java.security.MessageDigest.getInstance("MD5").digest(customSpiderJar.bytes).encodeHex().toString()
|
||||
md5File.text = md5
|
||||
|
||||
// 替换index.json md5 内容
|
||||
def indexJsonContent = indexJsonFile.text
|
||||
|
||||
// 使用正则表达式替换 spider 字段中的 MD5 值
|
||||
def updatedContent = indexJsonContent.replaceAll(
|
||||
/("spider":\s*"[^;]+;md5;)[^"]+"/,
|
||||
'$1' + md5 + '"'
|
||||
)
|
||||
|
||||
// 写回文件
|
||||
indexJsonFile.write(updatedContent)
|
||||
|
||||
// 清理临时目录
|
||||
delete(
|
||||
"$spiderJarDir/build",
|
||||
"$spiderJarDir/smali",
|
||||
"$spiderJarDir/dist",
|
||||
smaliOutputDir
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
tasks.named('buildCustomSpiderJar') {
|
||||
dependsOn 'assembleRelease'
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.github.catvod.api;
|
||||
|
||||
|
||||
|
||||
import com.github.catvod.bean.BD.Cache;
|
||||
import com.github.catvod.bean.yun.User;
|
||||
import com.github.catvod.utils.Path;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class BaiDuYunHandler {
|
||||
|
||||
private final Cache cache;
|
||||
|
||||
public File getCache() {
|
||||
return Path.tv("bd");
|
||||
}
|
||||
|
||||
private BaiDuYunHandler() {
|
||||
cache = Cache.objectFrom(Path.read(getCache()));
|
||||
}
|
||||
|
||||
private static class Loader {
|
||||
static volatile BaiDuYunHandler INSTANCE = new BaiDuYunHandler();
|
||||
}
|
||||
|
||||
public static BaiDuYunHandler get() {
|
||||
return BaiDuYunHandler.Loader.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
public String getToken() {
|
||||
User user = cache.getUser();
|
||||
return user.getCookie();
|
||||
//return "cGM6MTg4OTY3ODE2MDE6eTM1Tjd1dG58MXxSQ1N8MTc1NDQ2OTgwNzEyOXxzMlN0T1VEV3lOVmF5V3pNbGFfM2tJbVp1ZmlqSHBqaEhTSzVyNHZqVXNRLmlhV3loSUxHNDFkMUI5N1BqXzhWN0dtVWtKLnBTclhpNGpZU1EuTGZWMTV3MVFoZmNpcEVoZkxUV2tvYjB0bkFTYV9RTUhhaHhveWx6YkdmcEhQdjNCS1lrbnp1LkxaWDdKOE40YkNNRjkzT3piNmx2Y0d3TWdVUkl5b18ubVUt";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,262 +0,0 @@
|
|||
package com.github.catvod.api
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.text.TextUtils
|
||||
import android.view.Gravity
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import com.github.catvod.bean.BD.Cache
|
||||
import com.github.catvod.bean.yun.User
|
||||
import com.github.catvod.crawler.SpiderDebug
|
||||
import com.github.catvod.net.OkHttp
|
||||
import com.github.catvod.spider.Init
|
||||
import com.github.catvod.utils.*
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import org.apache.commons.lang3.StringEscapeUtils
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.UnsupportedEncodingException
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.concurrent.Volatile
|
||||
|
||||
|
||||
class BaiDuYunHandler private constructor() {
|
||||
private val cache: Cache
|
||||
private var service: ScheduledExecutorService? = null
|
||||
private var dialog: AlertDialog? = null
|
||||
private var cookies = ""
|
||||
private val headers = mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Linux; Android 12; SM-X800) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.40 Safari/537.36",
|
||||
"Accept" to "application/json, text/plain, */*",
|
||||
"Content-Type" to "application/x-www-form-urlencoded",
|
||||
"Origin" to "https://pan.baidu.com",
|
||||
"Referer" to "https://pan.baidu.com/"
|
||||
)
|
||||
|
||||
fun getCache(): File {
|
||||
return Path.tv("bd")
|
||||
}
|
||||
|
||||
init {
|
||||
cache = Cache.objectFrom(Path.read(getCache()))
|
||||
}
|
||||
|
||||
private object Loader {
|
||||
@Volatile
|
||||
var INSTANCE: BaiDuYunHandler = BaiDuYunHandler()
|
||||
}
|
||||
|
||||
val token: String
|
||||
get() {
|
||||
val user: User = cache.getUser()
|
||||
return user.getCookie()
|
||||
//return "cGM6MTg4OTY3ODE2MDE6eTM1Tjd1dG58MXxSQ1N8MTc1NDQ2OTgwNzEyOXxzMlN0T1VEV3lOVmF5V3pNbGFfM2tJbVp1ZmlqSHBqaEhTSzVyNHZqVXNRLmlhV3loSUxHNDFkMUI5N1BqXzhWN0dtVWtKLnBTclhpNGpZU1EuTGZWMTV3MVFoZmNpcEVoZkxUV2tvYjB0bkFTYV9RTUhhaHhveWx6YkdmcEhQdjNCS1lrbnp1LkxaWDdKOE40YkNNRjkzT3piNmx2Y0d3TWdVUkl5b18ubVUt";
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun get(): BaiDuYunHandler {
|
||||
return Loader.INSTANCE
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(java.lang.Exception::class)
|
||||
fun startScan(): ByteArray {
|
||||
val result = loginByQRCode()
|
||||
// Step 2: Get QR Code
|
||||
val byteStr: ByteArray = downloadQRCode(result["qrCodeImageUrl"]!!);
|
||||
|
||||
Init.run(Runnable { showQRCode(byteStr) })
|
||||
// Step 3: Check login status
|
||||
|
||||
Init.execute(Runnable {
|
||||
startService(
|
||||
result["sign"]!!
|
||||
)
|
||||
})
|
||||
return byteStr
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun downloadQRCode(url: String): ByteArray {
|
||||
val headers: MutableMap<String?, String?> = HashMap<String?, String?>()
|
||||
headers.put(
|
||||
"user-agent",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36"
|
||||
)
|
||||
|
||||
|
||||
val request = Request.Builder().url(url).headers(Headers.of(headers)).build()
|
||||
val response = OkHttp.newCall(request)
|
||||
if (response.code() == 200) {
|
||||
return response.body()!!.bytes()
|
||||
}
|
||||
return "".toByteArray()
|
||||
}
|
||||
|
||||
fun loginByQRCode(): Map<String, String> {
|
||||
return try {
|
||||
// 获取登录二维码
|
||||
val timestamp = System.currentTimeMillis()
|
||||
val qrCodeUrl = "https://passport.baidu.com/v2/api/getqrcode?lp=pc&_=$timestamp"
|
||||
|
||||
val response = OkHttp.string(qrCodeUrl, emptyMap(), headers)
|
||||
val json = Json.safeObject(response)
|
||||
|
||||
if (json["errno"].asInt != 0) {
|
||||
return mapOf("error" to "获取登录二维码错误, code: ${json["errno"].asInt}")
|
||||
}
|
||||
|
||||
val sign = json["sign"].asString
|
||||
val imgurl = json["imgurl"].asString
|
||||
val qrCodeImageUrl = "https://$imgurl"
|
||||
|
||||
val qrLoginUrl =
|
||||
"https://wappass.baidu.com/wp/?qrlogin&t=$timestamp" + "&error=0&sign=$sign&cmd=login&lp=pc&tpl=netdisk&uaonly=" + "&client_id=&adapter=3&client=&qrloginfrom=pc&wechat=0&traceid="
|
||||
|
||||
// 返回二维码信息供前端显示
|
||||
val result = mapOf(
|
||||
"qrCodeImageUrl" to qrCodeImageUrl, "qrLoginUrl" to qrLoginUrl, "sign" to sign
|
||||
)
|
||||
|
||||
result
|
||||
} catch (e: Exception) {
|
||||
mapOf("error" to "获取二维码失败: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
fun checkQRLoginStatus(sign: String): Map<String, Any> {
|
||||
return try {
|
||||
val timestamp = System.currentTimeMillis()
|
||||
val checkUrl =
|
||||
"https://passport.baidu.com/channel/unicast?channel_id=$sign" + "&tpl=netdisk&callback=&apiver=v3&tt=$timestamp&_=$timestamp"
|
||||
|
||||
val response = OkHttp.string(checkUrl, emptyMap(), headers)
|
||||
val cleanResponse = response.trim('(', ' ', '\n', ')')
|
||||
val json = Json.safeObject(cleanResponse)
|
||||
|
||||
if (json["errno"].asInt == 0) {
|
||||
SpiderDebug.log("百度扫码成功")
|
||||
val channelV = json["channel_v"].asString
|
||||
val channelJson = Json.safeObject(channelV)
|
||||
|
||||
if (channelJson["status"].asInt == 0) {
|
||||
val bduss = channelJson["v"].asString
|
||||
|
||||
// 执行登录
|
||||
val loginTimestamp = System.currentTimeMillis()
|
||||
val loginUrl =
|
||||
"https://passport.baidu.com/v3/login/main/qrbdusslogin?" + "v=$loginTimestamp&bduss=$bduss&u=&loginVersion=v4&qrcode=1&tpl=netdisk&apiver=v3" + "&tt=$loginTimestamp&traceid=&callback=bd__cbs__cupstt"
|
||||
|
||||
val loginResponse = OkHttp.get(loginUrl, emptyMap(), headers)
|
||||
val cleanLoginResponse = loginResponse.body.substringAfter("(").substringBeforeLast(")")
|
||||
val loginJson = Json.safeObject(StringEscapeUtils.unescapeHtml4(cleanLoginResponse))
|
||||
|
||||
if (loginJson.has("errInfo") && loginJson["errInfo"].asJsonObject["no"].asString == "0") {
|
||||
// 登录成功,设置cookie
|
||||
SpiderDebug.log("百度登录成功,设置cookie:${bduss}")
|
||||
cookies = "BDUSS=$bduss"
|
||||
cookies = generateCooike(loginResponse.resp["set-cookie"])
|
||||
|
||||
if (cookies.isNotEmpty()) {
|
||||
cache.setUser(User.objectFrom(this.cookies))
|
||||
//停止检验线程,关闭弹窗
|
||||
stopService()
|
||||
Notify.show("百度登录成功")
|
||||
|
||||
}
|
||||
|
||||
|
||||
mapOf("success" to true, "bduss" to bduss)
|
||||
} else {
|
||||
mapOf("error" to "登录失败: $cleanLoginResponse")
|
||||
}
|
||||
} else {
|
||||
mapOf("status" to channelJson["status"].asInt)
|
||||
}
|
||||
} else {
|
||||
mapOf("errno" to json["errno"].asInt)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
mapOf("error" to "检查登录状态失败: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
fun generateCooike(cookies: List<String>?): String {
|
||||
if (cookies == null || cookies.isEmpty()) {
|
||||
return ""
|
||||
}
|
||||
|
||||
val cookieList: MutableList<String?> = ArrayList<String?>()
|
||||
for (cookie in cookies) {
|
||||
cookieList.add(cookie.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0])
|
||||
}
|
||||
return TextUtils.join(";", cookieList)
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示qrcode
|
||||
*
|
||||
* @param base64Str
|
||||
*/
|
||||
fun showQRCode(bytes: ByteArray) {
|
||||
try {
|
||||
val size = ResUtil.dp2px(240)
|
||||
val params = FrameLayout.LayoutParams(size, size)
|
||||
val image = ImageView(Init.context())
|
||||
image.setScaleType(ImageView.ScaleType.CENTER_CROP)
|
||||
image.setImageBitmap(QRCode.Bytes2Bimap(bytes))
|
||||
val frame = FrameLayout(Init.context())
|
||||
params.gravity = Gravity.CENTER
|
||||
frame.addView(image, params)
|
||||
dialog = AlertDialog.Builder(Init.getActivity()).setView(frame)
|
||||
.setOnCancelListener(DialogInterface.OnCancelListener { dialog: DialogInterface? -> this.dismiss(dialog) })
|
||||
.setOnDismissListener(DialogInterface.OnDismissListener { dialog: DialogInterface? ->
|
||||
this.dismiss(dialog)
|
||||
}).show()
|
||||
dialog!!.getWindow()!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
Notify.show("请使用百度网盘App扫描二维码")
|
||||
} catch (ignored: java.lang.Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun dismiss() {
|
||||
try {
|
||||
dialog?.dismiss()
|
||||
} catch (ignored: java.lang.Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun dismiss(dialog: DialogInterface?) {
|
||||
stopService()
|
||||
}
|
||||
|
||||
private fun stopService() {
|
||||
service?.shutdownNow()
|
||||
Init.run(Runnable { this.dismiss() })
|
||||
}
|
||||
|
||||
fun startService(sign: String) {
|
||||
SpiderDebug.log("----start 百度 token service")
|
||||
|
||||
service = Executors.newScheduledThreadPool(1)
|
||||
|
||||
service?.scheduleWithFixedDelay(Runnable {
|
||||
try {
|
||||
SpiderDebug.log("----check百度tatus中")
|
||||
|
||||
checkQRLoginStatus(sign)
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}, 3, 3, TimeUnit.SECONDS)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ import com.github.catvod.utils.ProxyServer.buildProxyUrl
|
|||
import com.github.catvod.utils.Util
|
||||
import com.github.catvod.utils.Util.MEDIA
|
||||
import com.google.gson.JsonObject
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
|
||||
object BaiduDrive {
|
||||
|
|
@ -23,8 +22,6 @@ object BaiduDrive {
|
|||
"Referer" to "https://pan.baidu.com/"
|
||||
)
|
||||
|
||||
//是否删除过文件标志
|
||||
private var deleteTag = 0;
|
||||
private val saveDirName = "TVBOX_BD"
|
||||
|
||||
private var cookies = BaiDuYunHandler.get().token
|
||||
|
|
@ -40,12 +37,6 @@ object BaiduDrive {
|
|||
}
|
||||
|
||||
fun processShareLinks(urls: List<String>): Pair<List<String>, List<String>> {
|
||||
|
||||
//首先确保cookie不为空
|
||||
if (cookies.isEmpty()) {
|
||||
BaiDuYunHandler.get().startScan()
|
||||
cookies = BaiDuYunHandler.get().token
|
||||
}
|
||||
if (urls.isEmpty()) return emptyList<String>() to emptyList()
|
||||
|
||||
|
||||
|
|
@ -166,8 +157,7 @@ object BaiduDrive {
|
|||
// 处理items
|
||||
items.forEach { item ->
|
||||
if (item.asJsonObject["isdir"].asInt == 1) {
|
||||
val folderPath =
|
||||
"/sharelink$uk-${item.asJsonObject["fs_id"].asString}/${item.asJsonObject["server_filename"].asString}"
|
||||
val folderPath = "/sharelink$uk-$shareid/${item.asJsonObject["server_filename"].asString}"
|
||||
if (folderPath !in seenFolders) {
|
||||
seenFolders.add(folderPath)
|
||||
pendingFolders.add(
|
||||
|
|
@ -301,7 +291,7 @@ object BaiduDrive {
|
|||
"shareid" to folderInfo["shareid"]!!.toString(),
|
||||
"page" to folderInfo["page"].toString(),
|
||||
"num" to "9999",
|
||||
"dir" to URLEncoder.encode(folderInfo["dir"]!!.toString()),
|
||||
"dir" to folderInfo["dir"]!!.toString(),
|
||||
"desc" to "0",
|
||||
"order" to "name",
|
||||
)
|
||||
|
|
@ -324,7 +314,6 @@ object BaiduDrive {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private fun parseQueryParams(url: String): Map<String, List<String>> {
|
||||
val query = url.substringAfter(
|
||||
"?"
|
||||
|
|
@ -428,12 +417,9 @@ object BaiduDrive {
|
|||
)
|
||||
// 先清空文件夹在创建文件夹
|
||||
|
||||
if (deleteTag == 0) {
|
||||
_deleteTransferFile("/$saveDirName")
|
||||
//创建路径
|
||||
createSaveDir()
|
||||
deleteTag = 1
|
||||
}
|
||||
_deleteTransferFile("/$saveDirName")
|
||||
//创建路径
|
||||
createSaveDir()
|
||||
|
||||
|
||||
val data =
|
||||
|
|
@ -782,7 +768,7 @@ object BaiduDrive {
|
|||
fun playerContent(json: JsonObject, flag: String): String {
|
||||
val play = getVideoUrl(json, flag);
|
||||
val header = play["header"] as Map<String, String>
|
||||
return Result.get().url(buildProxyUrl(play["url"] as String, header)).octet().header(header).string();
|
||||
return Result.get().url(buildProxyUrl(play["url"] as String, header) ).octet().header(header).string();
|
||||
}
|
||||
|
||||
fun getPlayFormatList(): Array<String> {
|
||||
|
|
|
|||
|
|
@ -1,398 +0,0 @@
|
|||
package com.github.catvod.api
|
||||
|
||||
import com.github.catvod.bean.Result
|
||||
import com.github.catvod.bean.Vod
|
||||
import com.github.catvod.bean.Vod.VodPlayBuilder
|
||||
import com.github.catvod.bean.pan123.ShareInfo
|
||||
import com.github.catvod.crawler.SpiderDebug
|
||||
import com.github.catvod.net.OkHttp
|
||||
import com.github.catvod.utils.Json
|
||||
import com.github.catvod.utils.ProxyServer.buildProxyUrl
|
||||
import com.github.catvod.utils.Util
|
||||
import com.google.gson.JsonObject
|
||||
import okhttp3.HttpUrl
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
* 123网盘API操作类
|
||||
* 提供123网盘的文件分享、下载、播放等功能
|
||||
*/
|
||||
object Pan123Api {
|
||||
public const val regex =
|
||||
"https://(123592\\.com|123912\\.com|123865\\.com|123684\\.com|www\\.123684\\.com|www\\.123865\\.com|www\\.123912\\.com|www\\.123pan\\.com|www\\.123pan\\.cn|www\\.123592\\.com)/s/([^/]+)"
|
||||
|
||||
private const val api = "https://www.123684.com/b/api/share/"
|
||||
private const val loginUrl = "https://login.123pan.com/api/user/sign_in"
|
||||
|
||||
private var authToken = ""
|
||||
|
||||
|
||||
/**
|
||||
* 初始化方法,检查登录状态
|
||||
*/
|
||||
fun init() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取认证token
|
||||
*/
|
||||
private fun getAuth(): String {
|
||||
if (authToken.isNotBlank()) {
|
||||
return authToken
|
||||
}
|
||||
return Pan123Handler.getAuth()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
*/
|
||||
fun login(passport: String, password: String): JsonObject? {
|
||||
|
||||
val data = mapOf(
|
||||
"passport" to passport, "password" to password, "remember" to true
|
||||
)
|
||||
|
||||
val headers = mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
|
||||
"Content-Type" to "application/json",
|
||||
"App-Version" to "43",
|
||||
"Referer" to "https://login.123pan.com/centerlogin?redirect_url=https%3A%2F%2Fwww.123684.com&source_page=website",
|
||||
"Accept" to "application/json, text/plain, */*",
|
||||
"Origin" to "https://login.123pan.com",
|
||||
"Connection" to "keep-alive",
|
||||
"Accept-Language" to "zh-CN,zh;q=0.9"
|
||||
)
|
||||
|
||||
try {
|
||||
val response = OkHttp.post(loginUrl, Json.toJson(data), headers)
|
||||
SpiderDebug.log("登录请求信息:")
|
||||
SpiderDebug.log("URL: $loginUrl")
|
||||
SpiderDebug.log("账号: ${passport}")
|
||||
SpiderDebug.log("响应内容: ${response.body}")
|
||||
|
||||
if (response.code == 200) {
|
||||
val authData = Json.safeObject(response.body)
|
||||
SpiderDebug.log("解析后的响应数据: $authData")
|
||||
if (authData.has("data") && authData.getAsJsonObject("data").has("token")) {
|
||||
val token = authData.getAsJsonObject("data").get("token").asString
|
||||
// setAuth(token)
|
||||
SpiderDebug.log("登录成功")
|
||||
authToken=token
|
||||
|
||||
return authData.get("data").asJsonObject
|
||||
}
|
||||
}
|
||||
|
||||
throw Exception("登录失败: HTTP状态码=${response.code}, 响应=${response.body}")
|
||||
} catch (e: Exception) {
|
||||
SpiderDebug.log("登录过程中发生错误: ${e.message}")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析分享链接,提取分享密钥和提取码
|
||||
*/
|
||||
fun getShareData(url: String): Map<String, String> {
|
||||
SpiderDebug.log("123链接:$url")
|
||||
var sharePwd = ""
|
||||
var lurl = java.net.URLDecoder.decode(url, "UTF-8")
|
||||
|
||||
// 处理提取码格式
|
||||
if ("提取码" in lurl && "?" !in lurl) {
|
||||
lurl = lurl.replace(Regex("提取码[::]"), "?")
|
||||
}
|
||||
if ("提取码" in lurl && "?" in lurl) {
|
||||
lurl = lurl.replace(Regex("提取码[::]?"), "")
|
||||
}
|
||||
if (":" in lurl) {
|
||||
lurl = lurl.replace(":", "")
|
||||
}
|
||||
|
||||
val matcher = Pattern.compile(regex).matcher(lurl)
|
||||
|
||||
// 提取分享密码
|
||||
if ("?" in lurl) {
|
||||
val queryPart = lurl.split("?")[1]
|
||||
val pwdMatcher = Regex("[A-Za-z0-9]+").find(queryPart)
|
||||
if (pwdMatcher != null) {
|
||||
sharePwd = queryPart.split("=")[1]
|
||||
}
|
||||
}
|
||||
|
||||
if (matcher.find()) {
|
||||
val match = matcher.group(2) ?: ""
|
||||
val key = when {
|
||||
"?" in match -> match.split("?")[0]
|
||||
".html" in match -> match.replace(".html", "")
|
||||
"www" in match -> matcher.group(1) ?: match
|
||||
else -> match
|
||||
}
|
||||
return mapOf("key" to key, "sharePwd" to sharePwd)
|
||||
}
|
||||
|
||||
return emptyMap()
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分享链接获取文件列表
|
||||
*/
|
||||
fun getFilesByShareUrl(shareKey: String, sharePwd: String): List<ShareInfo> {
|
||||
// 获取分享信息
|
||||
val cate = getShareInfo(shareKey, sharePwd, 0, 0)
|
||||
|
||||
return cate
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取分享信息
|
||||
*/
|
||||
private fun getShareInfo(
|
||||
shareKey: String, sharePwd: String, next: Int, parentFileId: Long
|
||||
): List<ShareInfo> {
|
||||
|
||||
|
||||
//文件夹
|
||||
val folders = mutableListOf<ShareInfo>()
|
||||
//视频
|
||||
val videos = mutableListOf<ShareInfo>()
|
||||
|
||||
|
||||
val url =
|
||||
"${api}get?limit=100&next=$next&orderBy=file_name&orderDirection=asc&shareKey=${shareKey.trim()}&SharePwd=${sharePwd.ifEmpty { "" }}&ParentFileId=$parentFileId&Page=1"
|
||||
|
||||
try {
|
||||
val response = OkHttp.string(
|
||||
url, mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"
|
||||
)
|
||||
)
|
||||
|
||||
val data = Json.safeObject(response)
|
||||
if (data.has("code") && data.get("code").asInt == 5103) {
|
||||
SpiderDebug.log("123获取文件列表出错:" + data.get("message").asString)
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val info = data.getAsJsonObject("data")
|
||||
//其下没有文件
|
||||
if (info.get("Len").asLong <= 0) {
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
val nextValue = info.get("Next").asInt
|
||||
val infoList = info.getAsJsonArray("InfoList")
|
||||
|
||||
// 处理文件夹
|
||||
for (item in infoList) {
|
||||
val itemObj = item.asJsonObject
|
||||
//文件夹
|
||||
if (itemObj.get("Category").asInt == 0) {
|
||||
folders.add(
|
||||
ShareInfo(
|
||||
itemObj.get("FileName").asString,
|
||||
shareKey,
|
||||
sharePwd,
|
||||
nextValue,
|
||||
itemObj.get("FileId").asLong,
|
||||
itemObj["S3KeyFlag"].asString,
|
||||
itemObj["Size"].asLong,
|
||||
itemObj["Etag"].asString,
|
||||
|
||||
)
|
||||
)
|
||||
} else if (itemObj.get("Category").asInt == 2) {
|
||||
videos.add(
|
||||
ShareInfo(
|
||||
itemObj.get("FileName").asString,
|
||||
shareKey,
|
||||
sharePwd,
|
||||
nextValue,
|
||||
itemObj.get("FileId").asLong,
|
||||
itemObj["S3KeyFlag"].asString,
|
||||
itemObj["Size"].asLong,
|
||||
itemObj["Etag"].asString,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 递归获取子文件夹信息
|
||||
|
||||
for (item in folders) {
|
||||
val result = getShareInfo(
|
||||
item.shareKey, item.sharePwd, item.next, item.fileId
|
||||
)
|
||||
videos.addAll(result)
|
||||
}
|
||||
|
||||
return videos
|
||||
} catch (e: Exception) {
|
||||
SpiderDebug.log("获取分享信息时发生错误: ${e.message}")
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取文件下载链接
|
||||
*/
|
||||
fun getDownload(
|
||||
shareKey: String, fileId: Long, s3KeyFlag: String, size: Long, etag: String
|
||||
): String {
|
||||
|
||||
|
||||
SpiderDebug.log("获取下载链接参数:")
|
||||
SpiderDebug.log("ShareKey: $shareKey")
|
||||
SpiderDebug.log("FileID: $fileId")
|
||||
SpiderDebug.log("S3KeyFlag: $s3KeyFlag")
|
||||
SpiderDebug.log("Size: $size")
|
||||
SpiderDebug.log("Etag: $etag")
|
||||
SpiderDebug.log("Auth Token: ${getAuth().take(30)}...")
|
||||
|
||||
val data = mapOf(
|
||||
"ShareKey" to shareKey, "FileID" to fileId, "S3KeyFlag" to s3KeyFlag, "Size" to size, "Etag" to etag
|
||||
)
|
||||
|
||||
val url = "${api}download/info"
|
||||
SpiderDebug.log("请求URL: $url")
|
||||
SpiderDebug.log("请求数据: ${Json.toJson(data)}")
|
||||
|
||||
val headers = mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
|
||||
"Content-Type" to "application/json",
|
||||
"Authorization" to "Bearer ${getAuth()}",
|
||||
"platform" to "android"
|
||||
|
||||
)
|
||||
|
||||
try {
|
||||
val response = OkHttp.post(url, Json.toJson(data), headers)
|
||||
SpiderDebug.log("响应状态码: ${response.code}")
|
||||
SpiderDebug.log("响应内容: ${response.body}")
|
||||
|
||||
if (response.code == 200) {
|
||||
val responseData = Json.safeObject(response.body)
|
||||
if (responseData.has("data") && responseData.getAsJsonObject("data").has("DownloadURL")) {
|
||||
val encodeUrl = responseData.getAsJsonObject("data").get("DownloadURL").asString
|
||||
return Util.base64Decode(HttpUrl.parse(encodeUrl)?.queryParameter("params"))
|
||||
}
|
||||
}
|
||||
|
||||
throw Exception("获取下载链接失败: HTTP状态码=${response.code}, 响应=${response.body}")
|
||||
} catch (e: Exception) {
|
||||
SpiderDebug.log("获取下载链接时发生错误: ${e.message}")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取视频在线播放链接
|
||||
*/
|
||||
fun getLiveTranscoding(
|
||||
shareKey: String, fileId: Long, s3KeyFlag: String, size: Long, etag: String
|
||||
): List<Map<String, String>> {
|
||||
|
||||
|
||||
val url = "https://www.123684.com/b/api/video/play/info?" + "etag=$etag&size=$size&from=1&shareKey=$shareKey"
|
||||
|
||||
val headers = mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
|
||||
"Authorization" to "Bearer ${getAuth()}",
|
||||
"Content-Type" to "application/json;charset=UTF-8",
|
||||
"platform" to "android"
|
||||
)
|
||||
|
||||
try {
|
||||
val response = OkHttp.string(url, headers)
|
||||
|
||||
val downData = Json.safeObject(response)
|
||||
if (downData.has("data") && downData.getAsJsonObject("data").has("video_play_info")) {
|
||||
val videoInfo = mutableListOf<Map<String, String>>()
|
||||
val videoPlayInfo = downData.getAsJsonObject("data").getAsJsonArray("video_play_info")
|
||||
|
||||
for (item in videoPlayInfo) {
|
||||
val itemObj = item.asJsonObject
|
||||
if (itemObj.has("url") && !itemObj.get("url").isJsonNull) {
|
||||
val resolution = if (itemObj.has("resolution")) itemObj.get("resolution").asString else ""
|
||||
val urlValue = itemObj.get("url").asString
|
||||
|
||||
videoInfo.add(
|
||||
mapOf(
|
||||
"name" to resolution, "url" to urlValue
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return videoInfo
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
SpiderDebug.log("获取视频播放链接时发生错误: ${e.message}")
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
fun getPlayFormatList(): Array<String> {
|
||||
return arrayOf("原画")
|
||||
}
|
||||
|
||||
fun getVod(key: String, sharePwd: String): Vod {
|
||||
val list = getFilesByShareUrl(key, sharePwd)
|
||||
|
||||
val builder = VodPlayBuilder()
|
||||
for (i in getPlayFormatList().indices) {
|
||||
val playUrls = mutableListOf<VodPlayBuilder.PlayUrl>();
|
||||
for (item in list) {
|
||||
|
||||
val play = VodPlayBuilder.PlayUrl()
|
||||
play.name = "[${Util.getSize(item.Size.toDouble())}]${item.filename}"
|
||||
play.url =
|
||||
listOf(item.shareKey, item.fileId, item.S3KeyFlag, item.Size, item.Etag).joinToString("\\+\\+")
|
||||
|
||||
playUrls.add(play)
|
||||
|
||||
}
|
||||
builder.append("pan123" + getPlayFormatList()[i], playUrls)
|
||||
}
|
||||
val buildResult = builder.build();
|
||||
|
||||
val vod = Vod()
|
||||
vod.setVodId(key + "++" + sharePwd)
|
||||
vod.setVodPic("")
|
||||
vod.setVodYear("")
|
||||
vod.setVodName("")
|
||||
vod.setVodContent("")
|
||||
vod.setVodPlayFrom(buildResult.vodPlayFrom)
|
||||
vod.setVodPlayUrl(buildResult.vodPlayUrl)
|
||||
return vod
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun playerContent(id: String, flag: String): String {
|
||||
val itemJson = id.split("\\+\\+")
|
||||
|
||||
SpiderDebug.log("播放参数:$itemJson")
|
||||
val url = getDownload(
|
||||
itemJson[0], itemJson[1].toLong(), itemJson[2], itemJson[3].toLong(), itemJson[4]
|
||||
)
|
||||
val header = mapOf(
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"
|
||||
)
|
||||
|
||||
return Result.get().url(buildProxyUrl(url, header)).octet().header(header).string();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
package com.github.catvod.api
|
||||
|
||||
|
||||
import android.R
|
||||
import android.app.AlertDialog
|
||||
import android.content.DialogInterface
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import com.github.catvod.api.Pan123Api.login
|
||||
import com.github.catvod.bean.pan123.Cache
|
||||
import com.github.catvod.bean.pan123.User
|
||||
import com.github.catvod.crawler.SpiderDebug
|
||||
import com.github.catvod.spider.Init
|
||||
import com.github.catvod.utils.Notify
|
||||
import com.github.catvod.utils.Path
|
||||
import com.github.catvod.utils.ResUtil
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import java.io.File
|
||||
|
||||
object Pan123Handler {
|
||||
|
||||
|
||||
private var cache: Cache? = null
|
||||
private var dialog: AlertDialog? = null
|
||||
|
||||
private var auth = ""
|
||||
private var userName = ""
|
||||
private var passwd = ""
|
||||
private var expire = 0L;
|
||||
|
||||
fun getCache(): File {
|
||||
return Path.tv("pan123")
|
||||
}
|
||||
|
||||
fun getAuth(): String {
|
||||
return auth
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
|
||||
cache = Cache.objectFrom(Path.read(getCache()))
|
||||
if (cache == null) {
|
||||
SpiderDebug.log("cache 为null")
|
||||
startFlow()
|
||||
} else {
|
||||
userName = cache!!.user.userName
|
||||
passwd = cache!!.user.password
|
||||
auth = cache!!.user.cookie
|
||||
expire = cache!!.user.expire
|
||||
if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(passwd)) {
|
||||
if (StringUtils.isBlank(auth) || expire == 0L || System.currentTimeMillis() > expire) {
|
||||
SpiderDebug.log("auth 为空或者登录已过期")
|
||||
this.loginWithPassword(userName, passwd)
|
||||
}
|
||||
} else {
|
||||
SpiderDebug.log("userName passwd 为空")
|
||||
startFlow()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun loginWithPassword(uname: String?, passwd: String?) {
|
||||
SpiderDebug.log("loginWithPassword uname: $uname,passwd:$passwd")
|
||||
|
||||
try {
|
||||
//保存的账号密码
|
||||
val json = login(uname!!, passwd!!)
|
||||
if (json != null) {
|
||||
val user = User()
|
||||
user.cookie = json.get("token").asString
|
||||
user.password = passwd
|
||||
user.userName = uname
|
||||
user.expire = json.get("refresh_token_expire_time").asLong * 1000
|
||||
this.auth = json.get("token").asString
|
||||
cache?.setUserInfo(user)
|
||||
Notify.show("123登录成功")
|
||||
} else {
|
||||
Notify.show("123登录失败")
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
SpiderDebug.log("登录失败: " + e.message)
|
||||
Notify.show("123登录失败: " + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
fun startFlow() {
|
||||
Init.run { this.showInput() }
|
||||
}
|
||||
|
||||
|
||||
private fun showInput() {
|
||||
try {
|
||||
val margin = ResUtil.dp2px(16)
|
||||
val params =
|
||||
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
val frame = LinearLayout(Init.context())
|
||||
frame.setOrientation(LinearLayout.VERTICAL)
|
||||
// frame.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
// params.setMargins(margin, margin, margin, margin);
|
||||
val username = EditText(Init.context())
|
||||
username.setHint("请输入123用户名")
|
||||
val password = EditText(Init.context())
|
||||
password.setHint("请输入123密码")
|
||||
frame.addView(username, params)
|
||||
frame.addView(password, params)
|
||||
dialog = AlertDialog.Builder(Init.getActivity()).setTitle("请输入123用户名和密码").setView(frame)
|
||||
.setNegativeButton(
|
||||
R.string.cancel, null
|
||||
).setPositiveButton(
|
||||
R.string.ok, DialogInterface.OnClickListener { dialog: DialogInterface?, which: Int ->
|
||||
onPositive(
|
||||
username.getText().toString(), password.getText().toString()
|
||||
)
|
||||
}).show()
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun onPositive(username: String?, password: String?) {
|
||||
SpiderDebug.log("123用户名: $username")
|
||||
SpiderDebug.log("123密码: $password")
|
||||
dismiss()
|
||||
Init.execute(Runnable {
|
||||
loginWithPassword(username, password)
|
||||
})
|
||||
}
|
||||
|
||||
private fun dismiss() {
|
||||
try {
|
||||
if (dialog != null) dialog!!.dismiss()
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import android.view.ViewGroup;
|
|||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.bean.quark.Cache;
|
||||
|
|
@ -23,14 +24,30 @@ import com.github.catvod.net.OkHttp;
|
|||
import com.github.catvod.net.OkResult;
|
||||
import com.github.catvod.spider.Init;
|
||||
import com.github.catvod.spider.Proxy;
|
||||
import com.github.catvod.utils.*;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.github.catvod.utils.Notify;
|
||||
import com.github.catvod.utils.Path;
|
||||
import com.github.catvod.utils.ProxyServer;
|
||||
import com.github.catvod.utils.ProxyVideo;
|
||||
import com.github.catvod.utils.QRCode;
|
||||
import com.github.catvod.utils.ResUtil;
|
||||
import com.github.catvod.utils.Util;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
|
@ -210,18 +227,15 @@ public class QuarkApi {
|
|||
|
||||
String fileId = split[0], fileToken = split[1], shareId = split[2], stoken = split[3];
|
||||
String playUrl = "";
|
||||
if (flag.contains("quark原画")) {
|
||||
playUrl = this.getDownload(shareId, stoken, fileId, fileToken, true);
|
||||
} else {
|
||||
playUrl = this.getLiveTranscoding(shareId, stoken, fileId, fileToken, flag);
|
||||
}
|
||||
Map<String, String> header = getHeaders();
|
||||
header.remove("Host");
|
||||
header.remove("Content-Type");
|
||||
if (flag.contains("quark原画")) {
|
||||
playUrl = this.getDownload(shareId, stoken, fileId, fileToken, true);
|
||||
return Result.get().url(ProxyServer.INSTANCE.buildProxyUrl(playUrl, header)).octet().header(header).string();
|
||||
} else {
|
||||
playUrl = this.getLiveTranscoding(shareId, stoken, fileId, fileToken, flag);
|
||||
return Result.get().url(proxyVideoUrl(playUrl, header)).octet().header(header).string();
|
||||
}
|
||||
|
||||
|
||||
return Result.get().url(ProxyServer.INSTANCE.buildProxyUrl(playUrl, header)).octet().header(header).string();
|
||||
}
|
||||
|
||||
private String proxyVideoUrl(String url, Map<String, String> header) {
|
||||
|
|
@ -414,7 +428,7 @@ public class QuarkApi {
|
|||
for (Map<String, Object> item : items) {
|
||||
if (Boolean.TRUE.equals(item.get("dir"))) {
|
||||
subDir.add(item);
|
||||
} else if (Boolean.TRUE.equals(item.get("file")) && (Util.isMedia((String) item.get("file_name")))) {
|
||||
} else if (Boolean.TRUE.equals(item.get("file")) && "video".equals(item.get("obj_category"))) {
|
||||
if ((Double) item.get("size") < 1024 * 1024 * 5) continue;
|
||||
item.put("stoken", this.shareTokenCache.get(shareData.getShareId()).get("stoken"));
|
||||
videos.add(Item.objectFrom(item, shareData.getShareId(), shareIndex));
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
public class TianyiApi {
|
||||
private String apiUrl = "https://cloud.189.cn/api/open/share/";
|
||||
public static final String URL_CONTAIN = "cloud.189.cn/";
|
||||
public static final String URL_START = "https://cloud.189.cn/";
|
||||
|
||||
|
||||
private Map<String, JsonObject> shareTokenCache = new HashMap<>();
|
||||
|
|
@ -221,30 +221,41 @@ public class TianyiApi {
|
|||
|
||||
|
||||
public ShareData getShareData(String url, String accessCode) {
|
||||
// 从整个URL中直接提取访问码,无论格式如何
|
||||
Matcher accessMatcher = Pattern.compile("访问码[::]([a-zA-Z0-9]+)").matcher(url);
|
||||
if (accessMatcher.find()) {
|
||||
accessCode = accessMatcher.group(1);
|
||||
} else if (accessCode == null || accessCode.isEmpty()) {
|
||||
accessCode = "";
|
||||
}
|
||||
|
||||
String shareCode = null;
|
||||
// 第一种匹配规则:兼容http和https
|
||||
Matcher matcher = Pattern.compile("https?:\\/\\/cloud\\.189\\.cn\\/web\\/share\\?code=([^&\\s]+)").matcher(url);
|
||||
String shareCode = "";
|
||||
// 第一种匹配规则:使用预编译的 regex
|
||||
Matcher matcher = Pattern.compile("https:\\/\\/cloud\\.189\\.cn\\/web\\/share\\?code=([^&]+)").matcher(url);
|
||||
if (matcher.find() && matcher.group(1) != null) {
|
||||
shareCode = matcher.group(1);
|
||||
// 从shareCode中提取访问码
|
||||
Matcher accessMatcher = Pattern.compile("访问码:([a-zA-Z0-9]+)").matcher(shareCode);
|
||||
if (accessMatcher.find()) {
|
||||
accessCode = accessMatcher.group(1);
|
||||
|
||||
} else {
|
||||
accessCode = "";
|
||||
}
|
||||
} else {
|
||||
// 第二种匹配规则:直接匹配 cloud.189.cn/t/ 格式,兼容http和https,匹配到空格前
|
||||
Matcher fallbackMatcher = Pattern.compile("https?:\\/\\/cloud\\.189\\.cn\\/t/([^\\s]+)").matcher(url);
|
||||
// 第二种匹配规则:直接匹配 cloud.189.cn/t/ 格式
|
||||
Matcher fallbackMatcher = Pattern.compile("https://cloud\\.189\\.cn/t/([^&]+)").matcher(url);
|
||||
if (fallbackMatcher.find()) {
|
||||
shareCode = fallbackMatcher.group(1);
|
||||
} else {
|
||||
shareCode = null;
|
||||
}
|
||||
// 再次尝试从shareCode提取访问码
|
||||
if (shareCode != null) {
|
||||
Matcher accessMatcher = Pattern.compile("访问码:([a-zA-Z0-9]+)").matcher(shareCode);
|
||||
accessCode = accessMatcher.find() ? accessMatcher.group(1) : "";
|
||||
} else {
|
||||
accessCode = "";
|
||||
}
|
||||
}
|
||||
|
||||
shareCode = shareCode.split("(访问码")[0].trim();
|
||||
ShareData shareData = new ShareData(shareCode, "0");
|
||||
shareData.setSharePwd(accessCode);
|
||||
return shareData;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class UCApi {
|
|||
private String cookieToken = "";
|
||||
private String ckey = "";
|
||||
private Map<String, Map<String, Object>> shareTokenCache = new HashMap<>();
|
||||
private String pr = "pr=UCBrowser&fr=pc&sys=darwin&ve=1.8.6&ut=Nk27FcCv6q1eo6rXz8QHR/nIG6qLA3jh7KdL+agFgcOvww==";
|
||||
private String pr = "pr=UCBrowser&fr=pc";
|
||||
private List<String> subtitleExts = Arrays.asList(".srt", ".ass", ".scc", ".stl", ".ttml");
|
||||
private Map<String, String> saveFileIdCaches = new HashMap<>();
|
||||
private String saveDirId = null;
|
||||
|
|
@ -87,15 +87,7 @@ public class UCApi {
|
|||
cache = Cache.objectFrom(Path.read(getCache()));
|
||||
tokenCache = Cache.objectFrom(Path.read(qrCodeHandler.getCache()));
|
||||
|
||||
java.lang.String tokenCacheJson = tokenCache.getUser().getCookie();
|
||||
if (StringUtils.isNoneBlank(tokenCacheJson)) {
|
||||
|
||||
|
||||
//刷新token,并返回
|
||||
this.cookieToken = qrCodeHandler.refreshToken(Json.safeObject(tokenCacheJson).getAsJsonObject().get("refresh_token").getAsString());
|
||||
|
||||
SpiderDebug.log("UC初始化获取到的cookieToken: " + cookieToken);
|
||||
}
|
||||
this.cookieToken = tokenCache.getUser().getCookie();
|
||||
SpiderDebug.log("UC初始化获取到的cookieToken: " + cookieToken);
|
||||
}
|
||||
|
||||
|
|
@ -189,9 +181,9 @@ public class UCApi {
|
|||
List<String> playFrom = UCApi.get().getPlayFormatList();
|
||||
List<String> playFromtmp = new ArrayList<>();
|
||||
playFromtmp.add("uc原画");
|
||||
/* for (String s : playFrom) {
|
||||
for (String s : playFrom) {
|
||||
playFromtmp.add("uc" + s);
|
||||
}*/
|
||||
}
|
||||
List<String> playUrl = new ArrayList<>();
|
||||
|
||||
if (files.isEmpty()) {
|
||||
|
|
@ -225,19 +217,23 @@ public class UCApi {
|
|||
SpiderDebug.log("flag:" + flag);
|
||||
String fileId = split[0], fileToken = split[1], shareId = split[2], stoken = split[3];
|
||||
String playUrl = "";
|
||||
if (flag.contains("uc原画")) {
|
||||
playUrl = this.getDownload(shareId, stoken, fileId, fileToken, true);
|
||||
} else {
|
||||
playUrl = this.getLiveTranscoding(shareId, stoken, fileId, fileToken, flag);
|
||||
}
|
||||
SpiderDebug.log("origin playUrl:" + playUrl);
|
||||
Map<String, String> header = getHeaders();
|
||||
header.remove("Host");
|
||||
header.remove("Content-Type");
|
||||
if (flag.contains("uc原画")) {
|
||||
playUrl = this.getDownload(shareId, stoken, fileId, fileToken, true);
|
||||
|
||||
//UCTV 可以直接播放,不需要代理
|
||||
if (testVideo(playUrl)) {
|
||||
SpiderDebug.log("UCTV 可以直接播放,不需要代理" );
|
||||
|
||||
return Result.get().url(playUrl).string();
|
||||
} else {
|
||||
playUrl = this.getLiveTranscoding(shareId, stoken, fileId, fileToken, flag);
|
||||
return Result.get().url(proxyVideoUrl(playUrl, new HashMap<>())).string();
|
||||
}
|
||||
|
||||
|
||||
return Result.get().url(proxyVideoUrl(playUrl, header)).octet().header(header).string();
|
||||
}
|
||||
|
||||
private boolean testVideo(String url) {
|
||||
|
|
|
|||
|
|
@ -178,7 +178,25 @@ public class UCTokenHandler {
|
|||
JsonObject resData = Json.safeObject(okResult.getBody());
|
||||
String code = resData.get("code").getAsString();
|
||||
|
||||
OkResult okResult1 = getAccessToken(code, false);
|
||||
pathname = "/token";
|
||||
reqId = generateReqId(deviceID, timestamp);
|
||||
|
||||
Map<String, String> postData = new HashMap<>();
|
||||
postData.put("req_id", reqId);
|
||||
postData.put("app_ver", (String) conf.get("appVer"));
|
||||
postData.put("device_id", deviceID);
|
||||
postData.put("device_brand", "Xiaomi");
|
||||
postData.put("platform", "tv");
|
||||
postData.put("device_name", "M2004J7AC");
|
||||
postData.put("device_model", "M2004J7AC");
|
||||
postData.put("build_device", "M2004J7AC");
|
||||
postData.put("build_product", "M2004J7AC");
|
||||
postData.put("device_gpu", "Adreno (TM) 550");
|
||||
postData.put("activity_rect", URLEncoder.encode("{}", "UTF-8"));
|
||||
postData.put("channel", (String) conf.get("channel"));
|
||||
postData.put("code", code);
|
||||
|
||||
OkResult okResult1 = OkHttp.post(conf.get("codeApi") + pathname, Json.toJson(postData), headers);
|
||||
|
||||
|
||||
if (okResult1.getCode() == 200) {
|
||||
|
|
@ -190,14 +208,15 @@ public class UCTokenHandler {
|
|||
SpiderDebug.log("uc Token获取成功:" + tokenResData.get("data").getAsJsonObject().get("access_token").getAsString());
|
||||
|
||||
//保存到本地
|
||||
cache.setTokenUser(User.objectFrom(Json.toJson(tokenResData.get("data").getAsJsonObject())));
|
||||
cache.setTokenUser(User.objectFrom(tokenResData.get("data").getAsJsonObject().get("access_token").getAsString()));
|
||||
|
||||
//停止检验线程,关闭弹窗
|
||||
stopService();
|
||||
return result;
|
||||
}
|
||||
|
||||
} else if (okResult.getCode() == 400) {
|
||||
SpiderDebug.log("uc Token获取失败:" + okResult.getBody());
|
||||
SpiderDebug.log("uc Token获取失败:" +okResult.getBody());
|
||||
|
||||
return Map.of("status", "NEW");
|
||||
|
||||
|
|
@ -207,74 +226,6 @@ public class UCTokenHandler {
|
|||
platformStates.remove("UC_TOKEN");
|
||||
return Map.of("status", "EXPIRED");
|
||||
}
|
||||
/**
|
||||
* 获取访问令牌或者刷新令牌
|
||||
*
|
||||
* @param code
|
||||
* @param refresh 是否刷新,如果是,code为refresh_token
|
||||
* @return
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
public OkResult getAccessToken(String code, boolean refresh) {
|
||||
|
||||
String timestamp = String.valueOf(new Date().getTime() / 1000 + 1) + "000";
|
||||
String deviceID = StringUtils.isAllBlank((String) addition.get("DeviceID")) ? (String) addition.get("DeviceID") : generateDeviceID(timestamp);
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Accept", "application/json, text/plain, */*");
|
||||
headers.put("User-Agent", "Mozilla/5.0 (Linux; U; Android 13; zh-cn; M2004J7AC Build/UKQ1.231108.001) AppleWebKit/533.1 (KHTML, like Gecko) Mobile Safari/533.1");
|
||||
|
||||
String pathname = "/token";
|
||||
String reqId = generateReqId(deviceID, timestamp);
|
||||
|
||||
Map<String, String> postData = new HashMap<>();
|
||||
postData.put("req_id", reqId);
|
||||
postData.put("app_ver", (String) conf.get("appVer"));
|
||||
postData.put("device_id", deviceID);
|
||||
postData.put("device_brand", "Xiaomi");
|
||||
postData.put("platform", "tv");
|
||||
postData.put("device_name", "M2004J7AC");
|
||||
postData.put("device_model", "M2004J7AC");
|
||||
postData.put("build_device", "M2004J7AC");
|
||||
postData.put("build_product", "M2004J7AC");
|
||||
postData.put("device_gpu", "Adreno (TM) 550");
|
||||
try {
|
||||
postData.put("activity_rect", URLEncoder.encode("{}", "UTF-8"));
|
||||
} catch (Exception e) {
|
||||
|
||||
SpiderDebug.log("encode出错" + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
postData.put("channel", conf.get("channel"));
|
||||
if (refresh) {
|
||||
postData.put("refresh_token", code);
|
||||
SpiderDebug.log("开始刷新uc accesstoken");
|
||||
} else {
|
||||
postData.put("code", code);
|
||||
SpiderDebug.log("开始获取uc accesstoken");
|
||||
}
|
||||
|
||||
|
||||
return OkHttp.post(conf.get("codeApi") + pathname, Json.toJson(postData), headers);
|
||||
}
|
||||
/**
|
||||
* 刷新refresh token
|
||||
*
|
||||
* @param refreshToken 刷新token
|
||||
* @return 防火新的accesstoken
|
||||
*/
|
||||
public String refreshToken(String refreshToken) {
|
||||
OkResult okResult1 = this.getAccessToken(refreshToken, true);
|
||||
|
||||
if (okResult1.getCode() == 200) {
|
||||
JsonObject tokenResData = Json.safeObject(okResult1.getBody());
|
||||
SpiderDebug.log("uc Token刷新成功:" + tokenResData.get("data").getAsJsonObject().get("access_token").getAsString());
|
||||
//保存到本地
|
||||
cache.setTokenUser(User.objectFrom(Json.toJson(tokenResData.get("data").getAsJsonObject())));
|
||||
return tokenResData.get("data").getAsJsonObject().get("access_token").getAsString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String download(String token, String saveFileId) throws Exception {
|
||||
SpiderDebug.log("开始下载:" + saveFileId + ";token:" + token);
|
||||
|
|
@ -315,11 +266,6 @@ public class UCTokenHandler {
|
|||
|
||||
OkResult okResult1 = OkHttp.get(API_URL + pathname, params, headers);
|
||||
JsonObject obj = Json.safeObject(okResult1.getBody());
|
||||
if (okResult1.getCode() != 200) {
|
||||
Notify.show(obj.get("error_info").getAsString());
|
||||
SpiderDebug.log("uc TV 错误信息:" + obj.get("error_info").getAsString());
|
||||
return null;
|
||||
}
|
||||
String downloadUrl = obj.get("data").getAsJsonObject().get("video_info").getAsJsonArray().get(0).getAsJsonObject().get("url").getAsString();
|
||||
SpiderDebug.log("uc TV 下载文件内容:" + downloadUrl);
|
||||
return downloadUrl;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.github.catvod.bean.BD;
|
|||
|
||||
|
||||
import com.github.catvod.api.BaiDuYunHandler;
|
||||
import com.github.catvod.api.YunTokenHandler;
|
||||
import com.github.catvod.bean.yun.User;
|
||||
import com.github.catvod.spider.Init;
|
||||
import com.github.catvod.utils.Path;
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
package com.github.catvod.bean.pan123;
|
||||
|
||||
import com.github.catvod.api.Pan123Handler;
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
import com.github.catvod.spider.Init;
|
||||
import com.github.catvod.utils.Path;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Cache {
|
||||
|
||||
@SerializedName("user")
|
||||
private User user;
|
||||
|
||||
|
||||
public static Cache objectFrom(String str) {
|
||||
if(str.isEmpty()) return new Cache();
|
||||
SpiderDebug.log("Cache.objectFrom: " + str);
|
||||
Cache item = new Gson().fromJson(str, Cache.class);
|
||||
return item == null ? new Cache() : item;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user == null ? new User() : user;
|
||||
}
|
||||
|
||||
|
||||
public void setUserInfo(User user) {
|
||||
this.user = user;
|
||||
this.saveUser();
|
||||
}
|
||||
|
||||
public void saveUser() {
|
||||
SpiderDebug.log("Cache.saveUser: " + toString());
|
||||
SpiderDebug.log("Cache.path: " + Pan123Handler.INSTANCE.getCache().getAbsolutePath());
|
||||
Init.execute(() -> Path.write(Pan123Handler.INSTANCE.getCache(), toString()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new Gson().toJson(this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
package com.github.catvod.bean.pan123
|
||||
|
||||
data class ShareInfo(
|
||||
val filename: String,
|
||||
val shareKey: String,
|
||||
val sharePwd: String,
|
||||
val next: Int,
|
||||
val fileId: Long,
|
||||
val S3KeyFlag: String,
|
||||
val Size: Long,
|
||||
val Etag: String
|
||||
)
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
package com.github.catvod.bean.pan123;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class User {
|
||||
|
||||
@SerializedName("expire")
|
||||
private long expire;
|
||||
@SerializedName("cookie")
|
||||
private String cookie;
|
||||
|
||||
@SerializedName("userName")
|
||||
private String userName;
|
||||
@SerializedName("password")
|
||||
private String password;
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getCookie() {
|
||||
return cookie;
|
||||
}
|
||||
|
||||
public void setCookie(String cookie) {
|
||||
this.cookie = cookie;
|
||||
}
|
||||
|
||||
public long getExpire() {
|
||||
return expire;
|
||||
}
|
||||
|
||||
public void setExpire(long expire) {
|
||||
this.expire = expire;
|
||||
}
|
||||
|
||||
public static User objectFrom(String str) {
|
||||
User item = new Gson().fromJson(str, User.class);
|
||||
return item == null ? new User() : item;
|
||||
}
|
||||
|
||||
|
||||
public void clean() {
|
||||
this.cookie = "";
|
||||
this.userName = "";
|
||||
this.password = "";
|
||||
this.expire = 0L;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ class BaiDuPan : Spider() {
|
|||
return TextUtils.join("$$$", BaiduDrive.get().getPlayFormatList());
|
||||
}*/
|
||||
for (i in 1..ids.size) {
|
||||
playFrom.add( String.format(Locale.getDefault(), "BD原画" + "#%02d_%02d", i, index))
|
||||
playFrom.add("BD原画" + i + index)
|
||||
/* for (s in getPlayFormatList()) {
|
||||
playFrom.add(String.format(Locale.getDefault(), "BD" + s + "#%02d%02d", i, index))
|
||||
}*/
|
||||
|
|
@ -78,7 +78,7 @@ class BaiDuPan : Spider() {
|
|||
* @param ids share_link 集合
|
||||
* @return 詳情內容視頻播放地址
|
||||
*/
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun detailContentVodPlayUrl(ids: List<String>): String? {
|
||||
val playUrl: MutableList<String?> = ArrayList<String?>()
|
||||
for (id in ids) {
|
||||
|
|
@ -86,7 +86,6 @@ class BaiDuPan : Spider() {
|
|||
playUrl.add(getVod(id).getVodPlayUrl())
|
||||
} catch (e: Exception) {
|
||||
SpiderDebug.log("获取播放地址出错:" + e.message)
|
||||
playUrl.add("")
|
||||
}
|
||||
}
|
||||
return TextUtils.join("$$$", playUrl)
|
||||
|
|
|
|||
|
|
@ -2,191 +2,127 @@ package com.github.catvod.spider;
|
|||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import com.github.catvod.api.Pan123Api;
|
||||
import com.github.catvod.api.TianyiApi;
|
||||
import com.github.catvod.crawler.Spider;
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.github.catvod.utils.Util;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.github.catvod.api.TianyiApi.URL_CONTAIN;
|
||||
import static com.github.catvod.api.TianyiApi.URL_START;
|
||||
|
||||
/**
|
||||
* @author ColaMint & Adam & FongMi
|
||||
*/
|
||||
public class Cloud extends Spider {
|
||||
private Quark quark = null;
|
||||
/* private Ali ali = null;*/
|
||||
private UC uc = null;
|
||||
/* private Ali ali = null;
|
||||
private UC uc = null;*/
|
||||
private TianYi tianYi = null;
|
||||
private YiDongYun yiDongYun = null;
|
||||
private BaiDuPan baiDuPan = null;
|
||||
private Pan123 pan123 = null;
|
||||
private static final Map<String, ImmutablePair<List<String>, List<String>>> resultMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void init(Context context, String extend) throws Exception {
|
||||
JsonObject ext = Json.safeObject(extend);
|
||||
quark = new Quark();
|
||||
uc = new UC();
|
||||
/* ali = new Ali();*/
|
||||
/* uc = new UC();
|
||||
ali = new Ali();*/
|
||||
tianYi = new TianYi();
|
||||
yiDongYun = new YiDongYun();
|
||||
baiDuPan = new BaiDuPan();
|
||||
pan123 = new Pan123();
|
||||
boolean first = Objects.nonNull(ext);
|
||||
quark.init(context, first && ext.has("cookie") ? ext.get("cookie").getAsString() : "");
|
||||
uc.init(context, first && ext.has("uccookie") ? ext.get("uccookie").getAsString() : "");
|
||||
/* ali.init(context, first && ext.has("token") ? ext.get("token").getAsString() : "");*/
|
||||
/* uc.init(context, first && ext.has("uccookie") ? ext.get("uccookie").getAsString() : "");
|
||||
ali.init(context, first && ext.has("token") ? ext.get("token").getAsString() : "");*/
|
||||
tianYi.init(context, first && ext.has("tianyicookie") ? ext.get("tianyicookie").getAsString() : "");
|
||||
yiDongYun.init(context, "");
|
||||
baiDuPan.init(context, "");
|
||||
pan123.init(context, "");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String detailContent(List<String> shareUrl) throws Exception {
|
||||
SpiderDebug.log("cloud detailContent shareUrl:" + Json.toJson(shareUrl));
|
||||
|
||||
/* if (shareUrl.get(0).matches(Util.patternAli)) {
|
||||
return ali.detailContent(shareUrl);
|
||||
} else */
|
||||
if (shareUrl.get(0).matches(Util.patternQuark)) {
|
||||
} else */if (shareUrl.get(0).matches(Util.patternQuark)) {
|
||||
return quark.detailContent(shareUrl);
|
||||
} else if (shareUrl.get(0).matches(Util.patternUC)) {
|
||||
} /*else if (shareUrl.get(0).matches(Util.patternUC)) {
|
||||
return uc.detailContent(shareUrl);
|
||||
} else if (shareUrl.get(0).contains(URL_CONTAIN)) {
|
||||
} */else if (shareUrl.get(0).startsWith(TianyiApi.URL_START)) {
|
||||
return tianYi.detailContent(shareUrl);
|
||||
} else if (shareUrl.get(0).contains(YiDongYun.URL_START)) {
|
||||
return yiDongYun.detailContent(shareUrl);
|
||||
} else if (shareUrl.get(0).contains(BaiDuPan.URL_START)) {
|
||||
}else if (shareUrl.get(0).contains(BaiDuPan.URL_START)) {
|
||||
return baiDuPan.detailContent(shareUrl);
|
||||
} else if (shareUrl.get(0).matches(Pan123Api.regex)) {
|
||||
SpiderDebug.log("Pan123Api shareUrl:" + Json.toJson(shareUrl));
|
||||
return pan123.detailContent(shareUrl);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
|
||||
SpiderDebug.log("cloud playerContent flag:" + flag + " id:" + id);
|
||||
|
||||
if (flag.contains("quark")) {
|
||||
return quark.playerContent(flag, id, vipFlags);
|
||||
} else if (flag.contains("uc")) {
|
||||
} /*else if (flag.contains("uc")) {
|
||||
return uc.playerContent(flag, id, vipFlags);
|
||||
} else if (flag.contains("天意")) {
|
||||
} */else if (flag.contains("天意")) {
|
||||
return tianYi.playerContent(flag, id, vipFlags);
|
||||
} else if (flag.contains("移动")) {
|
||||
return yiDongYun.playerContent(flag, id, vipFlags);
|
||||
}/* else {
|
||||
return ali.playerContent(flag, id, vipFlags);
|
||||
}*/ else if (flag.contains("BD")) {
|
||||
}*/
|
||||
|
||||
else if (flag.contains("BD")) {
|
||||
return baiDuPan.playerContent(flag, id, vipFlags);
|
||||
} else if (flag.contains("pan123")) {
|
||||
return pan123.playerContent(flag, id, vipFlags);
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
protected String detailContentVodPlayFrom(List<String> shareLinks) {
|
||||
ImmutablePair<List<String>, List<String>> pairs = resultMap.get(Util.MD5(Json.toJson(shareLinks)));
|
||||
if (pairs != null && pairs.left != null && !pairs.left.isEmpty()) {
|
||||
return TextUtils.join("$$$", pairs.right);
|
||||
List<String> from = new ArrayList<>();
|
||||
int i = 0;
|
||||
for (String shareLink : shareLinks) {
|
||||
i++;
|
||||
/*if (shareLink.matches(Util.patternUC)) {
|
||||
from.add(uc.detailContentVodPlayFrom(List.of(shareLink), i));
|
||||
} else*/ if (shareLink.matches(Util.patternQuark)) {
|
||||
from.add(quark.detailContentVodPlayFrom(List.of(shareLink), i));
|
||||
} /*else if (shareLink.matches(Util.patternAli)) {
|
||||
from.add(ali.detailContentVodPlayFrom(List.of(shareLink), i));
|
||||
} */else if (shareLink.startsWith(URL_START)) {
|
||||
from.add(tianYi.detailContentVodPlayFrom(List.of(shareLink), i));
|
||||
} else if (shareLink.contains(YiDongYun.URL_START)) {
|
||||
from.add(yiDongYun.detailContentVodPlayFrom(List.of(shareLink), i));
|
||||
}
|
||||
else if (shareLink.contains(BaiDuPan.URL_START)) {
|
||||
from.add(baiDuPan.detailContentVodPlayFrom(List.of(shareLink), i));
|
||||
}
|
||||
}
|
||||
|
||||
getPlayFromAndUrl(shareLinks);
|
||||
pairs = resultMap.get(Util.MD5(Json.toJson(shareLinks)));
|
||||
if (pairs != null && pairs.left != null && !pairs.left.isEmpty()) {
|
||||
return TextUtils.join("$$$", pairs.right);
|
||||
}
|
||||
return "";
|
||||
|
||||
return TextUtils.join("$$$", from);
|
||||
}
|
||||
|
||||
protected String detailContentVodPlayUrl(List<String> shareLinks) {
|
||||
ImmutablePair<List<String>, List<String>> pairs = resultMap.get(Util.MD5(Json.toJson(shareLinks)));
|
||||
if (pairs != null && pairs.left != null && !pairs.left.isEmpty()) {
|
||||
return TextUtils.join("$$$", pairs.left);
|
||||
}
|
||||
|
||||
getPlayFromAndUrl(shareLinks);
|
||||
pairs = resultMap.get(Util.MD5(Json.toJson(shareLinks)));
|
||||
if (pairs != null && pairs.left != null && !pairs.left.isEmpty()) {
|
||||
return TextUtils.join("$$$", pairs.left);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
//同時获取from 和url ,放入缓存,只要一个函数执行就行,避免重复执行
|
||||
private void getPlayFromAndUrl(List<String> shareLinks) {
|
||||
ExecutorService service = Executors.newFixedThreadPool(4);
|
||||
try { //首先清空缓存,避免太多缓存
|
||||
resultMap.clear();
|
||||
List<String> urls = new ArrayList<>();
|
||||
List<String> froms = new ArrayList<>();
|
||||
|
||||
List<Future<ImmutablePair<String, String>>> futures = new ArrayList<>();
|
||||
int i = 0;
|
||||
for (String shareLink : shareLinks) {
|
||||
|
||||
int finalI = ++i;
|
||||
futures.add(service.submit(() -> {
|
||||
|
||||
String url = "";
|
||||
String from = "";
|
||||
if (shareLink.matches(Util.patternUC)) {
|
||||
url = uc.detailContentVodPlayUrl(List.of(shareLink));
|
||||
from = uc.detailContentVodPlayFrom(List.of(shareLink), finalI);
|
||||
} else if (shareLink.matches(Util.patternQuark)) {
|
||||
url = quark.detailContentVodPlayUrl(List.of(shareLink));
|
||||
from = quark.detailContentVodPlayFrom(List.of(shareLink), finalI);
|
||||
}/* else if (shareLink.matches(Util.patternAli)) {
|
||||
protected String detailContentVodPlayUrl(List<String> shareLinks) throws Exception {
|
||||
List<String> urls = new ArrayList<>();
|
||||
for (String shareLink : shareLinks) {
|
||||
/* if (shareLink.matches(Util.patternUC)) {
|
||||
urls.add(uc.detailContentVodPlayUrl(List.of(shareLink)));
|
||||
} else */if (shareLink.matches(Util.patternQuark)) {
|
||||
urls.add(quark.detailContentVodPlayUrl(List.of(shareLink)));
|
||||
}/* else if (shareLink.matches(Util.patternAli)) {
|
||||
urls.add(ali.detailContentVodPlayUrl(List.of(shareLink)));
|
||||
} */ else if (shareLink.contains(URL_CONTAIN)) {
|
||||
url = tianYi.detailContentVodPlayUrl(List.of(shareLink));
|
||||
from = tianYi.detailContentVodPlayFrom(List.of(shareLink), finalI);
|
||||
} else if (shareLink.contains(YiDongYun.URL_START)) {
|
||||
url = yiDongYun.detailContentVodPlayUrl(List.of(shareLink));
|
||||
from = yiDongYun.detailContentVodPlayFrom(List.of(shareLink), finalI);
|
||||
} else if (shareLink.contains(BaiDuPan.URL_START)) {
|
||||
url = baiDuPan.detailContentVodPlayUrl(List.of(shareLink));
|
||||
from = baiDuPan.detailContentVodPlayFrom(List.of(shareLink), finalI);
|
||||
} else if (shareLink.matches(Pan123Api.regex)) {
|
||||
url = pan123.detailContentVodPlayUrl(List.of(shareLink));
|
||||
from = pan123.detailContentVodPlayFrom(List.of(shareLink), finalI);
|
||||
}
|
||||
return new ImmutablePair<>(url, from);
|
||||
}));
|
||||
|
||||
} */else if (shareLink.startsWith(URL_START)) {
|
||||
urls.add(tianYi.detailContentVodPlayUrl(List.of(shareLink)));
|
||||
} else if (shareLink.contains(YiDongYun.URL_START)) {
|
||||
urls.add(yiDongYun.detailContentVodPlayUrl(List.of(shareLink)));
|
||||
}else if (shareLink.contains(BaiDuPan.URL_START)) {
|
||||
urls.add(baiDuPan.detailContentVodPlayUrl(List.of(shareLink)));
|
||||
}
|
||||
|
||||
for (Future<ImmutablePair<String, String>> future : futures) {
|
||||
//只有连接不为空才放入进去
|
||||
if (StringUtils.isNoneBlank(future.get().left)) {
|
||||
urls.add(future.get().left);
|
||||
froms.add(future.get().right);
|
||||
}
|
||||
|
||||
}
|
||||
resultMap.put(Util.MD5(Json.toJson(shareLinks)), new ImmutablePair<>(urls, froms));
|
||||
|
||||
SpiderDebug.log("---urls:" + Json.toJson(urls));
|
||||
SpiderDebug.log("---froms:" + Json.toJson(froms));
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log("获取异步结果出错:" + e);
|
||||
} finally {
|
||||
service.shutdown();
|
||||
}
|
||||
return TextUtils.join("$$$", urls);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.crawler.Spider;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.github.catvod.bean.Class;
|
||||
import com.github.catvod.utils.Util;
|
||||
|
||||
public class Jable extends Spider {
|
||||
|
||||
private static final String siteUrl = "https://jable.tv";
|
||||
private static final String cateUrl = siteUrl + "/categories/";
|
||||
private static final String detailUrl = siteUrl + "/videos/";
|
||||
private static final String searchUrl = siteUrl + "/search/";
|
||||
|
||||
private HashMap<String, String> getHeaders() {
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("User-Agent", "PostmanRuntime/7.36.3");
|
||||
headers.put("Host", "jable.tv");
|
||||
headers.put("Postman-Token", "33290483-3c8d-413f-a160-0d3aea9e6f95");
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String homeContent(boolean filter) throws Exception {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
List<Class> classes = new ArrayList<>();
|
||||
Document doc = Jsoup.parse(OkHttp.string(cateUrl, getHeaders()));
|
||||
for (Element element : doc.select("div.img-box > a")) {
|
||||
String typeId = element.attr("href").split("/")[4];
|
||||
String typeName = element.select("div.absolute-center > h4").text();
|
||||
classes.add(new Class(typeId, typeName));
|
||||
}
|
||||
doc = Jsoup.parse(OkHttp.string(siteUrl, getHeaders()));
|
||||
for (Element element : doc.select("div.video-img-box")) {
|
||||
String pic = element.select("img").attr("data-src");
|
||||
String url = element.select("a").attr("href");
|
||||
String name = element.select("div.detail > h6").text();
|
||||
if (pic.endsWith(".gif") || name.isEmpty()) continue;
|
||||
String id = url.split("/")[4];
|
||||
list.add(new Vod(id, name, pic));
|
||||
}
|
||||
return Result.string(classes, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) throws Exception {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
String target = cateUrl + tid + "/?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=post_date&from=" + String.format(Locale.getDefault(), "%02d", Integer.parseInt(pg)) + "&_=" + System.currentTimeMillis();
|
||||
Document doc = Jsoup.parse(OkHttp.string(target, getHeaders()));
|
||||
for (Element element : doc.select("div.video-img-box")) {
|
||||
String pic = element.select("img").attr("data-src");
|
||||
String url = element.select("a").attr("href");
|
||||
String name = element.select("div.detail > h6").text();
|
||||
String id = url.split("/")[4];
|
||||
list.add(new Vod(id, name, pic));
|
||||
}
|
||||
return Result.string(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String detailContent(List<String> ids) throws Exception {
|
||||
Document doc = Jsoup.parse(OkHttp.string(detailUrl.concat(ids.get(0)).concat("/"), getHeaders()));
|
||||
String name = doc.select("meta[property=og:title]").attr("content");
|
||||
String pic = doc.select("meta[property=og:image]").attr("content");
|
||||
String year = doc.select("span.inactive-color").get(0).text();
|
||||
Vod vod = new Vod();
|
||||
vod.setVodId(ids.get(0));
|
||||
vod.setVodPic(pic);
|
||||
vod.setVodYear(year.replace("上市於 ", ""));
|
||||
vod.setVodName(name);
|
||||
vod.setVodPlayFrom("Jable");
|
||||
vod.setVodPlayUrl("播放$" + Util.getVar(doc.html(), "hlsUrl"));
|
||||
return Result.string(vod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick) throws Exception {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
Document doc = Jsoup.parse(OkHttp.string(searchUrl.concat(URLEncoder.encode(key)).concat("/"), getHeaders()));
|
||||
for (Element element : doc.select("div.video-img-box")) {
|
||||
String pic = element.select("img").attr("data-src");
|
||||
String url = element.select("a").attr("href");
|
||||
String name = element.select("div.detail > h6").text();
|
||||
String id = url.split("/")[4];
|
||||
list.add(new Vod(id, name, pic));
|
||||
}
|
||||
return Result.string(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
|
||||
return Result.get().url(id).header(getHeaders()).string();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.github.catvod.bean.Class;
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.crawler.Spider;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
import com.github.catvod.utils.Util;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Qile
|
||||
*/
|
||||
public class JavDb extends Spider {
|
||||
|
||||
private static String siteUrl = "https://javdb523.com";
|
||||
|
||||
@Override
|
||||
public void init(Context context, String extend) throws Exception {
|
||||
if (!extend.isEmpty()) siteUrl = extend;
|
||||
}
|
||||
|
||||
private Map<String, String> getHeader() {
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("User-Agent", Util.CHROME);
|
||||
header.put("Referer", siteUrl + "/");
|
||||
return header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String homeContent(boolean filter) throws Exception {
|
||||
List<Class> classes = new ArrayList<>();
|
||||
List<String> typeIds = Arrays.asList("", "censored", "uncensored", "western");
|
||||
List<String> typeNames = Arrays.asList("全部", "有码", "无码", "欧美");
|
||||
for (int i = 0; i < typeIds.size(); i++) classes.add(new Class(typeIds.get(i), typeNames.get(i)));
|
||||
Document doc = Jsoup.parse(OkHttp.string(siteUrl, getHeader()));
|
||||
List<Vod> list = new ArrayList<>();
|
||||
for (Element li : doc.select(".item")) {
|
||||
String vid = siteUrl + li.select("a").attr("href");
|
||||
String name = li.select("a").attr("title");
|
||||
String pic = li.select("img").attr("src");
|
||||
list.add(new Vod(vid, name, pic));
|
||||
}
|
||||
return Result.string(classes, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) throws Exception {
|
||||
String cateUrl = siteUrl + String.format("/%s?page=%s", tid, pg);
|
||||
Document doc = Jsoup.parse(OkHttp.string(cateUrl, getHeader()));
|
||||
List<Vod> list = new ArrayList<>();
|
||||
for (Element li : doc.select(".item")) {
|
||||
String vid = siteUrl + li.select("a").attr("href");
|
||||
String name = li.select("a").attr("title");
|
||||
String pic = li.select("img").attr("src");
|
||||
list.add(new Vod(vid, name, pic));
|
||||
}
|
||||
return Result.string(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String detailContent(List<String> ids) throws Exception {
|
||||
Document doc = Jsoup.parse(OkHttp.string(ids.get(0), getHeader()));
|
||||
if (doc.text().contains("歡迎登入")) return Result.error("该资源需要登入");
|
||||
List<String> vodItems = new ArrayList<>();
|
||||
Elements sourceList = doc.select(".item.columns");
|
||||
for (Element a : sourceList) {
|
||||
String episodeUrl = a.select("div a").attr("href");
|
||||
String episodeName = a.select("div a").text();
|
||||
vodItems.add(episodeName + "$" + episodeUrl);
|
||||
}
|
||||
Elements elements = doc.select(".panel-block");
|
||||
String classifyName = "";
|
||||
String year = "";
|
||||
String area = "";
|
||||
String remark = "";
|
||||
for (Element element : elements) {
|
||||
String text = element.text();
|
||||
if (text.startsWith("類別:")) {
|
||||
classifyName = element.select("span a").text();
|
||||
} else if (text.startsWith("片商:")) {
|
||||
area = element.select("span a").text();
|
||||
} else if (text.startsWith("日期:")) {
|
||||
year = element.select("span").text();
|
||||
} else if (text.startsWith("時長:")) {
|
||||
remark = element.select("span").text();
|
||||
}
|
||||
}
|
||||
Vod vod = new Vod();
|
||||
vod.setVodId(ids.get(0));
|
||||
vod.setVodYear(year);
|
||||
vod.setVodArea(area);
|
||||
vod.setVodRemarks(remark);
|
||||
vod.setTypeName(classifyName);
|
||||
vod.setVodContent(ids.get(0));
|
||||
vod.setVodPlayFrom("Qile");
|
||||
vod.setVodPlayUrl(TextUtils.join("#", vodItems));
|
||||
return Result.string(vod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick) throws Exception {
|
||||
String searchUrl = siteUrl + "/search?q=" + Uri.encode(key) + "&f=all";
|
||||
Document doc = Jsoup.parse(OkHttp.string(searchUrl, getHeader()));
|
||||
List<Vod> list = new ArrayList<>();
|
||||
for (Element li : doc.select(".item")) {
|
||||
String vid = siteUrl + li.select("a").attr("href");
|
||||
String name = li.select("a").attr("title");
|
||||
String pic = li.select("img").attr("src");
|
||||
list.add(new Vod(vid, name, pic));
|
||||
}
|
||||
return Result.string(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
|
||||
return Result.get().url(id).header(getHeader()).string();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import com.github.catvod.api.Pan123Api;
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.crawler.Spider;
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author lushunming
|
||||
*/
|
||||
public class Pan123 extends Spider {
|
||||
|
||||
|
||||
@Override
|
||||
public void init(Context context, String extend) throws Exception {
|
||||
|
||||
if (StringUtils.isNoneBlank(extend)) {
|
||||
// Pan123Api.INSTANCE.setAuth(extend);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String detailContent(List<String> ids) throws Exception {
|
||||
|
||||
@NotNull Map<@NotNull String, @NotNull String> shareData = Pan123Api.INSTANCE.getShareData(ids.get(0));
|
||||
return Result.string(Pan123Api.INSTANCE.getVod(shareData.get("key"), shareData.get("sharePwd")));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
|
||||
return Pan123Api.INSTANCE.playerContent(id, flag);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 獲取詳情內容視頻播放來源(多 shared_link)
|
||||
*
|
||||
* @param ids share_link 集合
|
||||
* @param
|
||||
* @return 詳情內容視頻播放來源
|
||||
*/
|
||||
public String detailContentVodPlayFrom(List<String> ids, int index) {
|
||||
List<String> playFrom = new ArrayList<>();
|
||||
/* if (ids.size() < 2){
|
||||
return TextUtils.join("$$$", Pan123Api.INSTANCE.getPlayFormatList());
|
||||
}*/
|
||||
|
||||
for (int i = 1; i <= ids.size(); i++) {
|
||||
|
||||
for (String s : Pan123Api.INSTANCE.getPlayFormatList()) {
|
||||
playFrom.add(String.format(Locale.getDefault(), "pan123" + s + "#%02d_%02d", i, index));
|
||||
|
||||
}
|
||||
// playFrom.add("天意" + i + index);
|
||||
}
|
||||
return TextUtils.join("$$$", playFrom);
|
||||
}
|
||||
|
||||
/**
|
||||
* 獲取詳情內容視頻播放地址(多 share_link)
|
||||
*
|
||||
* @param ids share_link 集合
|
||||
* @return 詳情內容視頻播放地址
|
||||
*/
|
||||
public String detailContentVodPlayUrl(List<String> ids){
|
||||
List<String> playUrl = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
@NotNull Map<@NotNull String, @NotNull String> shareData = Pan123Api.INSTANCE.getShareData(id);
|
||||
try {
|
||||
playUrl.add(Pan123Api.INSTANCE.getVod(shareData.get("key"), shareData.get("sharePwd")).getVodPlayUrl());
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log("获取播放地址出错:" + e.getMessage());
|
||||
playUrl.add("");
|
||||
}
|
||||
}
|
||||
return TextUtils.join("$$$", playUrl);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ import com.github.catvod.bean.Result;
|
|||
import com.github.catvod.bean.Sub;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.crawler.Spider;
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
import com.github.catvod.utils.Image;
|
||||
import com.github.catvod.utils.Util;
|
||||
|
|
@ -20,54 +19,31 @@ import java.util.List;
|
|||
|
||||
public class Push extends Spider {
|
||||
|
||||
private Cloud cloud;
|
||||
private final Ali ali;
|
||||
|
||||
public Push() {
|
||||
cloud = new Cloud();
|
||||
ali = new Ali();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Context context, String extend) {
|
||||
try {
|
||||
cloud.init(context, extend);
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log("Cloud init error: " + e.getMessage());
|
||||
}
|
||||
ali.init(context, extend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String detailContent(List<String> ids) throws Exception {
|
||||
String url = ids.get(0);
|
||||
|
||||
// 使用Cloud类处理各种云盘链接
|
||||
String cloudResult = cloud.detailContent(ids);
|
||||
if (cloudResult != null) {
|
||||
return cloudResult;
|
||||
}
|
||||
|
||||
// 如果不是云盘链接,返回普通链接处理结果
|
||||
return Result.string(vod(url));
|
||||
if (Ali.pattern.matcher(ids.get(0)).find()) return ali.detailContent(ids);
|
||||
return Result.string(vod(ids.get(0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String playerContent(String flag, String id, List<String> vipFlags) {
|
||||
try {
|
||||
// 使用Cloud类处理云盘链接的播放
|
||||
String cloudResult = cloud.playerContent(flag, id, vipFlags);
|
||||
if (cloudResult != null) {
|
||||
return cloudResult;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log("Cloud playerContent error: " + e.getMessage());
|
||||
}
|
||||
|
||||
// 原有逻辑处理其他类型链接
|
||||
if (id.startsWith("http") && id.contains("***")) id = id.replace("***", "#");
|
||||
if (flag.equals("直連")) return Result.get().url(id).subs(getSubs(id)).string();
|
||||
if (flag.equals("解析")) return Result.get().parse().jx().url(id).string();
|
||||
if (flag.equals("嗅探")) return Result.get().parse().url(id).string();
|
||||
if (flag.equals("迅雷")) return Result.get().url(id).string();
|
||||
return Result.get().url(id).string();
|
||||
return ali.playerContent(flag, id, vipFlags);
|
||||
}
|
||||
|
||||
private Vod vod(String url) {
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ public class Quark extends Spider {
|
|||
}*/
|
||||
|
||||
for (int i = 1; i <= ids.size(); i++) {
|
||||
playFrom.add(String.format("quark原画#%02d_%02d" ,i , index));
|
||||
playFrom.add("quark原画" + i + index);
|
||||
for (String s : QuarkApi.get().getPlayFormatList()) {
|
||||
playFrom.add(String.format(Locale.getDefault(), "quark" + s + "#%02d_%02d", i, index));
|
||||
playFrom.add(String.format(Locale.getDefault(), "quark" + s + "#%02d%02d", i, index));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -70,15 +70,14 @@ public class Quark extends Spider {
|
|||
* @param ids share_link 集合
|
||||
* @return 詳情內容視頻播放地址
|
||||
*/
|
||||
public String detailContentVodPlayUrl(List<String> ids) {
|
||||
public String detailContentVodPlayUrl(List<String> ids) throws Exception {
|
||||
List<String> playUrl = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
ShareData shareData = QuarkApi.get().getShareData(id);
|
||||
try {
|
||||
playUrl.add(QuarkApi.get().getVod(shareData)==null?"":QuarkApi.get().getVod(shareData).getVodPlayUrl());
|
||||
playUrl.add(QuarkApi.get().getVod(shareData).getVodPlayUrl());
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log("获取播放地址出错:" + e.getMessage());
|
||||
playUrl.add("");
|
||||
}
|
||||
}
|
||||
return TextUtils.join("$$$", playUrl);
|
||||
|
|
|
|||
|
|
@ -1,192 +0,0 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Qupans extends Cloud {
|
||||
|
||||
private static final String BASE_URL = "https://www.qupanshe.com";
|
||||
private static final String DEFAULT_COVER_URL = "https://fs-im-kefu.7moor-fs1.com/ly/4d2c3f00-7d4c-11e5-af15-41bf63ae4ea0/1743950734122/baidu.jpg";
|
||||
|
||||
private String get(String url) {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
|
||||
headers.put("Referer", BASE_URL);
|
||||
return OkHttp.string(url, headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String homeContent(boolean filter) {
|
||||
try {
|
||||
JSONObject result = new JSONObject();
|
||||
JSONArray classes = new JSONArray();
|
||||
String[][] types = {{"电影","3"}, {"电视剧","2"}, {"综艺","4"}, {"动漫","5"}, {"纪录片","6"}};
|
||||
for (String[] type : types) {
|
||||
JSONObject cls = new JSONObject();
|
||||
cls.put("type_id", type[1]);
|
||||
cls.put("type_name", type[0]);
|
||||
classes.put(cls);
|
||||
}
|
||||
result.put("class", classes);
|
||||
return result.toString();
|
||||
} catch (Exception e) {
|
||||
return "{\"class\":[]}";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) {
|
||||
try {
|
||||
String html = get(BASE_URL + "/forum.php?mod=forumdisplay&fid=" + tid + "&page=" + pg);
|
||||
Document doc = Jsoup.parse(html);
|
||||
JSONArray list = new JSONArray();
|
||||
|
||||
for (Element item : doc.select("div.tit_box > a.s")) {
|
||||
String title = item.text();
|
||||
if (title.contains("公告") || title.contains("求")) continue;
|
||||
JSONObject vod = new JSONObject();
|
||||
vod.put("vod_id", item.attr("href"));
|
||||
vod.put("vod_name", title);
|
||||
vod.put("vod_pic", DEFAULT_COVER_URL);
|
||||
vod.put("vod_remarks", "");
|
||||
list.put(vod);
|
||||
}
|
||||
|
||||
return new JSONObject()
|
||||
.put("list", list)
|
||||
.put("page", pg)
|
||||
.put("pagecount", "0")
|
||||
.put("total", "0")
|
||||
.toString();
|
||||
} catch (Exception e) {
|
||||
return "{\"list\":[]}";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String detailContent(List<String> ids) {
|
||||
try {
|
||||
String vodId = ids.get(0);
|
||||
String html = get(vodId.startsWith("http") ? vodId : BASE_URL + "/" + vodId);
|
||||
Document doc = Jsoup.parse(html);
|
||||
|
||||
Vod vod = new Vod();
|
||||
vod.setVodId(vodId);
|
||||
vod.setVodName(doc.select("h1").first().text());
|
||||
vod.setVodPic(DEFAULT_COVER_URL);
|
||||
|
||||
List<String> links = getLinks(doc);
|
||||
if (!links.isEmpty()) {
|
||||
String pwd = getPwd(doc);
|
||||
for (int i = 0; i < links.size(); i++) {
|
||||
String link = links.get(i);
|
||||
if (!link.contains("pwd=") && !TextUtils.isEmpty(pwd)) {
|
||||
links.set(i, link + "?pwd=" + pwd);
|
||||
}
|
||||
}
|
||||
vod.setVodPlayFrom(super.detailContentVodPlayFrom(links));
|
||||
vod.setVodPlayUrl(super.detailContentVodPlayUrl(links));
|
||||
}
|
||||
|
||||
return Result.string(vod);
|
||||
} catch (Exception e) {
|
||||
Vod vod = new Vod();
|
||||
vod.setVodId(ids.get(0));
|
||||
vod.setVodName("加载失败");
|
||||
vod.setVodPic(DEFAULT_COVER_URL);
|
||||
return Result.string(vod);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getLinks(Document doc) {
|
||||
List<String> links = new ArrayList<>();
|
||||
// 从a标签中提取链接
|
||||
Elements linksElements = doc.select("a");
|
||||
for (Element linkElement : linksElements) {
|
||||
String href = linkElement.attr("href");
|
||||
if (href.contains(".baidu")) {
|
||||
links.add(href);
|
||||
break; // 只提取第一个百度网盘链接
|
||||
}
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
private String getPwd(Document doc) {
|
||||
try {
|
||||
// 使用正则表达式模式提取密码
|
||||
String patternStr = "提取码:\\s*([A-Za-z0-9]{4})";
|
||||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(patternStr);
|
||||
Element contentElement = doc.select("td.t_f").first();
|
||||
if (contentElement != null) {
|
||||
String text = contentElement.text();
|
||||
java.util.regex.Matcher matcher = pattern.matcher(text);
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略异常
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick) {
|
||||
return searchContent(key, quick, "1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick, String pg) {
|
||||
try {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("searchsubmit", "yes");
|
||||
params.put("srchtxt", key);
|
||||
String[] fids = {"2", "3", "4", "5", "6"};
|
||||
for (int i = 0; i < fids.length; i++) params.put("srchfid[" + i + "]", fids[i]);
|
||||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
|
||||
headers.put("content-type", "application/x-www-form-urlencoded");
|
||||
|
||||
String html = OkHttp.post(BASE_URL + "/search.php?mod=forum", params, headers).getBody();
|
||||
Document doc = Jsoup.parse(html);
|
||||
|
||||
JSONArray list = new JSONArray();
|
||||
for (Element item : doc.select("#threadlist ul li h3 > a")) {
|
||||
JSONObject vod = new JSONObject();
|
||||
vod.put("vod_id", item.attr("href"));
|
||||
vod.put("vod_name", item.text());
|
||||
vod.put("vod_pic", DEFAULT_COVER_URL);
|
||||
vod.put("vod_remarks", "");
|
||||
list.put(vod);
|
||||
}
|
||||
|
||||
return new JSONObject()
|
||||
.put("list", list)
|
||||
.put("page", pg)
|
||||
.put("pagecount", "1")
|
||||
.put("total", list.length())
|
||||
.toString();
|
||||
} catch (Exception e) {
|
||||
return "{\"list\":[]}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,248 +0,0 @@
|
|||
package com.github.catvod.spider
|
||||
|
||||
|
||||
import android.content.Context
|
||||
import com.github.catvod.bean.Class
|
||||
import com.github.catvod.bean.Filter
|
||||
import com.github.catvod.bean.Result
|
||||
import com.github.catvod.bean.Vod
|
||||
import com.github.catvod.net.OkHttp
|
||||
import com.github.catvod.utils.Util
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import kotlinx.coroutines.*
|
||||
import okhttp3.HttpUrl
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import java.net.URLEncoder
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
* @author lushunming
|
||||
*/
|
||||
class SeedHub : Cloud() {
|
||||
private val siteUrl = "https://www.seedhub.cc"
|
||||
private val regexCategory: Pattern = Pattern.compile("/vodtype/(\\w+).html")
|
||||
private val regexPageTotal: Pattern = Pattern.compile("\\$\\(\"\\.mac_total\"\\)\\.text\\('(\\d+)'\\);")
|
||||
|
||||
private var extend: JsonObject? = null
|
||||
|
||||
|
||||
private val header: MutableMap<String?, String?>
|
||||
get() {
|
||||
val header: MutableMap<String?, String?> = HashMap<String?, String?>()
|
||||
header.put("User-Agent", Util.MOBILE)
|
||||
return header
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun init(context: Context, extend: String) {
|
||||
this.extend = JsonParser.parseString(extend).getAsJsonObject()
|
||||
super.init(context, "")
|
||||
}
|
||||
|
||||
override fun homeContent(filter: Boolean): String? {
|
||||
val classes: MutableList<Class?> = ArrayList<Class?>()
|
||||
val filters = LinkedHashMap<String?, MutableList<Filter?>?>()
|
||||
|
||||
|
||||
val html = OkHttp.string(siteUrl, this.header)
|
||||
val doc = Jsoup.parse(html)
|
||||
|
||||
parseClassFromDoc(doc, classes)
|
||||
if (filter) {
|
||||
parseFilterFromDoc(doc, filters)
|
||||
}
|
||||
|
||||
return Result.string(classes, parseVodListFromDoc(doc), filters)
|
||||
}
|
||||
|
||||
private fun parseFilterFromDoc(
|
||||
doc: Document, filters: LinkedHashMap<String?, MutableList<Filter?>?>
|
||||
) {
|
||||
|
||||
val groups = doc.select("div.sidebar-group")
|
||||
for (group in groups) {
|
||||
val clazz = group.select("p.sidebar-heading a")
|
||||
if (clazz.attr("href").startsWith("/")) {
|
||||
val name = clazz.text()
|
||||
val url = clazz.attr("href")
|
||||
val filter = group.select("ul.sidebar-sub-headers>li.sidebar-sub-header>a")
|
||||
val filterList: MutableList<Filter?> = ArrayList<Filter?>()
|
||||
val values: MutableList<Filter.Value> = ArrayList<Filter.Value>()
|
||||
for (f in filter) {
|
||||
val filterName = f.text()
|
||||
val filterUrl = f.attr("href")
|
||||
values.add(Filter.Value(filterName, filterUrl))
|
||||
}
|
||||
filterList.add(Filter("0", "分类", values))
|
||||
filters[url] = filterList
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*获取分类
|
||||
*/
|
||||
private fun parseClassFromDoc(
|
||||
doc: Document, classes: MutableList<Class?>
|
||||
) {
|
||||
val navs = doc.select("div.nav-item")
|
||||
for (nav in navs) {
|
||||
val link = nav.select("a")
|
||||
if (link.attr("href").startsWith("/")) {
|
||||
val name = nav.select("a").text()
|
||||
val url = nav.select("a").attr("href")
|
||||
classes.add(Class(url, name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun categoryContent(
|
||||
tid: String?, pg: String, filter: Boolean, extend: HashMap<String, String?>?
|
||||
): String? {
|
||||
var urlParams = tid
|
||||
if (extend != null && extend.size > 0) {
|
||||
extend.keys.forEach {
|
||||
urlParams = extend[it]
|
||||
}
|
||||
}
|
||||
val doc = Jsoup.parse(
|
||||
OkHttp.string(
|
||||
String.format("%s%s?page=%s", siteUrl, urlParams, pg), this.header
|
||||
)
|
||||
)
|
||||
val page = pg.toInt()
|
||||
val limit = 20
|
||||
val total = Int.MAX_VALUE
|
||||
|
||||
|
||||
return Result.get().vod(parseVodListFromDoc(doc)).page(page, 0, limit, total).string()
|
||||
}
|
||||
|
||||
private fun parseVodListFromDoc(doc: Document): MutableList<Vod?> {
|
||||
val list: MutableList<Vod?> = ArrayList<Vod?>()
|
||||
val elements = doc.select("div.cover")
|
||||
for (e in elements) {
|
||||
val vodId = e.selectFirst(" a")!!.attr("href")
|
||||
var vodPic = e.selectFirst("img")!!.attr("src")
|
||||
if (!vodPic.startsWith("http")) {
|
||||
vodPic = siteUrl + vodPic
|
||||
}
|
||||
val vodName = e.selectFirst("h2")!!.text()
|
||||
val vodRemarks = e.select("ul >li")!!.text()
|
||||
list.add(Vod(vodId, vodName, vodPic, vodRemarks))
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun detailContent(ids: MutableList<String?>): String? {
|
||||
|
||||
val vodId = ids.get(0)
|
||||
val doc = Jsoup.parse(
|
||||
OkHttp.string(
|
||||
siteUrl + vodId, this.header
|
||||
)
|
||||
)
|
||||
val infos = doc.select("div.cover-container >ul > li").text().replace(" ", "")
|
||||
val item = Vod()
|
||||
item.setVodId(vodId)
|
||||
item.setVodName(doc.selectFirst("h1")!!.text())
|
||||
item.setVodPic(doc.selectFirst("div.cover-container img")!!.attr("src"))
|
||||
item.setVodArea(Util.getStrByRegex(Pattern.compile("制片国家/地区:(.*?)语言:"), infos))
|
||||
item.setTypeName(Util.getStrByRegex(Pattern.compile("类型:(.*?)制片"), infos))
|
||||
item.setVodDirector(Util.getStrByRegex(Pattern.compile("导演:(.*?)制片"), infos))
|
||||
item.setVodActor(Util.getStrByRegex(Pattern.compile("主演:(.*?)类型"), infos))
|
||||
item.setVodYear(Util.getStrByRegex(Pattern.compile("首播:(.*?)集数"), infos))
|
||||
item.setVodRemarks(Util.getStrByRegex(Pattern.compile("豆瓣评分:(.*?)常用标签"), infos))
|
||||
item.vodContent = doc.select("div.content > p").text()
|
||||
|
||||
val shareLinks: CopyOnWriteArrayList<String?> = CopyOnWriteArrayList<String?>()
|
||||
val jobs = ArrayList<Job>()
|
||||
|
||||
runBlocking {
|
||||
val docEle = doc.select("ul.pan-links > li > a")
|
||||
docEle.filter { it.attr("data-link").contains("uc") }.take(2).forEach { element ->
|
||||
|
||||
jobs += CoroutineScope(Dispatchers.IO).launch {
|
||||
var link = siteUrl + element.attr("href")
|
||||
val movieTitle = HttpUrl.parse(link)?.queryParameter("movie_title")
|
||||
link = HttpUrl.parse(link)?.newBuilder()?.removeAllQueryParameters("movie_title")
|
||||
?.addEncodedQueryParameter(
|
||||
"movie_title", URLEncoder.encode(movieTitle)
|
||||
)?.build().toString()
|
||||
val string = OkHttp.string(link, header)
|
||||
val docEle = Jsoup.parse(string)
|
||||
docEle.select("a.direct-pan").attr("href").let {
|
||||
if (it.isNotEmpty()) {
|
||||
shareLinks.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
docEle.filter { it.attr("data-link").contains("baidu") }.take(2).forEach { element ->
|
||||
|
||||
jobs += CoroutineScope(Dispatchers.IO).launch {
|
||||
var link = siteUrl + element.attr("href")
|
||||
val movieTitle = HttpUrl.parse(link)?.queryParameter("movie_title")
|
||||
link = HttpUrl.parse(link)?.newBuilder()?.removeAllQueryParameters("movie_title")
|
||||
?.addEncodedQueryParameter(
|
||||
"movie_title", URLEncoder.encode(movieTitle)
|
||||
)?.build().toString()
|
||||
val string = OkHttp.string(link, header)
|
||||
val docEle = Jsoup.parse(string)
|
||||
docEle.select("a.direct-pan").attr("href").let {
|
||||
if (it.isNotEmpty()) {
|
||||
shareLinks.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
docEle.filter { it.attr("data-link").contains("quark") }.take(2).forEach { element ->
|
||||
|
||||
jobs += CoroutineScope(Dispatchers.IO).launch {
|
||||
var link = siteUrl + element.attr("href")
|
||||
val movieTitle = HttpUrl.parse(link)?.queryParameter("movie_title")
|
||||
link = HttpUrl.parse(link)?.newBuilder()?.removeAllQueryParameters("movie_title")
|
||||
?.addEncodedQueryParameter(
|
||||
"movie_title", URLEncoder.encode(movieTitle)
|
||||
)?.build().toString()
|
||||
val string = OkHttp.string(link, header)
|
||||
val docEle = Jsoup.parse(string)
|
||||
docEle.select("a.direct-pan").attr("href").let {
|
||||
if (it.isNotEmpty()) {
|
||||
shareLinks.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs.joinAll()
|
||||
item.vodPlayUrl = super.detailContentVodPlayUrl(java.util.ArrayList(shareLinks))
|
||||
item.setVodPlayFrom(super.detailContentVodPlayFrom(java.util.ArrayList(shareLinks)))
|
||||
|
||||
|
||||
}
|
||||
return Result.string(item)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun searchContent(key: String?, quick: Boolean): String? {
|
||||
return searchContent(key, "1")
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun searchContent(key: String?, quick: Boolean, pg: String?): String? {
|
||||
return searchContent(key, pg)
|
||||
}
|
||||
|
||||
private fun searchContent(key: String?, pg: String?): String? {
|
||||
val searchURL = siteUrl + String.format("/s/%s/?page=%s", URLEncoder.encode(key), pg)
|
||||
val html = OkHttp.string(searchURL, this.header)
|
||||
val doc = Jsoup.parse(html)
|
||||
|
||||
return Result.string(parseVodListFromDoc(doc))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
|
||||
import com.github.catvod.bean.Class;
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.crawler.Spider;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
import com.github.catvod.utils.ProxyVideo;
|
||||
import com.github.catvod.utils.Util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
|
||||
public class Supjav extends Spider {
|
||||
|
||||
private static final String siteUrl = "https://supjav.com/zh/";
|
||||
private static final String playUrl = "https://lk1.supremejav.com/";
|
||||
|
||||
private HashMap<String, String> getHeaders() {
|
||||
return getHeaders(siteUrl);
|
||||
}
|
||||
|
||||
private HashMap<String, String> getHeaders(String referer) {
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("Referer", "https://supjav.com/");
|
||||
headers.put("Host", "supjav.com");
|
||||
headers.put("User-Agent", Util.CHROME);
|
||||
return headers;
|
||||
}
|
||||
|
||||
private HashMap<String, String> getTVVideoHeaders(String referer) {
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("Referer", referer);
|
||||
headers.put("User-Agent", Util.CHROME);
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String homeContent(boolean filter) {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
List<Class> classes = new ArrayList<>();
|
||||
Document doc = Jsoup.parse(OkHttp.string(siteUrl, getHeaders()));
|
||||
for (Element element : doc.select("ul.nav > li > a")) {
|
||||
String href = element.attr("href");
|
||||
if (href.split("/").length < 5) continue;
|
||||
String typeId = href.replace(siteUrl, "");
|
||||
String typeName = element.text();
|
||||
classes.add(new Class(typeId, typeName));
|
||||
}
|
||||
for (Element element : doc.select("div.post")) {
|
||||
String src = element.select("img").attr("src");
|
||||
String data = element.select("img").attr("data-original");
|
||||
String url = element.select("a").attr("href");
|
||||
String name = element.select("a").attr("title");
|
||||
String pic = StringUtils.isEmpty(data) ? src : data;
|
||||
String id = url.split("/")[4];
|
||||
list.add(new Vod(id, name, pic));
|
||||
}
|
||||
return Result.string(classes, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
Document doc = Jsoup.parse(OkHttp.string(siteUrl + tid + "/page/" + pg, getHeaders()));
|
||||
for (Element element : doc.select("div.post")) {
|
||||
String pic = element.select("img").attr("data-original");
|
||||
String url = element.select("a").attr("href");
|
||||
String name = element.select("a").attr("title");
|
||||
String id = url.split("/")[4];
|
||||
list.add(new Vod(id, name, pic));
|
||||
}
|
||||
return Result.string(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String detailContent(List<String> ids) {
|
||||
Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat(ids.get(0)), getHeaders()));
|
||||
String name = doc.select("div.post-meta > img").attr("alt");
|
||||
String img = doc.select("div.post-meta > img").attr("src");
|
||||
String type = doc.select("p.cat > a").text();
|
||||
String director = "", actor = "";
|
||||
for (Element p : doc.select("div.cats > p")) {
|
||||
if (p.select("span").text().contains("Maker")) {
|
||||
director = p.select("a").text();
|
||||
}
|
||||
if (p.select("span").text().contains("Cast")) {
|
||||
actor = p.select("a").text();
|
||||
}
|
||||
}
|
||||
|
||||
Vod vod = new Vod();
|
||||
vod.setVodId(ids.get(0));
|
||||
vod.setVodPic(img);
|
||||
vod.setVodName(name);
|
||||
vod.setVodActor(actor);
|
||||
vod.setVodDirector(director);
|
||||
vod.setTypeName(type);
|
||||
|
||||
Map<String, String> sites = new LinkedHashMap<>();
|
||||
Elements sources = doc.select("a.btn-server");
|
||||
for (int i = 0; i < sources.size(); i++) {
|
||||
Element source = sources.get(i);
|
||||
String sourceName = source.text();
|
||||
if (sourceName.equals("TV")) continue;
|
||||
String sourceUrl = source.attr("data-link");
|
||||
sites.put(sourceName, "播放" + "$" + sourceUrl);
|
||||
}
|
||||
if (!sites.isEmpty()) {
|
||||
vod.setVodPlayFrom(StringUtils.join(sites.keySet(), "$$$"));
|
||||
vod.setVodPlayUrl(StringUtils.join(sites.values(), "$$$"));
|
||||
}
|
||||
return Result.string(vod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick) throws UnsupportedEncodingException {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat("?s=").concat(URLEncoder.encode(key, "UTF-8")), getHeaders()));
|
||||
for (Element element : doc.select("div.post")) {
|
||||
String pic = element.select("img").attr("data-original");
|
||||
String url = element.select("a").attr("href");
|
||||
String name = element.select("a").attr("title");
|
||||
String id = url.split("/")[4];
|
||||
list.add(new Vod(id, name, pic));
|
||||
}
|
||||
return Result.string(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String playerContent(String flag, String id, List<String> vipFlags) throws URISyntaxException, IOException {
|
||||
String redirect = OkHttp.getLocation(playUrl + "supjav.php?c=" + new StringBuilder(id).reverse(), getTVVideoHeaders(playUrl + "supjav.php?l=" + id + "&bg=undefined"));
|
||||
switch (flag) {
|
||||
case "TV":
|
||||
return parseTV(redirect);
|
||||
case "ST":
|
||||
return parseST(redirect);
|
||||
case "FST":
|
||||
return parseFST(redirect);
|
||||
case "VOE":
|
||||
return parseVOE(redirect);
|
||||
default:
|
||||
return Result.get().url(id).parse().string();
|
||||
}
|
||||
}
|
||||
|
||||
private String parseVOE(String redirect) {
|
||||
String data = OkHttp.string(redirect, getTVVideoHeaders(playUrl));
|
||||
redirect = Util.findByRegex("window.location.href = '(.*?)';", data, 1);
|
||||
data = OkHttp.string(redirect, getTVVideoHeaders(playUrl));
|
||||
String url=Util.findByRegex("prompt\\(\"Node\",(.*?)\\);", data, 1).trim().replace("\"", "");
|
||||
|
||||
return Result.get().url(ProxyVideo.buildCommonProxyUrl(url, Util.webHeaders(redirect))).header(getHeaders(redirect)).string();
|
||||
}
|
||||
|
||||
private String parseFST(String redirect) {
|
||||
String data = OkHttp.string(redirect, getTVVideoHeaders(playUrl));
|
||||
return Result.get().url(Util.findByRegex("file:\"(.*?)\"}]", data, 1)).header(getHeaders(redirect)).string();
|
||||
}
|
||||
|
||||
private String parseTV(String redirect) throws MalformedURLException {
|
||||
String data = OkHttp.string(redirect, getTVVideoHeaders(Util.getHost(redirect)));
|
||||
return Result.get().url(Util.getVar(data, "urlPlay")).header(getTVVideoHeaders(Util.getHost(redirect))).string();
|
||||
}
|
||||
|
||||
private String parseST(String redirect) throws IOException {
|
||||
String data = OkHttp.string(redirect, getTVVideoHeaders(playUrl));
|
||||
String robot = Jsoup.parse(data).getElementById("robotlink").text();
|
||||
robot = robot.substring(0, robot.indexOf("&token=") + 7);
|
||||
for (String text : data.split("&token=")) {
|
||||
if (!text.contains("').substring(")) continue;
|
||||
robot = "https:/" + robot + text.split("'")[0] + "&stream=1";
|
||||
String url = OkHttp.getLocation(robot, getTVVideoHeaders(redirect));
|
||||
return Result.get().url(ProxyVideo.buildCommonProxyUrl(url, Util.webHeaders(robot))).header(getHeaders(redirect)).string();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String parseDS(String redirect) throws URISyntaxException, IOException {
|
||||
String host = "https://" + Util.getHost(redirect);
|
||||
redirect = host + OkHttp.getLocation(redirect, getTVVideoHeaders(playUrl));
|
||||
String data = OkHttp.string(redirect, getHeaders());
|
||||
for (String text : data.split("'")) {
|
||||
if (!text.startsWith("/pass_md5/")) continue;
|
||||
String token = text.split("/")[3];
|
||||
String url = OkHttp.string(host + text, getHeaders(redirect));
|
||||
url = url + getDSRnd() + "?token=" + token + "&expiry=" + System.currentTimeMillis();
|
||||
return Result.get().url(url).header(getHeaders(redirect)).string();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String getDSRnd() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
for (int o = 0; o < 10; o++)
|
||||
sb.append(t.charAt((int) Math.floor(Math.random() * t.length())));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
package com.github.catvod.spider
|
||||
|
||||
import com.github.catvod.bean.Result
|
||||
import com.github.catvod.bean.Vod
|
||||
import com.github.catvod.net.OkHttp
|
||||
import com.github.catvod.utils.Json
|
||||
import com.github.catvod.utils.Util
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
* @author zhixc
|
||||
*/
|
||||
class Tg123Search : Cloud() {
|
||||
private val URL = "https://tgsou.252035.xyz/"
|
||||
|
||||
private val header: Map<String, String>
|
||||
get() {
|
||||
val header: MutableMap<String, String> = HashMap()
|
||||
header["User-Agent"] = Util.CHROME
|
||||
return header
|
||||
}
|
||||
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun searchContent(key: String, quick: Boolean): String {
|
||||
val url =
|
||||
URL + "?channelUsername=wp123zy,xx123pan,yp123pan,zyfb123&pic=true&keyword=" + URLEncoder.encode(
|
||||
key, Charset.defaultCharset().name()
|
||||
)
|
||||
val list: MutableList<Vod> = ArrayList()
|
||||
val html = OkHttp.string(url, header)
|
||||
val json = Json.safeObject(html);
|
||||
json["results"].asJsonArray.forEach { element ->
|
||||
val array = element.asString.split("$$$")
|
||||
if (array.size >= 2 && array[1].isNotEmpty()) {
|
||||
array[1].split("##").forEach {
|
||||
|
||||
|
||||
val id = it.split("@")[0]
|
||||
val pic = it.split("@")[1].split("$$")[0]
|
||||
val name = it.split("@")[1].split("$$")[1]
|
||||
|
||||
list.add(Vod(id, name, pic, ""))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return Result.string(list)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,8 +3,8 @@ package com.github.catvod.spider
|
|||
import com.github.catvod.bean.Result
|
||||
import com.github.catvod.bean.Vod
|
||||
import com.github.catvod.net.OkHttp
|
||||
import com.github.catvod.utils.Json
|
||||
import com.github.catvod.utils.Util
|
||||
import org.jsoup.Jsoup
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.Charset
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ import java.nio.charset.Charset
|
|||
* @author zhixc
|
||||
*/
|
||||
class Tg189Search : Cloud() {
|
||||
private val URL = "https://tgsou.252035.xyz/"
|
||||
private val URL = "https://tg.252035.xyz/"
|
||||
|
||||
private val header: Map<String, String>
|
||||
get() {
|
||||
|
|
@ -30,24 +30,16 @@ class Tg189Search : Cloud() {
|
|||
)
|
||||
val list: MutableList<Vod> = ArrayList()
|
||||
val html = OkHttp.string(url, header)
|
||||
val json = Json.safeObject(html);
|
||||
json["results"].asJsonArray.forEach { element ->
|
||||
val array = element.asString.split("$$$")
|
||||
if (array.size >= 2 && array[1].isNotEmpty()) {
|
||||
array[1].split("##").forEach {
|
||||
|
||||
|
||||
val id = it.split("@")[0]
|
||||
val pic = it.split("@")[1].split("$$")[0]
|
||||
val name = it.split("@")[1].split("$$")[1]
|
||||
|
||||
list.add(Vod(id, name, pic, ""))
|
||||
}
|
||||
|
||||
val arr = html.split(":I".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (arr.isNotEmpty()) {
|
||||
for (s in arr) {
|
||||
val doc = Jsoup.parse(s)
|
||||
val id = doc.select(" a").eachAttr("href")
|
||||
.first { it.contains("189") || it.contains("139") }
|
||||
val name=doc.select("strong").text()
|
||||
|
||||
list.add(Vod(id, name, "", ""))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package com.github.catvod.spider
|
|||
import com.github.catvod.bean.Result
|
||||
import com.github.catvod.bean.Vod
|
||||
import com.github.catvod.net.OkHttp
|
||||
import com.github.catvod.utils.Json
|
||||
import com.github.catvod.utils.Util
|
||||
import org.jsoup.Jsoup
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.Charset
|
||||
|
||||
|
|
@ -12,11 +12,12 @@ import java.nio.charset.Charset
|
|||
* @author zhixc
|
||||
*/
|
||||
class TgQuarkSearch : Cloud() {
|
||||
private val URL = "https://tgsou.252035.xyz/"
|
||||
private val URL = "https://tg.252035.xyz/"
|
||||
|
||||
private val header: Map<String, String>
|
||||
get() {
|
||||
val header: MutableMap<String, String> = HashMap()
|
||||
val header: MutableMap<String, String> =
|
||||
HashMap()
|
||||
header["User-Agent"] = Util.CHROME
|
||||
return header
|
||||
}
|
||||
|
|
@ -26,32 +27,23 @@ class TgQuarkSearch : Cloud() {
|
|||
override fun searchContent(key: String, quick: Boolean): String {
|
||||
val url =
|
||||
URL + "?channelUsername=alyp_1,clouddriveresources,dianyingshare,hdhhd21,jdjdn1111,leoziyuan,NewQuark,PanjClub,Quark_Movies,xiangxiunb,yunpanchat,yunpanqk,XiangxiuNB,alyp_4K_Movies,alyp_Animation,alyp_TV,alyp_JLP&pic=true&keyword=" + URLEncoder.encode(
|
||||
key, Charset.defaultCharset().name()
|
||||
key,
|
||||
Charset.defaultCharset().name()
|
||||
)
|
||||
val list: MutableList<Vod> = ArrayList()
|
||||
val html = OkHttp.string(url, header)
|
||||
val json = Json.safeObject(html);
|
||||
json["results"].asJsonArray.forEach { element ->
|
||||
val array = element.asString.split("$$$")
|
||||
if (array.size >= 2 && array[1].isNotEmpty()) {
|
||||
array[1].split("##").forEach {
|
||||
|
||||
|
||||
val id = it.split("@")[0]
|
||||
val pic = it.split("@")[1].split("$$")[0]
|
||||
val name = it.split("@")[1].split("$$")[1]
|
||||
|
||||
list.add(Vod(id, name, pic, ""))
|
||||
}
|
||||
|
||||
|
||||
val arr = html.split(":I".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (arr.size > 0) {
|
||||
for (s in arr) {
|
||||
val doc = Jsoup.parse(s)
|
||||
val id = doc.select(" a").eachAttr("href")
|
||||
.first { it.contains("189") || it.contains("139")|| it.contains("quark") }
|
||||
val name=doc.select("strong").text()
|
||||
list.add(Vod(id, name, "", ""))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return Result.string(list)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,258 +0,0 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
import com.github.catvod.net.OkResult;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.github.catvod.utils.Util;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class TgSearch123 extends Cloud {
|
||||
private static final String KEY_API_URLS = "api_urls";
|
||||
private static final String KEY_DOMAIN_MAP = "siteurl";
|
||||
private static final String KEY_SOURCES = "sources";
|
||||
private static final int DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
private List<String> apiUrls = new ArrayList<>();
|
||||
private Map<String, String> domainMap = new HashMap<String, String>() {{
|
||||
put("alipan", "阿里");
|
||||
put("aliyundrive", "阿里");
|
||||
put("quark", "夸克");
|
||||
put("115cdn", "115");
|
||||
put("baidu.com", "百度");
|
||||
put("uc", "UC");
|
||||
put("189.cn", "天翼");
|
||||
put("139.com", "移动");
|
||||
put("123", "123盘");
|
||||
}};
|
||||
private Set<String> sources = new HashSet<>();
|
||||
private String[] extInfos = null;
|
||||
|
||||
@Override
|
||||
public synchronized void init(Context context, String extend) throws Exception {
|
||||
super.init(context, extend);
|
||||
|
||||
this.apiUrls.clear();
|
||||
|
||||
if (!TextUtils.isEmpty(extend)) {
|
||||
try {
|
||||
if (extend.contains("###")) {
|
||||
String[] infos = extend.split("###");
|
||||
this.extInfos = infos;
|
||||
|
||||
if (infos.length > 0 && !TextUtils.isEmpty(infos[0])) {
|
||||
processExtendConfig(infos[0]);
|
||||
}
|
||||
} else {
|
||||
this.extInfos = new String[]{extend};
|
||||
processExtendConfig(extend);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
this.extInfos = null; // 重置,避免内存泄漏
|
||||
}
|
||||
|
||||
private void processExtendConfig(String config) {
|
||||
try {
|
||||
// 检查是否为HTTP URL
|
||||
if (isValidUrl(config)) {
|
||||
if (!this.apiUrls.contains(config)) {
|
||||
this.apiUrls.add(config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试JSON格式解析
|
||||
JsonObject ext = Json.safeObject(config);
|
||||
|
||||
// 处理API URLs配置
|
||||
processApiUrls(ext);
|
||||
|
||||
// 处理域名映射配置
|
||||
processDomainMap(ext);
|
||||
|
||||
// 处理来源过滤配置
|
||||
processSources(ext, true);
|
||||
} catch (Exception e) {
|
||||
// 可以添加日志记录
|
||||
}
|
||||
}
|
||||
|
||||
private void processApiUrls(JsonObject config) {
|
||||
if (config.has(KEY_API_URLS) && config.get(KEY_API_URLS).isJsonArray()) {
|
||||
JsonArray urlsArray = config.getAsJsonArray(KEY_API_URLS);
|
||||
for (JsonElement element : urlsArray) {
|
||||
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
String url = element.getAsString();
|
||||
if (isValidUrl(url) && !this.apiUrls.contains(url)) {
|
||||
this.apiUrls.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processDomainMap(JsonObject config) {
|
||||
if (config.has(KEY_DOMAIN_MAP) && config.get(KEY_DOMAIN_MAP).isJsonObject()) {
|
||||
JsonObject customDomains = config.getAsJsonObject(KEY_DOMAIN_MAP);
|
||||
for (Map.Entry<String, JsonElement> entry : customDomains.entrySet()) {
|
||||
if (entry == null || entry.getValue() == null) continue;
|
||||
|
||||
String domain = entry.getKey();
|
||||
String sourceName = "";
|
||||
try {
|
||||
sourceName = entry.getValue().getAsString();
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(domain) && !TextUtils.isEmpty(sourceName) && !domainMap.containsKey(domain)) {
|
||||
domainMap.put(domain, sourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processSources(JsonObject config, boolean clearExisting) {
|
||||
if (config.has(KEY_SOURCES) && config.get(KEY_SOURCES).isJsonArray()) {
|
||||
if (clearExisting) {
|
||||
this.sources.clear();
|
||||
}
|
||||
|
||||
JsonArray sourcesArray = config.getAsJsonArray(KEY_SOURCES);
|
||||
for (JsonElement element : sourcesArray) {
|
||||
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
String source = element.getAsString();
|
||||
if (!TextUtils.isEmpty(source) && !sources.contains(source)) {
|
||||
sources.add(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidUrl(String url) {
|
||||
return !TextUtils.isEmpty(url) && (url.startsWith("http://") || url.startsWith("https://"));
|
||||
}
|
||||
|
||||
|
||||
private Map<String, String> getHeader() {
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("User-Agent", Util.CHROME);
|
||||
return header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick) throws Exception {
|
||||
if (key == null || key.trim().isEmpty()) {
|
||||
return Result.error("关键词不能为空");
|
||||
}
|
||||
|
||||
return performSearch(key, 1, DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
private String performSearch(String key, int page, int pageSize) throws Exception {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
int total = 0;
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("kw", key);
|
||||
params.put("page", String.valueOf(page));
|
||||
params.put("size", String.valueOf(pageSize));
|
||||
|
||||
for (String apiUrl : apiUrls) {
|
||||
if (!isValidUrl(apiUrl)) continue;
|
||||
|
||||
try {
|
||||
OkResult result = OkHttp.get(apiUrl, params, getHeader());
|
||||
if (result.getCode() == 500 || TextUtils.isEmpty(result.getBody())) continue;
|
||||
|
||||
JsonObject jsonObject = Json.safeObject(result.getBody());
|
||||
if (!jsonObject.has("code") || jsonObject.get("code").getAsInt() != 0 || !jsonObject.has("data"))
|
||||
continue;
|
||||
|
||||
JsonObject data = jsonObject.getAsJsonObject("data");
|
||||
|
||||
total = data.has("total") && !data.get("total").isJsonNull() ? data.get("total").getAsInt() : 0;
|
||||
|
||||
// 直接检查merged_by_type字段,无需三重判断
|
||||
if (!data.has("merged_by_type") || !data.get("merged_by_type").isJsonObject()) continue;
|
||||
|
||||
JsonObject mergedByType = data.getAsJsonObject("merged_by_type");
|
||||
|
||||
for (Map.Entry<String, JsonElement> categoryEntry : mergedByType.entrySet()) {
|
||||
if (!categoryEntry.getValue().isJsonArray()) continue;
|
||||
|
||||
JsonArray items = categoryEntry.getValue().getAsJsonArray();
|
||||
|
||||
for (JsonElement item : items) {
|
||||
if (!item.isJsonObject()) continue;
|
||||
|
||||
JsonObject entry = item.getAsJsonObject();
|
||||
|
||||
String vodUrl = entry.has("url") && !entry.get("url").isJsonNull() ? entry.get("url").getAsString() : "";
|
||||
if (TextUtils.isEmpty(vodUrl)) continue;
|
||||
|
||||
// 获取来源信息并映射
|
||||
String originalSource = entry.has("source") && !entry.get("source").isJsonNull() ? entry.get("source").getAsString() : "未知来源";
|
||||
String sourceName = mapSource(vodUrl, originalSource);
|
||||
|
||||
// 获取标题
|
||||
String title = entry.has("note") && !entry.get("note").isJsonNull() ? entry.get("note").getAsString() : "未命名资源";
|
||||
|
||||
// 获取图片
|
||||
String pic = getFirstImage(entry);
|
||||
|
||||
// 简化VodPlayBuilder的使用
|
||||
Vod vod = new Vod(vodUrl, title, pic, sourceName + " (" + originalSource + ")");
|
||||
// 由于只有一个播放源,直接设置播放信息
|
||||
vod.setVodPlayFrom(sourceName);
|
||||
vod.setVodPlayUrl("播放源$" + vodUrl);
|
||||
|
||||
// 来源过滤
|
||||
if (sources.isEmpty() || sources.contains(sourceName)) {
|
||||
list.add(vod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pageCount = total > 0 && pageSize > 0 ? (total + pageSize - 1) / pageSize : 1;
|
||||
return Result.string(page, pageCount, pageSize, total, list);
|
||||
} catch (Exception e) {
|
||||
// 出错时继续尝试下一个API
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return Result.error("无法连接到任何搜索API");
|
||||
}
|
||||
|
||||
// 提取来源映射逻辑为单独方法
|
||||
private String mapSource(String vodUrl, String originalSource) {
|
||||
for (Map.Entry<String, String> domainEntry : domainMap.entrySet()) {
|
||||
if (vodUrl.contains(domainEntry.getKey())) {
|
||||
return domainEntry.getValue();
|
||||
}
|
||||
}
|
||||
return originalSource;
|
||||
}
|
||||
|
||||
// 提取图片获取逻辑为单独方法
|
||||
private String getFirstImage(JsonObject entry) {
|
||||
if (entry.has("images") && !entry.get("images").isJsonNull() && entry.get("images").isJsonArray()) {
|
||||
JsonArray images = entry.getAsJsonArray("images");
|
||||
if (images.size() > 0 && !images.get(0).isJsonNull() && images.get(0).isJsonPrimitive()) {
|
||||
return images.get(0).getAsString();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
import com.github.catvod.net.OkResult;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.github.catvod.utils.Util;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class TgSearch139 extends Cloud {
|
||||
private static final String KEY_API_URLS = "api_urls";
|
||||
private static final String KEY_DOMAIN_MAP = "siteurl";
|
||||
private static final String KEY_SOURCES = "sources";
|
||||
private static final int DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
private List<String> apiUrls = new ArrayList<>();
|
||||
private Map<String, String> domainMap = new HashMap<String, String>() {{
|
||||
put("alipan", "阿里");
|
||||
put("aliyundrive", "阿里");
|
||||
put("quark", "夸克");
|
||||
put("115cdn", "115");
|
||||
put("baidu.com", "百度");
|
||||
put("uc", "UC");
|
||||
put("189.cn", "天翼");
|
||||
put("139.com", "移动");
|
||||
put("123", "123盘");
|
||||
}};
|
||||
private Set<String> sources = new HashSet<>();
|
||||
private String[] extInfos = null;
|
||||
|
||||
@Override
|
||||
public synchronized void init(Context context, String extend) throws Exception {
|
||||
super.init(context, extend);
|
||||
|
||||
this.apiUrls.clear();
|
||||
|
||||
if (!TextUtils.isEmpty(extend)) {
|
||||
try {
|
||||
if (extend.contains("###")) {
|
||||
String[] infos = extend.split("###");
|
||||
this.extInfos = infos;
|
||||
|
||||
if (infos.length > 0 && !TextUtils.isEmpty(infos[0])) {
|
||||
processExtendConfig(infos[0]);
|
||||
}
|
||||
} else {
|
||||
this.extInfos = new String[]{extend};
|
||||
processExtendConfig(extend);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
this.extInfos = null; // 重置,避免内存泄漏
|
||||
}
|
||||
|
||||
private void processExtendConfig(String config) {
|
||||
try {
|
||||
// 检查是否为HTTP URL
|
||||
if (isValidUrl(config)) {
|
||||
if (!this.apiUrls.contains(config)) {
|
||||
this.apiUrls.add(config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试JSON格式解析
|
||||
JsonObject ext = Json.safeObject(config);
|
||||
|
||||
// 处理API URLs配置
|
||||
processApiUrls(ext);
|
||||
|
||||
// 处理域名映射配置
|
||||
processDomainMap(ext);
|
||||
|
||||
// 处理来源过滤配置
|
||||
processSources(ext, true);
|
||||
} catch (Exception e) {
|
||||
// 可以添加日志记录
|
||||
}
|
||||
}
|
||||
|
||||
private void processApiUrls(JsonObject config) {
|
||||
if (config.has(KEY_API_URLS) && config.get(KEY_API_URLS).isJsonArray()) {
|
||||
JsonArray urlsArray = config.getAsJsonArray(KEY_API_URLS);
|
||||
for (JsonElement element : urlsArray) {
|
||||
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
String url = element.getAsString();
|
||||
if (isValidUrl(url) && !this.apiUrls.contains(url)) {
|
||||
this.apiUrls.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processDomainMap(JsonObject config) {
|
||||
if (config.has(KEY_DOMAIN_MAP) && config.get(KEY_DOMAIN_MAP).isJsonObject()) {
|
||||
JsonObject customDomains = config.getAsJsonObject(KEY_DOMAIN_MAP);
|
||||
for (Map.Entry<String, JsonElement> entry : customDomains.entrySet()) {
|
||||
if (entry == null || entry.getValue() == null) continue;
|
||||
|
||||
String domain = entry.getKey();
|
||||
String sourceName = "";
|
||||
try {
|
||||
sourceName = entry.getValue().getAsString();
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(domain) && !TextUtils.isEmpty(sourceName) && !domainMap.containsKey(domain)) {
|
||||
domainMap.put(domain, sourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processSources(JsonObject config, boolean clearExisting) {
|
||||
if (config.has(KEY_SOURCES) && config.get(KEY_SOURCES).isJsonArray()) {
|
||||
if (clearExisting) {
|
||||
this.sources.clear();
|
||||
}
|
||||
|
||||
JsonArray sourcesArray = config.getAsJsonArray(KEY_SOURCES);
|
||||
for (JsonElement element : sourcesArray) {
|
||||
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
String source = element.getAsString();
|
||||
if (!TextUtils.isEmpty(source) && !sources.contains(source)) {
|
||||
sources.add(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidUrl(String url) {
|
||||
return !TextUtils.isEmpty(url) && (url.startsWith("http://") || url.startsWith("https://"));
|
||||
}
|
||||
|
||||
|
||||
private Map<String, String> getHeader() {
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("User-Agent", Util.CHROME);
|
||||
return header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick) throws Exception {
|
||||
if (key == null || key.trim().isEmpty()) {
|
||||
return Result.error("关键词不能为空");
|
||||
}
|
||||
|
||||
return performSearch(key, 1, DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
private String performSearch(String key, int page, int pageSize) throws Exception {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
int total = 0;
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("kw", key);
|
||||
params.put("page", String.valueOf(page));
|
||||
params.put("size", String.valueOf(pageSize));
|
||||
|
||||
for (String apiUrl : apiUrls) {
|
||||
if (!isValidUrl(apiUrl)) continue;
|
||||
|
||||
try {
|
||||
OkResult result = OkHttp.get(apiUrl, params, getHeader());
|
||||
if (result.getCode() == 500 || TextUtils.isEmpty(result.getBody())) continue;
|
||||
|
||||
JsonObject jsonObject = Json.safeObject(result.getBody());
|
||||
if (!jsonObject.has("code") || jsonObject.get("code").getAsInt() != 0 || !jsonObject.has("data"))
|
||||
continue;
|
||||
|
||||
JsonObject data = jsonObject.getAsJsonObject("data");
|
||||
|
||||
total = data.has("total") && !data.get("total").isJsonNull() ? data.get("total").getAsInt() : 0;
|
||||
|
||||
// 直接检查merged_by_type字段,无需三重判断
|
||||
if (!data.has("merged_by_type") || !data.get("merged_by_type").isJsonObject()) continue;
|
||||
|
||||
JsonObject mergedByType = data.getAsJsonObject("merged_by_type");
|
||||
|
||||
for (Map.Entry<String, JsonElement> categoryEntry : mergedByType.entrySet()) {
|
||||
if (!categoryEntry.getValue().isJsonArray()) continue;
|
||||
|
||||
JsonArray items = categoryEntry.getValue().getAsJsonArray();
|
||||
|
||||
for (JsonElement item : items) {
|
||||
if (!item.isJsonObject()) continue;
|
||||
|
||||
JsonObject entry = item.getAsJsonObject();
|
||||
|
||||
String vodUrl = entry.has("url") && !entry.get("url").isJsonNull() ? entry.get("url").getAsString() : "";
|
||||
if (TextUtils.isEmpty(vodUrl)) continue;
|
||||
|
||||
// 获取来源信息并映射
|
||||
String originalSource = entry.has("source") && !entry.get("source").isJsonNull() ? entry.get("source").getAsString() : "未知来源";
|
||||
String sourceName = mapSource(vodUrl, originalSource);
|
||||
|
||||
// 获取标题
|
||||
String title = entry.has("note") && !entry.get("note").isJsonNull() ? entry.get("note").getAsString() : "未命名资源";
|
||||
|
||||
// 获取图片
|
||||
String pic = getFirstImage(entry);
|
||||
|
||||
// 简化VodPlayBuilder的使用
|
||||
Vod vod = new Vod(vodUrl, title, pic, sourceName + " (" + originalSource + ")");
|
||||
// 由于只有一个播放源,直接设置播放信息
|
||||
vod.setVodPlayFrom(sourceName);
|
||||
vod.setVodPlayUrl("播放源$" + vodUrl);
|
||||
|
||||
// 来源过滤
|
||||
if (sources.isEmpty() || sources.contains(sourceName)) {
|
||||
list.add(vod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pageCount = total > 0 && pageSize > 0 ? (total + pageSize - 1) / pageSize : 1;
|
||||
return Result.string(page, pageCount, pageSize, total, list);
|
||||
} catch (Exception e) {
|
||||
// 出错时继续尝试下一个API
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return Result.error("无法连接到任何搜索API");
|
||||
}
|
||||
|
||||
// 提取来源映射逻辑为单独方法
|
||||
private String mapSource(String vodUrl, String originalSource) {
|
||||
for (Map.Entry<String, String> domainEntry : domainMap.entrySet()) {
|
||||
if (vodUrl.contains(domainEntry.getKey())) {
|
||||
return domainEntry.getValue();
|
||||
}
|
||||
}
|
||||
return originalSource;
|
||||
}
|
||||
|
||||
// 提取图片获取逻辑为单独方法
|
||||
private String getFirstImage(JsonObject entry) {
|
||||
if (entry.has("images") && !entry.get("images").isJsonNull() && entry.get("images").isJsonArray()) {
|
||||
JsonArray images = entry.getAsJsonArray("images");
|
||||
if (images.size() > 0 && !images.get(0).isJsonNull() && images.get(0).isJsonPrimitive()) {
|
||||
return images.get(0).getAsString();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
import com.github.catvod.net.OkResult;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.github.catvod.utils.Util;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class TgSearch189 extends Cloud {
|
||||
private static final String KEY_API_URLS = "api_urls";
|
||||
private static final String KEY_DOMAIN_MAP = "siteurl";
|
||||
private static final String KEY_SOURCES = "sources";
|
||||
private static final int DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
private List<String> apiUrls = new ArrayList<>();
|
||||
private Map<String, String> domainMap = new HashMap<String, String>() {{
|
||||
put("alipan", "阿里");
|
||||
put("aliyundrive", "阿里");
|
||||
put("quark", "夸克");
|
||||
put("115cdn", "115");
|
||||
put("baidu.com", "百度");
|
||||
put("uc", "UC");
|
||||
put("189.cn", "天翼");
|
||||
put("139.com", "移动");
|
||||
put("123", "123盘");
|
||||
}};
|
||||
private Set<String> sources = new HashSet<>();
|
||||
private String[] extInfos = null;
|
||||
|
||||
@Override
|
||||
public synchronized void init(Context context, String extend) throws Exception {
|
||||
super.init(context, extend);
|
||||
|
||||
this.apiUrls.clear();
|
||||
|
||||
if (!TextUtils.isEmpty(extend)) {
|
||||
try {
|
||||
if (extend.contains("###")) {
|
||||
String[] infos = extend.split("###");
|
||||
this.extInfos = infos;
|
||||
|
||||
if (infos.length > 0 && !TextUtils.isEmpty(infos[0])) {
|
||||
processExtendConfig(infos[0]);
|
||||
}
|
||||
} else {
|
||||
this.extInfos = new String[]{extend};
|
||||
processExtendConfig(extend);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
this.extInfos = null; // 重置,避免内存泄漏
|
||||
}
|
||||
|
||||
private void processExtendConfig(String config) {
|
||||
try {
|
||||
// 检查是否为HTTP URL
|
||||
if (isValidUrl(config)) {
|
||||
if (!this.apiUrls.contains(config)) {
|
||||
this.apiUrls.add(config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试JSON格式解析
|
||||
JsonObject ext = Json.safeObject(config);
|
||||
|
||||
// 处理API URLs配置
|
||||
processApiUrls(ext);
|
||||
|
||||
// 处理域名映射配置
|
||||
processDomainMap(ext);
|
||||
|
||||
// 处理来源过滤配置
|
||||
processSources(ext, true);
|
||||
} catch (Exception e) {
|
||||
// 可以添加日志记录
|
||||
}
|
||||
}
|
||||
|
||||
private void processApiUrls(JsonObject config) {
|
||||
if (config.has(KEY_API_URLS) && config.get(KEY_API_URLS).isJsonArray()) {
|
||||
JsonArray urlsArray = config.getAsJsonArray(KEY_API_URLS);
|
||||
for (JsonElement element : urlsArray) {
|
||||
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
String url = element.getAsString();
|
||||
if (isValidUrl(url) && !this.apiUrls.contains(url)) {
|
||||
this.apiUrls.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processDomainMap(JsonObject config) {
|
||||
if (config.has(KEY_DOMAIN_MAP) && config.get(KEY_DOMAIN_MAP).isJsonObject()) {
|
||||
JsonObject customDomains = config.getAsJsonObject(KEY_DOMAIN_MAP);
|
||||
for (Map.Entry<String, JsonElement> entry : customDomains.entrySet()) {
|
||||
if (entry == null || entry.getValue() == null) continue;
|
||||
|
||||
String domain = entry.getKey();
|
||||
String sourceName = "";
|
||||
try {
|
||||
sourceName = entry.getValue().getAsString();
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(domain) && !TextUtils.isEmpty(sourceName) && !domainMap.containsKey(domain)) {
|
||||
domainMap.put(domain, sourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processSources(JsonObject config, boolean clearExisting) {
|
||||
if (config.has(KEY_SOURCES) && config.get(KEY_SOURCES).isJsonArray()) {
|
||||
if (clearExisting) {
|
||||
this.sources.clear();
|
||||
}
|
||||
|
||||
JsonArray sourcesArray = config.getAsJsonArray(KEY_SOURCES);
|
||||
for (JsonElement element : sourcesArray) {
|
||||
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
String source = element.getAsString();
|
||||
if (!TextUtils.isEmpty(source) && !sources.contains(source)) {
|
||||
sources.add(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidUrl(String url) {
|
||||
return !TextUtils.isEmpty(url) && (url.startsWith("http://") || url.startsWith("https://"));
|
||||
}
|
||||
|
||||
|
||||
private Map<String, String> getHeader() {
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("User-Agent", Util.CHROME);
|
||||
return header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick) throws Exception {
|
||||
if (key == null || key.trim().isEmpty()) {
|
||||
return Result.error("关键词不能为空");
|
||||
}
|
||||
|
||||
return performSearch(key, 1, DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
private String performSearch(String key, int page, int pageSize) throws Exception {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
int total = 0;
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("kw", key);
|
||||
params.put("page", String.valueOf(page));
|
||||
params.put("size", String.valueOf(pageSize));
|
||||
|
||||
for (String apiUrl : apiUrls) {
|
||||
if (!isValidUrl(apiUrl)) continue;
|
||||
|
||||
try {
|
||||
OkResult result = OkHttp.get(apiUrl, params, getHeader());
|
||||
if (result.getCode() == 500 || TextUtils.isEmpty(result.getBody())) continue;
|
||||
|
||||
JsonObject jsonObject = Json.safeObject(result.getBody());
|
||||
if (!jsonObject.has("code") || jsonObject.get("code").getAsInt() != 0 || !jsonObject.has("data"))
|
||||
continue;
|
||||
|
||||
JsonObject data = jsonObject.getAsJsonObject("data");
|
||||
|
||||
total = data.has("total") && !data.get("total").isJsonNull() ? data.get("total").getAsInt() : 0;
|
||||
|
||||
// 直接检查merged_by_type字段,无需三重判断
|
||||
if (!data.has("merged_by_type") || !data.get("merged_by_type").isJsonObject()) continue;
|
||||
|
||||
JsonObject mergedByType = data.getAsJsonObject("merged_by_type");
|
||||
|
||||
for (Map.Entry<String, JsonElement> categoryEntry : mergedByType.entrySet()) {
|
||||
if (!categoryEntry.getValue().isJsonArray()) continue;
|
||||
|
||||
JsonArray items = categoryEntry.getValue().getAsJsonArray();
|
||||
|
||||
for (JsonElement item : items) {
|
||||
if (!item.isJsonObject()) continue;
|
||||
|
||||
JsonObject entry = item.getAsJsonObject();
|
||||
|
||||
String vodUrl = entry.has("url") && !entry.get("url").isJsonNull() ? entry.get("url").getAsString() : "";
|
||||
if (TextUtils.isEmpty(vodUrl)) continue;
|
||||
|
||||
// 获取来源信息并映射
|
||||
String originalSource = entry.has("source") && !entry.get("source").isJsonNull() ? entry.get("source").getAsString() : "未知来源";
|
||||
String sourceName = mapSource(vodUrl, originalSource);
|
||||
|
||||
// 获取标题
|
||||
String title = entry.has("note") && !entry.get("note").isJsonNull() ? entry.get("note").getAsString() : "未命名资源";
|
||||
|
||||
// 获取图片
|
||||
String pic = getFirstImage(entry);
|
||||
|
||||
// 简化VodPlayBuilder的使用
|
||||
Vod vod = new Vod(vodUrl, title, pic, sourceName + " (" + originalSource + ")");
|
||||
// 由于只有一个播放源,直接设置播放信息
|
||||
vod.setVodPlayFrom(sourceName);
|
||||
vod.setVodPlayUrl("播放源$" + vodUrl);
|
||||
|
||||
// 来源过滤
|
||||
if (sources.isEmpty() || sources.contains(sourceName)) {
|
||||
list.add(vod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pageCount = total > 0 && pageSize > 0 ? (total + pageSize - 1) / pageSize : 1;
|
||||
return Result.string(page, pageCount, pageSize, total, list);
|
||||
} catch (Exception e) {
|
||||
// 出错时继续尝试下一个API
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return Result.error("无法连接到任何搜索API");
|
||||
}
|
||||
|
||||
// 提取来源映射逻辑为单独方法
|
||||
private String mapSource(String vodUrl, String originalSource) {
|
||||
for (Map.Entry<String, String> domainEntry : domainMap.entrySet()) {
|
||||
if (vodUrl.contains(domainEntry.getKey())) {
|
||||
return domainEntry.getValue();
|
||||
}
|
||||
}
|
||||
return originalSource;
|
||||
}
|
||||
|
||||
// 提取图片获取逻辑为单独方法
|
||||
private String getFirstImage(JsonObject entry) {
|
||||
if (entry.has("images") && !entry.get("images").isJsonNull() && entry.get("images").isJsonArray()) {
|
||||
JsonArray images = entry.getAsJsonArray("images");
|
||||
if (images.size() > 0 && !images.get(0).isJsonNull() && images.get(0).isJsonPrimitive()) {
|
||||
return images.get(0).getAsString();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -11,8 +11,12 @@ import com.github.catvod.utils.Util;
|
|||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class TgSearchBaidu extends Cloud {
|
||||
private static final String KEY_API_URLS = "api_urls";
|
||||
|
|
@ -54,8 +58,7 @@ public class TgSearchBaidu extends Cloud {
|
|||
this.extInfos = new String[]{extend};
|
||||
processExtendConfig(extend);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
this.extInfos = null; // 重置,避免内存泄漏
|
||||
}
|
||||
|
|
@ -108,11 +111,7 @@ public class TgSearchBaidu extends Cloud {
|
|||
|
||||
String domain = entry.getKey();
|
||||
String sourceName = "";
|
||||
try {
|
||||
sourceName = entry.getValue().getAsString();
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
try { sourceName = entry.getValue().getAsString(); } catch (Exception e) { continue; }
|
||||
|
||||
if (!TextUtils.isEmpty(domain) && !TextUtils.isEmpty(sourceName) && !domainMap.containsKey(domain)) {
|
||||
domainMap.put(domain, sourceName);
|
||||
|
|
@ -144,6 +143,7 @@ public class TgSearchBaidu extends Cloud {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private Map<String, String> getHeader() {
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("User-Agent", Util.CHROME);
|
||||
|
|
@ -176,8 +176,7 @@ public class TgSearchBaidu extends Cloud {
|
|||
if (result.getCode() == 500 || TextUtils.isEmpty(result.getBody())) continue;
|
||||
|
||||
JsonObject jsonObject = Json.safeObject(result.getBody());
|
||||
if (!jsonObject.has("code") || jsonObject.get("code").getAsInt() != 0 || !jsonObject.has("data"))
|
||||
continue;
|
||||
if (!jsonObject.has("code") || jsonObject.get("code").getAsInt() != 0 || !jsonObject.has("data")) continue;
|
||||
|
||||
JsonObject data = jsonObject.getAsJsonObject("data");
|
||||
|
||||
|
|
@ -212,7 +211,7 @@ public class TgSearchBaidu extends Cloud {
|
|||
String pic = getFirstImage(entry);
|
||||
|
||||
// 简化VodPlayBuilder的使用
|
||||
Vod vod = new Vod(vodUrl, title, pic, sourceName + " (" + originalSource + ")");
|
||||
Vod vod = new Vod("push://" + vodUrl, title, pic, sourceName + " (" + originalSource + ")");
|
||||
// 由于只有一个播放源,直接设置播放信息
|
||||
vod.setVodPlayFrom(sourceName);
|
||||
vod.setVodPlayUrl("播放源$" + vodUrl);
|
||||
|
|
|
|||
|
|
@ -1,258 +0,0 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.net.OkHttp;
|
||||
import com.github.catvod.net.OkResult;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.github.catvod.utils.Util;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class TgSearchQuark extends Cloud {
|
||||
private static final String KEY_API_URLS = "api_urls";
|
||||
private static final String KEY_DOMAIN_MAP = "siteurl";
|
||||
private static final String KEY_SOURCES = "sources";
|
||||
private static final int DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
private List<String> apiUrls = new ArrayList<>();
|
||||
private Map<String, String> domainMap = new HashMap<String, String>() {{
|
||||
put("alipan", "阿里");
|
||||
put("aliyundrive", "阿里");
|
||||
put("quark", "夸克");
|
||||
put("115cdn", "115");
|
||||
put("baidu.com", "百度");
|
||||
put("uc", "UC");
|
||||
put("189.cn", "天翼");
|
||||
put("139.com", "移动");
|
||||
put("123", "123盘");
|
||||
}};
|
||||
private Set<String> sources = new HashSet<>();
|
||||
private String[] extInfos = null;
|
||||
|
||||
@Override
|
||||
public synchronized void init(Context context, String extend) throws Exception {
|
||||
super.init(context, extend);
|
||||
|
||||
this.apiUrls.clear();
|
||||
|
||||
if (!TextUtils.isEmpty(extend)) {
|
||||
try {
|
||||
if (extend.contains("###")) {
|
||||
String[] infos = extend.split("###");
|
||||
this.extInfos = infos;
|
||||
|
||||
if (infos.length > 0 && !TextUtils.isEmpty(infos[0])) {
|
||||
processExtendConfig(infos[0]);
|
||||
}
|
||||
} else {
|
||||
this.extInfos = new String[]{extend};
|
||||
processExtendConfig(extend);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
this.extInfos = null; // 重置,避免内存泄漏
|
||||
}
|
||||
|
||||
private void processExtendConfig(String config) {
|
||||
try {
|
||||
// 检查是否为HTTP URL
|
||||
if (isValidUrl(config)) {
|
||||
if (!this.apiUrls.contains(config)) {
|
||||
this.apiUrls.add(config);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试JSON格式解析
|
||||
JsonObject ext = Json.safeObject(config);
|
||||
|
||||
// 处理API URLs配置
|
||||
processApiUrls(ext);
|
||||
|
||||
// 处理域名映射配置
|
||||
processDomainMap(ext);
|
||||
|
||||
// 处理来源过滤配置
|
||||
processSources(ext, true);
|
||||
} catch (Exception e) {
|
||||
// 可以添加日志记录
|
||||
}
|
||||
}
|
||||
|
||||
private void processApiUrls(JsonObject config) {
|
||||
if (config.has(KEY_API_URLS) && config.get(KEY_API_URLS).isJsonArray()) {
|
||||
JsonArray urlsArray = config.getAsJsonArray(KEY_API_URLS);
|
||||
for (JsonElement element : urlsArray) {
|
||||
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
String url = element.getAsString();
|
||||
if (isValidUrl(url) && !this.apiUrls.contains(url)) {
|
||||
this.apiUrls.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processDomainMap(JsonObject config) {
|
||||
if (config.has(KEY_DOMAIN_MAP) && config.get(KEY_DOMAIN_MAP).isJsonObject()) {
|
||||
JsonObject customDomains = config.getAsJsonObject(KEY_DOMAIN_MAP);
|
||||
for (Map.Entry<String, JsonElement> entry : customDomains.entrySet()) {
|
||||
if (entry == null || entry.getValue() == null) continue;
|
||||
|
||||
String domain = entry.getKey();
|
||||
String sourceName = "";
|
||||
try {
|
||||
sourceName = entry.getValue().getAsString();
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(domain) && !TextUtils.isEmpty(sourceName) && !domainMap.containsKey(domain)) {
|
||||
domainMap.put(domain, sourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processSources(JsonObject config, boolean clearExisting) {
|
||||
if (config.has(KEY_SOURCES) && config.get(KEY_SOURCES).isJsonArray()) {
|
||||
if (clearExisting) {
|
||||
this.sources.clear();
|
||||
}
|
||||
|
||||
JsonArray sourcesArray = config.getAsJsonArray(KEY_SOURCES);
|
||||
for (JsonElement element : sourcesArray) {
|
||||
if (element != null && element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
String source = element.getAsString();
|
||||
if (!TextUtils.isEmpty(source) && !sources.contains(source)) {
|
||||
sources.add(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidUrl(String url) {
|
||||
return !TextUtils.isEmpty(url) && (url.startsWith("http://") || url.startsWith("https://"));
|
||||
}
|
||||
|
||||
|
||||
private Map<String, String> getHeader() {
|
||||
Map<String, String> header = new HashMap<>();
|
||||
header.put("User-Agent", Util.CHROME);
|
||||
return header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String searchContent(String key, boolean quick) throws Exception {
|
||||
if (key == null || key.trim().isEmpty()) {
|
||||
return Result.error("关键词不能为空");
|
||||
}
|
||||
|
||||
return performSearch(key, 1, DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
private String performSearch(String key, int page, int pageSize) throws Exception {
|
||||
List<Vod> list = new ArrayList<>();
|
||||
int total = 0;
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("kw", key);
|
||||
params.put("page", String.valueOf(page));
|
||||
params.put("size", String.valueOf(pageSize));
|
||||
|
||||
for (String apiUrl : apiUrls) {
|
||||
if (!isValidUrl(apiUrl)) continue;
|
||||
|
||||
try {
|
||||
OkResult result = OkHttp.get(apiUrl, params, getHeader());
|
||||
if (result.getCode() == 500 || TextUtils.isEmpty(result.getBody())) continue;
|
||||
|
||||
JsonObject jsonObject = Json.safeObject(result.getBody());
|
||||
if (!jsonObject.has("code") || jsonObject.get("code").getAsInt() != 0 || !jsonObject.has("data"))
|
||||
continue;
|
||||
|
||||
JsonObject data = jsonObject.getAsJsonObject("data");
|
||||
|
||||
total = data.has("total") && !data.get("total").isJsonNull() ? data.get("total").getAsInt() : 0;
|
||||
|
||||
// 直接检查merged_by_type字段,无需三重判断
|
||||
if (!data.has("merged_by_type") || !data.get("merged_by_type").isJsonObject()) continue;
|
||||
|
||||
JsonObject mergedByType = data.getAsJsonObject("merged_by_type");
|
||||
|
||||
for (Map.Entry<String, JsonElement> categoryEntry : mergedByType.entrySet()) {
|
||||
if (!categoryEntry.getValue().isJsonArray()) continue;
|
||||
|
||||
JsonArray items = categoryEntry.getValue().getAsJsonArray();
|
||||
|
||||
for (JsonElement item : items) {
|
||||
if (!item.isJsonObject()) continue;
|
||||
|
||||
JsonObject entry = item.getAsJsonObject();
|
||||
|
||||
String vodUrl = entry.has("url") && !entry.get("url").isJsonNull() ? entry.get("url").getAsString() : "";
|
||||
if (TextUtils.isEmpty(vodUrl)) continue;
|
||||
|
||||
// 获取来源信息并映射
|
||||
String originalSource = entry.has("source") && !entry.get("source").isJsonNull() ? entry.get("source").getAsString() : "未知来源";
|
||||
String sourceName = mapSource(vodUrl, originalSource);
|
||||
|
||||
// 获取标题
|
||||
String title = entry.has("note") && !entry.get("note").isJsonNull() ? entry.get("note").getAsString() : "未命名资源";
|
||||
|
||||
// 获取图片
|
||||
String pic = getFirstImage(entry);
|
||||
|
||||
// 简化VodPlayBuilder的使用
|
||||
Vod vod = new Vod(vodUrl, title, pic, sourceName + " (" + originalSource + ")");
|
||||
// 由于只有一个播放源,直接设置播放信息
|
||||
vod.setVodPlayFrom(sourceName);
|
||||
vod.setVodPlayUrl("播放源$" + vodUrl);
|
||||
|
||||
// 来源过滤
|
||||
if (sources.isEmpty() || sources.contains(sourceName)) {
|
||||
list.add(vod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pageCount = total > 0 && pageSize > 0 ? (total + pageSize - 1) / pageSize : 1;
|
||||
return Result.string(page, pageCount, pageSize, total, list);
|
||||
} catch (Exception e) {
|
||||
// 出错时继续尝试下一个API
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return Result.error("无法连接到任何搜索API");
|
||||
}
|
||||
|
||||
// 提取来源映射逻辑为单独方法
|
||||
private String mapSource(String vodUrl, String originalSource) {
|
||||
for (Map.Entry<String, String> domainEntry : domainMap.entrySet()) {
|
||||
if (vodUrl.contains(domainEntry.getKey())) {
|
||||
return domainEntry.getValue();
|
||||
}
|
||||
}
|
||||
return originalSource;
|
||||
}
|
||||
|
||||
// 提取图片获取逻辑为单独方法
|
||||
private String getFirstImage(JsonObject entry) {
|
||||
if (entry.has("images") && !entry.get("images").isJsonNull() && entry.get("images").isJsonArray()) {
|
||||
JsonArray images = entry.getAsJsonArray("images");
|
||||
if (images.size() > 0 && !images.get(0).isJsonNull() && images.get(0).isJsonPrimitive()) {
|
||||
return images.get(0).getAsString();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
package com.github.catvod.spider
|
||||
|
||||
import com.github.catvod.bean.Result
|
||||
import com.github.catvod.bean.Vod
|
||||
import com.github.catvod.net.OkHttp
|
||||
import com.github.catvod.utils.Json
|
||||
import com.github.catvod.utils.Util
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
* @author zhixc
|
||||
*/
|
||||
class TgbaiduSearch : Cloud() {
|
||||
private val URL = "https://tgsou.252035.xyz/"
|
||||
|
||||
private val header: Map<String, String>
|
||||
get() {
|
||||
val header: MutableMap<String, String> = HashMap()
|
||||
header["User-Agent"] = Util.CHROME
|
||||
return header
|
||||
}
|
||||
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun searchContent(key: String, quick: Boolean): String {
|
||||
val url =
|
||||
URL + "?channelUsername=BaiduCloudDisk,bdwpzhpd,Baidu_Netdisk&pic=true&keyword=" + URLEncoder.encode(
|
||||
key, Charset.defaultCharset().name()
|
||||
)
|
||||
val list: MutableList<Vod> = ArrayList()
|
||||
val html = OkHttp.string(url, header)
|
||||
val json = Json.safeObject(html);
|
||||
json["results"].asJsonArray.forEach { element ->
|
||||
val array = element.asString.split("$$$")
|
||||
if (array.size >= 2 && array[1].isNotEmpty()) {
|
||||
array[1].split("##").forEach {
|
||||
|
||||
|
||||
val id = it.split("@")[0]
|
||||
val pic = it.split("@")[1].split("$$")[0]
|
||||
val name = it.split("@")[1].split("$$")[1]
|
||||
|
||||
list.add(Vod(id, name, pic, ""))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return Result.string(list)
|
||||
}
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ public class TianYi extends Spider {
|
|||
for (int i = 1; i <= ids.size(); i++) {
|
||||
|
||||
for (String s : TianyiApi.get().getPlayFormatList()) {
|
||||
playFrom.add(String.format(Locale.getDefault(), "天意" + s + "#%02d_%02d", i, index));
|
||||
playFrom.add(String.format(Locale.getDefault(), "天意" + s + "#%02d%02d", i, index));
|
||||
|
||||
}
|
||||
// playFrom.add("天意" + i + index);
|
||||
|
|
@ -69,7 +69,7 @@ public class TianYi extends Spider {
|
|||
* @param ids share_link 集合
|
||||
* @return 詳情內容視頻播放地址
|
||||
*/
|
||||
public String detailContentVodPlayUrl(List<String> ids) {
|
||||
public String detailContentVodPlayUrl(List<String> ids) throws Exception {
|
||||
List<String> playUrl = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
ShareData shareData = TianyiApi.get().getShareData(id, "");
|
||||
|
|
@ -77,7 +77,6 @@ public class TianYi extends Spider {
|
|||
playUrl.add(TianyiApi.get().getVod(shareData).getVodPlayUrl());
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log("获取播放地址出错:" + e.getMessage());
|
||||
playUrl.add("");
|
||||
}
|
||||
}
|
||||
return TextUtils.join("$$$", playUrl);
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ public class UC extends Spider {
|
|||
|
||||
for (int i = 1; i <= ids.size(); i++) {
|
||||
|
||||
/* for (String s : UCApi.get().getPlayFormatList()) {
|
||||
for (String s : UCApi.get().getPlayFormatList()) {
|
||||
playFrom.add(String.format(Locale.getDefault(), "uc" + s + "#%02d%02d", i, index));
|
||||
|
||||
}*/
|
||||
}
|
||||
playFrom.add("uc原画" + i + index);
|
||||
}
|
||||
return TextUtils.join("$$$", playFrom);
|
||||
|
|
@ -71,17 +71,11 @@ public class UC extends Spider {
|
|||
* @param ids share_link 集合
|
||||
* @return 詳情內容視頻播放地址
|
||||
*/
|
||||
public String detailContentVodPlayUrl(List<String> ids) {
|
||||
public String detailContentVodPlayUrl(List<String> ids) throws Exception {
|
||||
List<String> playUrl = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
try {
|
||||
ShareData shareData = UCApi.get().getShareData(id);
|
||||
playUrl.add(UCApi.get().getVod(shareData)==null?"":UCApi.get().getVod(shareData).getVodPlayUrl());
|
||||
}catch (Exception e){
|
||||
SpiderDebug.log("获取播放地址出错:" + e.getMessage());
|
||||
playUrl.add("");
|
||||
}
|
||||
|
||||
ShareData shareData = UCApi.get().getShareData(id);
|
||||
playUrl.add(UCApi.get().getVod(shareData).getVodPlayUrl());
|
||||
}
|
||||
return TextUtils.join("$$$", playUrl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@ package com.github.catvod.spider;
|
|||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.github.catvod.api.YunDrive;
|
||||
import com.github.catvod.bean.Result;
|
||||
import com.github.catvod.bean.Vod;
|
||||
import com.github.catvod.crawler.Spider;
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -94,8 +96,8 @@ public class YiDongYun extends Spider {
|
|||
int i = 0;
|
||||
for (String id : ids) {
|
||||
i++;
|
||||
playFrom.add(String.format("移动(极速)#%2d", i));
|
||||
playFrom.add(String.format("移动(原画)#%2d", i));
|
||||
playFrom.add("移动(极速)" + i);
|
||||
playFrom.add("移动(原画)" + i);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -109,17 +111,10 @@ public class YiDongYun extends Spider {
|
|||
* @param ids share_link 集合
|
||||
* @return 詳情內容視頻播放地址
|
||||
*/
|
||||
public String detailContentVodPlayUrl(List<String> ids) {
|
||||
public String detailContentVodPlayUrl(List<String> ids) throws Exception {
|
||||
List<String> playUrl = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
try {
|
||||
playUrl.add(getVod(List.of(id)).getVodPlayUrl());
|
||||
}catch (Exception e) {
|
||||
SpiderDebug.log("获取播放地址出错:" + e.getMessage());
|
||||
playUrl.add("");
|
||||
}
|
||||
|
||||
|
||||
playUrl.add(getVod(List.of(id)).getVodPlayUrl());
|
||||
}
|
||||
return TextUtils.join("$$$", playUrl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,22 +4,28 @@ import com.github.catvod.crawler.SpiderDebug
|
|||
import com.github.catvod.net.OkHttp
|
||||
import com.github.catvod.utils.ProxyVideo.getMimeType
|
||||
import com.github.catvod.utils.ProxyVideo.parseRange
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.Response
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import java.io.InputStream
|
||||
import java.io.SequenceInputStream
|
||||
import java.util.*
|
||||
import java.util.Vector
|
||||
import kotlin.math.min
|
||||
|
||||
object DownloadMT {
|
||||
private val THREAD_NUM: Int = 16
|
||||
private val THREAD_NUM: Int = Runtime.getRuntime().availableProcessors() * 2
|
||||
|
||||
private val infos = mutableMapOf<String, Array<Any>>();
|
||||
|
||||
fun proxyMultiThread(url: String, headers: Map<String, String>): Array<out Any?>? = runBlocking {
|
||||
proxyAsync(url, headers)
|
||||
}
|
||||
fun proxyMultiThread(url: String, headers: Map<String, String>): Array<out Any?>? =
|
||||
runBlocking {
|
||||
proxyAsync(url, headers)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取是否分片信息,顺带请求一个1MB块
|
||||
|
|
@ -46,10 +52,11 @@ object DownloadMT {
|
|||
if (info == null) {
|
||||
infos.clear()
|
||||
info = CoroutineScope(Dispatchers.IO).async { getInfo(url, headers) }.await()
|
||||
infos[url] = info/* //支持分片,先返回这个1MB块
|
||||
if (info[0] as Int == 206) {
|
||||
return info
|
||||
}*/
|
||||
infos[url] = info
|
||||
/* //支持分片,先返回这个1MB块
|
||||
if (info[0] as Int == 206) {
|
||||
return info
|
||||
}*/
|
||||
}
|
||||
|
||||
val code = info[0] as Int
|
||||
|
|
@ -71,7 +78,8 @@ object DownloadMT {
|
|||
/* if (total.toLong() < 1024 * 1024 * 100) {
|
||||
return proxy(url, headers)
|
||||
}*/
|
||||
var range = if (StringUtils.isAllBlank(headers["range"])) headers["Range"] else headers["range"]
|
||||
var range =
|
||||
if (StringUtils.isAllBlank(headers["range"])) headers["Range"] else headers["range"]
|
||||
if (StringUtils.isAllBlank(range)) range = "bytes=0-";
|
||||
SpiderDebug.log("---proxyMultiThread,Range:$range")
|
||||
val rangeObj = parseRange(
|
||||
|
|
@ -120,7 +128,8 @@ object DownloadMT {
|
|||
|
||||
/* respHeaders.put("Access-Control-Allow-Credentials", "true");
|
||||
respHeaders.put("Access-Control-Allow-Origin", "*");*/
|
||||
resHeader["Content-Length"] = (partList[THREAD_NUM - 1][1] - partList[0][0] + 1).toString()
|
||||
resHeader["Content-Length"] =
|
||||
(partList[THREAD_NUM - 1][1] - partList[0][0] + 1).toString()
|
||||
resHeader.remove("content-length")
|
||||
|
||||
resHeader["Content-Range"] = String.format(
|
||||
|
|
@ -147,10 +156,12 @@ object DownloadMT {
|
|||
fun generatePart(rangeObj: Map<String?, String>, total: String): List<LongArray> {
|
||||
val totalSize = total.toLong()
|
||||
//超过10GB,分块是32Mb,不然是16MB
|
||||
val partSize = if (totalSize > 1024L * 1024L * 1024L * 10L) 1024 * 1024 * 8 * 4L else 1024 * 1024 * 8 * 2L
|
||||
val partSize =
|
||||
if (totalSize > 1024L * 1024L * 1024L * 10L) 1024 * 1024 * 8 * 4L else 1024 * 1024 * 8 * 2L
|
||||
|
||||
var start = rangeObj["start"]!!.toLong()
|
||||
var end = if (StringUtils.isAllBlank(rangeObj["end"])) start + partSize else rangeObj["end"]!!.toLong()
|
||||
var end =
|
||||
if (StringUtils.isAllBlank(rangeObj["end"])) start + partSize else rangeObj["end"]!!.toLong()
|
||||
|
||||
|
||||
end = min(end.toDouble(), (totalSize - 1).toDouble()).toLong()
|
||||
|
|
|
|||
|
|
@ -8,12 +8,11 @@ import kotlinx.coroutines.Job
|
|||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
|
||||
object ProxyServer {
|
||||
private val THREAD_NUM = Runtime.getRuntime().availableProcessors()
|
||||
private val partSize = 1024 * 1024
|
||||
private val partSize = 1024 * 1024 * 2
|
||||
private var port = 12345
|
||||
private var httpServer: AdvancedHttpServer? = null
|
||||
private val infos = mutableMapOf<String, MutableMap<String, MutableList<String>>>();
|
||||
|
|
@ -38,20 +37,15 @@ object ProxyServer {
|
|||
}
|
||||
};
|
||||
httpServer?.addRoutes("/proxy") { req, response ->
|
||||
try {
|
||||
run {
|
||||
val key = req.queryParams["key"];
|
||||
val url = urlMap[key]
|
||||
val header = headerMap[key]
|
||||
run {
|
||||
val key = req.queryParams["key"];
|
||||
val url = urlMap[key]
|
||||
val header = headerMap[key]
|
||||
|
||||
if (url != null && header != null) {
|
||||
proxyAsync(url, header, req, response)
|
||||
}
|
||||
if (url != null && header != null) {
|
||||
proxyAsync(url, header, req, response)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
SpiderDebug.log("代理视频出错:" + e.message)
|
||||
}
|
||||
|
||||
}
|
||||
httpServer?.start()
|
||||
|
||||
|
|
@ -144,13 +138,7 @@ object ProxyServer {
|
|||
producerJob += CoroutineScope(Dispatchers.IO).launch {
|
||||
// 异步下载数据块
|
||||
val data = getVideoStream(chunkStart, chunkEnd, url, headers)
|
||||
//如果是0开始,且检测到恶意头,那么就把数据截断
|
||||
if (chunkStart == 0L) {
|
||||
val offset = detectMaliciousPrefix(data)
|
||||
channels[i].send(data.copyOfRange(offset, data.size))
|
||||
} else {
|
||||
channels[i].send(data)
|
||||
}
|
||||
channels[i].send(data)
|
||||
|
||||
}
|
||||
currentStart = chunkEnd + 1
|
||||
|
|
@ -176,64 +164,6 @@ object ProxyServer {
|
|||
}
|
||||
}
|
||||
|
||||
fun detectMaliciousPrefix(data: ByteArray): Int {
|
||||
|
||||
|
||||
val buffer = ByteArray(64) // 读取前64字节足够
|
||||
ByteArrayInputStream(data).use { fis ->
|
||||
fis.read(buffer)
|
||||
}
|
||||
|
||||
// 检查是否以合法魔数开头
|
||||
if (isValidVideoHeader(buffer)) {
|
||||
return 0 // 正常,无恶意前缀
|
||||
}
|
||||
|
||||
// 在后续位置查找合法魔数(比如最多跳过前256字节)
|
||||
val searchLimit = minOf(256, data.size)
|
||||
val searchBuffer = ByteArray(searchLimit)
|
||||
ByteArrayInputStream(data).use { fis ->
|
||||
fis.read(searchBuffer)
|
||||
}
|
||||
|
||||
// 尝试从偏移1开始查找合法视频头
|
||||
for (offset in 1 until searchLimit - 16) {
|
||||
if (isValidVideoHeader(searchBuffer, offset)) {
|
||||
SpiderDebug.log("发现合法视频头位于偏移 $offset,疑似被插入恶意前缀!")
|
||||
return offset
|
||||
}
|
||||
}
|
||||
|
||||
return 0 // 未找到合法头,可能是损坏或非视频文件
|
||||
}
|
||||
|
||||
// 判断从指定偏移开始是否是合法视频头
|
||||
fun isValidVideoHeader(data: ByteArray, offset: Int = 0): Boolean {
|
||||
if (data.size - offset < 8) return false
|
||||
|
||||
// MP4 / MOV: ... ftyp
|
||||
if (offset + 8 <= data.size && data[offset + 4].toInt() == 0x66 && // 'f'
|
||||
data[offset + 5].toInt() == 0x74 && // 't'
|
||||
data[offset + 6].toInt() == 0x79 && // 'y'
|
||||
data[offset + 7].toInt() == 0x70 // 'p'
|
||||
) {
|
||||
// 还可进一步校验前4字节是否为合法 size(>=8 且合理)
|
||||
val size =
|
||||
(data[offset].toLong() and 0xFF shl 24) or (data[offset + 1].toLong() and 0xFF shl 16) or (data[offset + 2].toLong() and 0xFF shl 8) or (data[offset + 3].toLong() and 0xFF)
|
||||
if (size >= 8 && size <= 0x100000) return true
|
||||
}
|
||||
|
||||
// AVI: RIFF
|
||||
if (offset + 4 <= data.size && data[offset] == 0x52.toByte() && data[offset + 1] == 0x49.toByte() && data[offset + 2] == 0x46.toByte() && data[offset + 3] == 0x46.toByte()) return true
|
||||
|
||||
// MKV
|
||||
if (offset + 4 <= data.size && data[offset] == 0x1A.toByte() && data[offset + 1] == 0x45.toByte() && data[offset + 2] == 0xDF.toByte() && data[offset + 3] == 0xA3.toByte()) return true
|
||||
|
||||
// FLV
|
||||
if (offset + 4 <= data.size && data[offset] == 0x46.toByte() && data[offset + 1] == 0x4C.toByte() && data[offset + 2] == 0x56.toByte() && data[offset + 3] == 0x01.toByte()) return true
|
||||
|
||||
return false
|
||||
}
|
||||
private fun queryToMap(query: String?): Map<String, String>? {
|
||||
if (query == null) {
|
||||
return null
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ import java.util.*;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static android.net.Uri.encode;
|
||||
|
||||
public class Util {
|
||||
public static final String patternAli = "(https:\\/\\/www\\.aliyundrive\\.com\\/s\\/[^\"]+|https:\\/\\/www\\.alipan\\.com\\/s\\/[^\"]+)";
|
||||
public static final String patternQuark = "(https:\\/\\/pan\\.quark\\.cn\\/s\\/[^\"]+)";
|
||||
|
|
@ -32,8 +30,6 @@ public class Util {
|
|||
public static final Pattern RULE = Pattern.compile("http((?!http).){12,}?\\.(m3u8|mp4|mkv|flv|mp3|m4a|aac)\\?.*|http((?!http).){12,}\\.(m3u8|mp4|mkv|flv|mp3|m4a|aac)|http((?!http).)*?video/tos*");
|
||||
public static final Pattern THUNDER = Pattern.compile("(magnet|thunder|ed2k):.*");
|
||||
public static final String CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36";
|
||||
public static final String MOBILE = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Mobile Safari/537.36 Edg/142.0.0.0";
|
||||
|
||||
public static final String ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7";
|
||||
public static final List<String> MEDIA = Arrays.asList("mp4", "mkv", "wmv", "flv", "avi", "iso", "mpg", "ts", "mp3", "aac", "flac", "m4a", "ape", "ogg");
|
||||
public static final List<String> SUB = Arrays.asList("srt", "ass", "ssa", "vtt");
|
||||
|
|
@ -261,12 +257,6 @@ public class Util {
|
|||
return "";
|
||||
}
|
||||
}
|
||||
public static String getStrByRegex(Pattern pattern, String str) {
|
||||
Matcher matcher = pattern.matcher(str);
|
||||
if (matcher.find()) return matcher.group(1).trim();
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public static String base64Decode(String s) {
|
||||
return new String(android.util.Base64.decode(s, Base64.NO_WRAP), Charset.defaultCharset());
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
import android.app.Application;
|
||||
import com.github.catvod.spider.Init;
|
||||
import com.github.catvod.spider.Pan123;
|
||||
import com.github.catvod.spider.TianYi;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class Pan123Test {
|
||||
|
||||
private Application mockContext;
|
||||
|
||||
private Pan123 spider;
|
||||
|
||||
@org.junit.Before
|
||||
public void setUp() throws Exception {
|
||||
mockContext = RuntimeEnvironment.application;
|
||||
Init.init(mockContext);
|
||||
spider = new Pan123();
|
||||
// spider.init(mockContext, "b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; _UP_A4A_11_=wb9661c6dfb642f88f73d8e0c7edd398; b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; ctoken=wla6p3EUOLyn1FSB8IKp1SEW; grey-id=5583e32b-39df-4bf0-f39f-1adf83f604a2; grey-id.sig=p8ReBIMG2BeZu1sYvsuOAZxYbx-MVrsfKEiCv87MsTM; isQuark=true; isQuark.sig=hUgqObykqFom5Y09bll94T1sS9abT1X-4Df_lzgl8nM; _UP_F7E_8D_=ZkyvVHnrBLp1A1NFJIjWi0PwKLOVbxJPcg0RzQPI6KmBtV6ZMgPh38l93pgubgHDQqhaZ2Sfc0qv%2BRantbfg1mWGAUpRMP4RqXP78Wvu%2FCfvkWWGc5NhCTV71tGOIGgDBR3%2Bu6%2Fjj44KlE5biSNDOWW7Bigcz27lvOTidzNw8s%2FWtKAIxWbnCzZn4%2FJMBUub1SIMcW89g57k4mfPmDlCgpZKzxwl6beSfdtZ4RUWXmZOn5v5NkxVKhU4wR0Pq7NklczEGdRq2nIAcu7v22Uw2o%2FxMY0xBdeC9Korm5%2FNHnxl6K%2Bd6FXSoT9a3XIMQO359auZPiZWzrNlZe%2BqnOahXcx7KAhQIRqSOapSmL4ygJor4r5isJhRuDoXy7vJAVuH%2FRDtEJJ8rZTq0BdC23Bz%2B0MrsdgbK%2BiW; _UP_D_=pc; __wpkreporterwid_=3d3f74a7-99b7-4916-3f78-911fc2eb9d87; tfstk=fIoZNxjnbhKwPOu0TWZ4LsaRqirTcudSSmNbnxD0C5VgClMm8xMyB-GsnSu4tjpOflAOmSD-9PNiGl120XrgkVNb1SrqHbJBN3tSBAEYoQOWVUUg9qZ8n1bGGkD3CqGYINKSBABhjnXgp3_Vywz6gSc0Syj3BWf0mr2DLW24eZfiiovEKWefj1q0swq3E82iNEMinMy7SLrcpA4Fh3z_ZAViCfih3PbtdW5N_DuU77AaTijmYRkL2Wq54ENoy5a7ZXxCbok33XzS7QSZgxD-oyoVsdGotql0p2dVu7umC4nLStbiLmParc4FELHrI-c0u2dPVRrs8zoZWKCnIbNZrlHfUCMUz2z8KyXVSlgSFmUojh58OzeqTzgwaGll4YCYKwctDV5coP2LL79eKHxpNTXHmre1kZU32JPWCR_AkP2LL79eLZQY-WeUNdw1.; __pus=2051c82285199d8be553be41dd5a2100AAQ+mmv35G4FDDZ5x+3Mhe2OMbNgweQ1ODbW8zDt9YuP1LQVqHUuAAz9KWLsPjpNtim0AVGHusN4MCosTmbq/khM; __kp=e6604120-6051-11ef-bfe4-c31b6cdd0766; __kps=AATcZArVgS76EPn0FMaV4HEj; __ktd=sii/iz4ePzEaoVirXul7QQ==; __uid=AATcZArVgS76EPn0FMaV4HEj; __itrace_wid=5829b95d-dac1-48d3-bfd5-f60cd9462786; __puus=7da0b96cb710fa1b376934485f977e05AATp/q8/QupT7IiBR1GWqZhxlIRT677smMvoHlLxQA0Lk6CkP0YJBOTl+p9DZgzlMz6w4hPXPgWsokukk8PW7ZfhFfPmv8tKMgLpCGLW+tk57luhNghmSdTeVPkAF59STtyCPBEtiNzNAd/zZJ6qILJDi5ywEBAAAg+gOyWHoLHNUR+QxeHRuQa8g5WWA95J8jebIlrr8rCvI1vjTbtiYktT");
|
||||
// spider.init(mockContext, "{\"open.e.189.cn\":[{\"name\":\"SSON\",\"value\":\"dc466c8192e3109eaea837c1d136c1fd065253ce1c7d3a66ca1520d7d6d6307b10a1fe65c7becac73b95f24a6e681e654ec4f47c39533ebcc48bb78d6d6e63d1bbf3334e6e97eaa7092d34f87bf1209ee35f344871bc5a329eac34ae948d399d4a6b3b28a929c4f353ade0981657e9e0f09ce27cc1c15d8322c6e45a8ebb21eb431509f1dd7dc3a7856b32b0991d654d5ced73dd20b764ca8737600cbe699c37ccf59b3c610893fc42bdc08b477c5d394e290c14d175d1ca0ee9fa61a1a8dcac7007e9219fd0ae6ccd5dc760524213f85b6b8c6166af01a31336dab797d9118010b81a5a3c26e08e\",\"expiresAt\":253402300799999,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":true,\"httpOnly\":true,\"persistent\":true,\"hostOnly\":false},{\"name\":\"GUID\",\"value\":\"525d8874e53e46a7ba3ed8907e9fef1f\",\"expiresAt\":1775176321000,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":false,\"persistent\":true,\"hostOnly\":false},{\"name\":\"pageOp\",\"value\":\"336b9ddc820212fa6c9b5a0cfd7bf5b3\",\"expiresAt\":253402300799999,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":false,\"persistent\":false,\"hostOnly\":false},{\"name\":\"OPENINFO\",\"value\":\"33c28688ef52ce9e3a9ef87388047efbde5e3e2e4c7ef6ef267632468c7dfaf294ff59fa59d34801\",\"expiresAt\":253402300799999,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":true,\"persistent\":false,\"hostOnly\":false},{\"name\":\"GRAYNUMBER\",\"value\":\"319DE3F68C8730862F3BEF66F3D635B7\",\"expiresAt\":1775177653000,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":false,\"persistent\":true,\"hostOnly\":false}],\"cloud.189.cn\":[{\"name\":\"JSESSIONID\",\"value\":\"431787526C43DF21B6373E914FE597EC\",\"expiresAt\":253402300799999,\"domain\":\"cloud.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":true,\"persistent\":false,\"hostOnly\":true},{\"name\":\"COOKIE_LOGIN_USER\",\"value\":\"0C7407F59A6E5896EB6B777056E160DB020BAE67B121B5930CCD4777073744055308F7E8CD03F2FC2399E4823F60ECDD74120CEE4C529017\",\"expiresAt\":253402300799999,\"domain\":\"cloud.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":true,\"persistent\":false,\"hostOnly\":false}]}");
|
||||
// Server.get().start();
|
||||
spider.init(mockContext, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NjE1MjEyNzksImlhdCI6MTc2MDkxNjQ3OSwiaWQiOjE4NDc0Mjg3NzAsIm1haWwiOiIiLCJuaWNrbmFtZSI6IjE4ODk2NzgxNjAxIiwic3VwcGVyIjpmYWxzZSwidXNlcm5hbWUiOjE4ODk2NzgxNjAxLCJ2IjowfQ.gVhIfG1t2tUts68eYY-AdUfJoBKBNeG41k3XGYfwCek");
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void init() throws Exception {
|
||||
spider.init(mockContext, "{\"open.e.189.cn\":[{\"name\":\"SSON\",\"value\":\"dc466c8192e3109eaea837c1d136c1fd065253ce1c7d3a66ca1520d7d6d6307b10a1fe65c7becac73b95f24a6e681e654ec4f47c39533ebcc48bb78d6d6e63d1bbf3334e6e97eaa7092d34f87bf1209ee35f344871bc5a329eac34ae948d399d4a6b3b28a929c4f353ade0981657e9e0f09ce27cc1c15d8322c6e45a8ebb21eb431509f1dd7dc3a7856b32b0991d654d5ced73dd20b764ca8737600cbe699c37ccf59b3c610893fc42bdc08b477c5d394e290c14d175d1ca0ee9fa61a1a8dcac7007e9219fd0ae6ccd5dc760524213f85b6b8c6166af01a31336dab797d9118010b81a5a3c26e08e\",\"expiresAt\":253402300799999,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":true,\"httpOnly\":true,\"persistent\":true,\"hostOnly\":false},{\"name\":\"GUID\",\"value\":\"525d8874e53e46a7ba3ed8907e9fef1f\",\"expiresAt\":1775176321000,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":false,\"persistent\":true,\"hostOnly\":false},{\"name\":\"pageOp\",\"value\":\"336b9ddc820212fa6c9b5a0cfd7bf5b3\",\"expiresAt\":253402300799999,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":false,\"persistent\":false,\"hostOnly\":false},{\"name\":\"OPENINFO\",\"value\":\"33c28688ef52ce9e3a9ef87388047efbde5e3e2e4c7ef6ef267632468c7dfaf294ff59fa59d34801\",\"expiresAt\":253402300799999,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":true,\"persistent\":false,\"hostOnly\":false},{\"name\":\"GRAYNUMBER\",\"value\":\"319DE3F68C8730862F3BEF66F3D635B7\",\"expiresAt\":1775177653000,\"domain\":\"e.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":false,\"persistent\":true,\"hostOnly\":false}],\"cloud.189.cn\":[{\"name\":\"JSESSIONID\",\"value\":\"431787526C43DF21B6373E914FE597EC\",\"expiresAt\":253402300799999,\"domain\":\"cloud.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":true,\"persistent\":false,\"hostOnly\":true},{\"name\":\"COOKIE_LOGIN_USER\",\"value\":\"0C7407F59A6E5896EB6B777056E160DB020BAE67B121B5930CCD4777073744055308F7E8CD03F2FC2399E4823F60ECDD74120CEE4C529017\",\"expiresAt\":253402300799999,\"domain\":\"cloud.189.cn\",\"path\":\"/\",\"secure\":false,\"httpOnly\":true,\"persistent\":false,\"hostOnly\":false}]}");
|
||||
//Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void detailContent() throws Exception {
|
||||
|
||||
String content = spider.detailContent(Arrays.asList("https://www.123865.com/s/u9izjv-6hSWv"));
|
||||
System.out.println("detailContent--" + content);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("detailContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void playerContent() throws Exception {
|
||||
|
||||
String content = spider.playerContent("pan123原画","eyJmaWxlbmFtZSI6IuWRveaCrOS4gOeUny5TMDFFMDEuMjAyNS4yMTYwcC5XRUItREwuSDI2NS5ERFA1LjEubWt2Iiwic2hhcmVLZXkiOiJ1OWl6anYtNmhTV3YiLCJzaGFyZVB3ZCI6IiIsIm5leHQiOi0xLCJmaWxlSWQiOjI3MzQ0MjY3LCJTM0tleUZsYWciOiIxODI3MDg2NzQ5LTAiLCJTaXplIjoxNDExNDM3ODI2LCJFdGFnIjoiZGZmOGZlZWU2N2JkYzRhOTQxMjlhZTJlNTg1YmI0Y2QifQ==",new ArrayList<>());
|
||||
System.out.println("playerContent--" + content);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("playerContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonPrimitive("url").getAsString().isEmpty());
|
||||
while(true){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ public class QuarkTest {
|
|||
Init.init(mockContext);
|
||||
spider = new Quark();
|
||||
// spider.init(mockContext, "b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; _UP_A4A_11_=wb9661c6dfb642f88f73d8e0c7edd398; b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; ctoken=wla6p3EUOLyn1FSB8IKp1SEW; grey-id=5583e32b-39df-4bf0-f39f-1adf83f604a2; grey-id.sig=p8ReBIMG2BeZu1sYvsuOAZxYbx-MVrsfKEiCv87MsTM; isQuark=true; isQuark.sig=hUgqObykqFom5Y09bll94T1sS9abT1X-4Df_lzgl8nM; _UP_F7E_8D_=ZkyvVHnrBLp1A1NFJIjWi0PwKLOVbxJPcg0RzQPI6KmBtV6ZMgPh38l93pgubgHDQqhaZ2Sfc0qv%2BRantbfg1mWGAUpRMP4RqXP78Wvu%2FCfvkWWGc5NhCTV71tGOIGgDBR3%2Bu6%2Fjj44KlE5biSNDOWW7Bigcz27lvOTidzNw8s%2FWtKAIxWbnCzZn4%2FJMBUub1SIMcW89g57k4mfPmDlCgpZKzxwl6beSfdtZ4RUWXmZOn5v5NkxVKhU4wR0Pq7NklczEGdRq2nIAcu7v22Uw2o%2FxMY0xBdeC9Korm5%2FNHnxl6K%2Bd6FXSoT9a3XIMQO359auZPiZWzrNlZe%2BqnOahXcx7KAhQIRqSOapSmL4ygJor4r5isJhRuDoXy7vJAVuH%2FRDtEJJ8rZTq0BdC23Bz%2B0MrsdgbK%2BiW; _UP_D_=pc; __wpkreporterwid_=3d3f74a7-99b7-4916-3f78-911fc2eb9d87; tfstk=fIoZNxjnbhKwPOu0TWZ4LsaRqirTcudSSmNbnxD0C5VgClMm8xMyB-GsnSu4tjpOflAOmSD-9PNiGl120XrgkVNb1SrqHbJBN3tSBAEYoQOWVUUg9qZ8n1bGGkD3CqGYINKSBABhjnXgp3_Vywz6gSc0Syj3BWf0mr2DLW24eZfiiovEKWefj1q0swq3E82iNEMinMy7SLrcpA4Fh3z_ZAViCfih3PbtdW5N_DuU77AaTijmYRkL2Wq54ENoy5a7ZXxCbok33XzS7QSZgxD-oyoVsdGotql0p2dVu7umC4nLStbiLmParc4FELHrI-c0u2dPVRrs8zoZWKCnIbNZrlHfUCMUz2z8KyXVSlgSFmUojh58OzeqTzgwaGll4YCYKwctDV5coP2LL79eKHxpNTXHmre1kZU32JPWCR_AkP2LL79eLZQY-WeUNdw1.; __pus=2051c82285199d8be553be41dd5a2100AAQ+mmv35G4FDDZ5x+3Mhe2OMbNgweQ1ODbW8zDt9YuP1LQVqHUuAAz9KWLsPjpNtim0AVGHusN4MCosTmbq/khM; __kp=e6604120-6051-11ef-bfe4-c31b6cdd0766; __kps=AATcZArVgS76EPn0FMaV4HEj; __ktd=sii/iz4ePzEaoVirXul7QQ==; __uid=AATcZArVgS76EPn0FMaV4HEj; __itrace_wid=5829b95d-dac1-48d3-bfd5-f60cd9462786; __puus=7da0b96cb710fa1b376934485f977e05AATp/q8/QupT7IiBR1GWqZhxlIRT677smMvoHlLxQA0Lk6CkP0YJBOTl+p9DZgzlMz6w4hPXPgWsokukk8PW7ZfhFfPmv8tKMgLpCGLW+tk57luhNghmSdTeVPkAF59STtyCPBEtiNzNAd/zZJ6qILJDi5ywEBAAAg+gOyWHoLHNUR+QxeHRuQa8g5WWA95J8jebIlrr8rCvI1vjTbtiYktT");
|
||||
spider.init(mockContext, "_UP_28A_52_=386;_UP_BT_=html5;_UP_F7E_8D_=0z44HdIBxZZTFH3p1NV%2FwWJIkAWBTYaH20RoPCksvMmyhI6XxrMIHoi8gAqVoKf%2Bfw0hw4mmmcFLHpvA%2Fhicy1HUTu2LBlCP6GF%2FnM%2Bm0IJoj1BQdak3tm1o3OeN1OV9dQAEQ0UDfWTXDik4ZZxmO5Iwvj6IsFkb5GPrrCl5M87ivs0EP%2FjAQTQimMgEdat62Byd22%2BZGM703ymU3s8N9B3XRdiyy8E7vOTidzNw8s%2FWtKAIxWbnCzZn4%2FJMBUubLuroBmVIB9UVOMEdD6uzZJXMxBnUatpyAHLu79tlMNqP8TGNMQXXgvSqK5ufzR58ZeivnehV0qE%2FWt1yDEDt%2BfWrmT4mVs6zZWXvqpzmoV3MeygIUCEakh2GAn6rsLT1b2ZsrSkQkrM6F8u7yQFbh%2F0Q7RCSfK2U6tAXQttwc%2FtDK7HYGyvolg%3D%3D;_UP_6D1_64_=069;_UP_A4A_11_=wb9cc1693e1d486b8b2ac58e4839d64e;_UP_D_=mobilectoken=4IUaeDKAfn3pV-MKaWfg_GHG;__pus=76f683009a07bdd1c1a7c04f05838d4bAASVSWCD2jiL0GI43jmIC5x50sk6Tgbh4UtXFf/vqOUyaX8Aory/bsGsGCTl68Lo7sJPpZpBJdif81oItfZizhzH;__kp=d8da7a20-7522-11f0-8e98-7daef001221f;__kps=AATcZArVgS76EPn0FMaV4HEj;__ktd=sii/iz4ePzEaoVirXul7QQ==;__uid=AATcZArVgS76EPn0FMaV4HEj;__puus=b4617d4cdadeb05679ed39be924d99d8AATp/q8/QupT7IiBR1GWqZhx6c42nqKQR/5g49EMGJ5TE742htjk9EkPPibrpvSh8/N8ybuC/Wc4BP1YbLBb5ZFEEOPrmFBTCZtKVEh5HcqkSL6T6LoyeKfvGe32k9HckqoPn9MxbAThhpRlbHg8QgH8OwxLHp0V2cAYcsGY72XN2ZPL7JzZyOAwmSsJwpX9B0+LYNvco+Ixucn5KaaCTKND");
|
||||
spider.init(mockContext, "_UP_A4A_11_=wb9681fbaed6454a8112f31e53b5c0be; __pus=45beefa93e8775c9211487d0c8ddd2b1AASCmV5S7LY0dfX90N3p4wU/G4f/oS0gZK6cpxZMZiDtXt9s7KiSs3tVZOXnIDel69C9KaQ61IQlnLYH2rS4NGjO; __kp=fe663a90-68d5-11ef-8b23-e77b0eaa352c; __kps=AAT32Fob+vq66znO5UHSHAPi; __ktd=39oXE+BT53YlFgUfFVq9kw==; __uid=AAT32Fob+vq66znO5UHSHAPi; xlly_s=1; b-user-id=91d551ad-db9e-f092-2b42-aa4db35b8ed0; isg=BNXVFRgkH_dXwTuJ8PizGl2W5NGP0onkjXrhLld60cybrvegHyMutYcsfLIYrqGc; tfstk=fNlSqGqmrgj57RpyCwL4hfk8bfFCODOw9waKS2CPJ7F-JWib0zWyEJ-IhDn42_P82ZEQ7caRpHf8M9aTxuFEUuzKc2nJry8uwiCY7PzLvzeLHsUUP6Ud9WQoncuOabJuT6NutWKwbCRZz4V39rUtZ-SukyUWT_U8JbtmmvxwbCR2eZFBVhkeml_RcyqYyzEdwENYSyFdv_nLD-UT7gFKvWLbHy4G2aCLJoUYJoEL9WnKkjXR5y97q4TY2O9qutVEyo1soja-eT0zc6CKGxw7XBrf96hbPqfsiZf6LlHg4RrtDI57OqUIcRkWf_iIJVDLhXsJzcnxdDUmnH6Qfv3rIj2RJT3jOuwtw-_9SVg8JDeInh1aP7kbCbMk-i3-buMTZ2764qwshR4YHw68aAuZtRhJNGq4IyibQYt1NcIzH1r_KcBClRfQll8Xl9Xh_6YQJFIaDQy8ozw2lEs-K8U0ll8Xl9X3er477ETf2vf..; __puus=514ad4334da84f912529719d557085b2AASV1aKJKLRXGjvHRfwQJ5gupjOzlxgeAImozKKYdppZduMrKS7Q5+3hUZZ0f6zk7YpAGu7p0GVPYojTpZdhvnamXzCBLryM3ULhlqkw9yR6oVeTr3b1MituYgqfeFM4jHi4ASNiLk22pCNKteAtD6aowAM0K1ZFVc7j7xlpxLEgS1CoNSttupAb56Zf+ruuTkDPsjZPiRW1S4yM/kduA247");
|
||||
Server.get().start();
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ public class QuarkTest {
|
|||
@org.junit.Test
|
||||
public void detailContent() throws Exception {
|
||||
|
||||
String content = spider.detailContent(Arrays.asList("https://pan.quark.cn/s/469c2acf8640"));
|
||||
String content = spider.detailContent(Arrays.asList("https://pan.quark.cn/s/38c5e16d71f7"));
|
||||
System.out.println("detailContent--" + content);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
|
@ -52,7 +52,7 @@ public class QuarkTest {
|
|||
@org.junit.Test
|
||||
public void playerContent() throws Exception {
|
||||
|
||||
String content = spider.playerContent("quark原画", "a04522f504a742db8ebaf69e3b7f50d6++375807f3f1068a8fdabac127ec4db89f++469c2acf8640++PVTgPNXNtRFDDkE6SAYX4KPSjk9xl449JkTHl6mtu7k=", new ArrayList<>());
|
||||
String content = spider.playerContent("普画","41ea9a50cbdd4e50b019bcd78687ebc1++22fc6fa8350d22e0eaecc49035368e81++38c5e16d71f7++WFcYTmRhjJpKTui56aleYdzBZi9R203GERBVzYNxDxI=",new ArrayList<>());
|
||||
System.out.println("playerContent--" + content);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
|
|
|||
|
|
@ -1,100 +0,0 @@
|
|||
import android.app.Application;
|
||||
import com.github.catvod.server.Server;
|
||||
import com.github.catvod.spider.Init;
|
||||
import com.github.catvod.spider.SeedHub;
|
||||
import com.github.catvod.spider.Wogg;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class SeedHubTest {
|
||||
|
||||
private Application mockContext;
|
||||
|
||||
private SeedHub spider;
|
||||
|
||||
@org.junit.Before
|
||||
public void setUp() throws Exception {
|
||||
mockContext = RuntimeEnvironment.application;
|
||||
Init.init(mockContext);
|
||||
spider = new SeedHub();
|
||||
Server.get().start();
|
||||
// spider.init(mockContext, "{\"cookie\":\"b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; _UP_A4A_11_=wb9661c6dfb642f88f73d8e0c7edd398; b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; ctoken=wla6p3EUOLyn1FSB8IKp1SEW; grey-id=5583e32b-39df-4bf0-f39f-1adf83f604a2; grey-id.sig=p8ReBIMG2BeZu1sYvsuOAZxYbx-MVrsfKEiCv87MsTM; isQuark=true; isQuark.sig=hUgqObykqFom5Y09bll94T1sS9abT1X-4Df_lzgl8nM; _UP_F7E_8D_=ZkyvVHnrBLp1A1NFJIjWi0PwKLOVbxJPcg0RzQPI6KmBtV6ZMgPh38l93pgubgHDQqhaZ2Sfc0qv%2BRantbfg1mWGAUpRMP4RqXP78Wvu%2FCfvkWWGc5NhCTV71tGOIGgDBR3%2Bu6%2Fjj44KlE5biSNDOWW7Bigcz27lvOTidzNw8s%2FWtKAIxWbnCzZn4%2FJMBUub1SIMcW89g57k4mfPmDlCgpZKzxwl6beSfdtZ4RUWXmZOn5v5NkxVKhU4wR0Pq7NklczEGdRq2nIAcu7v22Uw2o%2FxMY0xBdeC9Korm5%2FNHnxl6K%2Bd6FXSoT9a3XIMQO359auZPiZWzrNlZe%2BqnOahXcx7KAhQIRqSOapSmL4ygJor4r5isJhRuDoXy7vJAVuH%2FRDtEJJ8rZTq0BdC23Bz%2B0MrsdgbK%2BiW; _UP_D_=pc; __wpkreporterwid_=3d3f74a7-99b7-4916-3f78-911fc2eb9d87; tfstk=fIoZNxjnbhKwPOu0TWZ4LsaRqirTcudSSmNbnxD0C5VgClMm8xMyB-GsnSu4tjpOflAOmSD-9PNiGl120XrgkVNb1SrqHbJBN3tSBAEYoQOWVUUg9qZ8n1bGGkD3CqGYINKSBABhjnXgp3_Vywz6gSc0Syj3BWf0mr2DLW24eZfiiovEKWefj1q0swq3E82iNEMinMy7SLrcpA4Fh3z_ZAViCfih3PbtdW5N_DuU77AaTijmYRkL2Wq54ENoy5a7ZXxCbok33XzS7QSZgxD-oyoVsdGotql0p2dVu7umC4nLStbiLmParc4FELHrI-c0u2dPVRrs8zoZWKCnIbNZrlHfUCMUz2z8KyXVSlgSFmUojh58OzeqTzgwaGll4YCYKwctDV5coP2LL79eKHxpNTXHmre1kZU32JPWCR_AkP2LL79eLZQY-WeUNdw1.; __pus=2051c82285199d8be553be41dd5a2100AAQ+mmv35G4FDDZ5x+3Mhe2OMbNgweQ1ODbW8zDt9YuP1LQVqHUuAAz9KWLsPjpNtim0AVGHusN4MCosTmbq/khM; __kp=e6604120-6051-11ef-bfe4-c31b6cdd0766; __kps=AATcZArVgS76EPn0FMaV4HEj; __ktd=sii/iz4ePzEaoVirXul7QQ==; __uid=AATcZArVgS76EPn0FMaV4HEj; __itrace_wid=5829b95d-dac1-48d3-bfd5-f60cd9462786; __puus=7da0b96cb710fa1b376934485f977e05AATp/q8/QupT7IiBR1GWqZhxlIRT677smMvoHlLxQA0Lk6CkP0YJBOTl+p9DZgzlMz6w4hPXPgWsokukk8PW7ZfhFfPmv8tKMgLpCGLW+tk57luhNghmSdTeVPkAF59STtyCPBEtiNzNAd/zZJ6qILJDi5ywEBAAAg+gOyWHoLHNUR+QxeHRuQa8g5WWA95J8jebIlrr8rCvI1vjTbtiYktT\",\"token\":\"26fc6787afff43e78b78992e782502f1\"}");
|
||||
spider.init(mockContext, "{\"site\": [\"https://www.wogg.net/\",\"https://wogg.xxooo.cf/\"],\"uccookie\":\"_UP_28A_52_=381;_UP_BT_=html5;_UP_F7E_8D_=ZkyvVHnrBLp1A1NFJIjWi0PwKLOVbxJPcg0RzQPI6Kl8ttcYB1X9Nkx0DnGMyJVLgv0M%2FCztZQaIhZhKaI%2F0Fa%2F5Fqe1t%2BDWF1o9sO71vnupc%2Fvxa%2B78J%2B%2BRZYZzk2EJNXvW0Y4gaAMFHf67r%2BOPjtggEPU7aNnlZbsGKBzPbuW85OJ3M3Dyz9a0oAjFZucLNmfj8kwFS5su6ugGZUgH1RU4wR0Pq7NklczEGdRq2nIAcu7v22Uw2o%2FxMY0xBdeC9Korm5%2FNHnxl6K%2Bd6FXSoT9a3XIMQO359auZPiZWzrNlZe%2BqnOahXcx7KAhQIRqSHYYCfquwtPWx%2FgYBqTnLfzoXy7vJAVuH%2FRDtEJJ8rZTq0BdC23Bz%2B0MrsdgbK%2BiW;_UP_6D1_64_=069;_UP_A4A_11_=wb96b12a16f941809f5af993726ba192;_UP_D_=mobilectoken=oxJV13ITm7aa7_rsplIXC-_v;__pus=cef2cc2dfd5d8af70df36bcedf83995cAAT3ZYhqlLos+yCaVQYYC944c4HEQnHz8uEpdQner0OcqISOpBObxl2kck65MGceRIDBd+MLtDxsNqwXvgDIFpYU;__kp=0d340990-9b39-11ef-ae54-4f733858896a;__kps=AAQXoZxLp9Oe2Ps0d/hNBJl4;__ktd=2gPNadz6Z9c+2+FyQyQZUw==;__uid=AAQXoZxLp9Oe2Ps0d/hNBJl4;UDRIVE_TRANSFER_SESS=UpLXXX2HAXJNW0AHgDcMurpazcqTbU-EQWnKG6RKtkdhdqZgHGTM-BSulf_oo1nmMMjo6hFdByLlm-bEiwjByMbIIEehsxhuuV00b96SSaPExn0wMcQ8SmzJa-YwonEE2MEVWCHcRYuW4Z-ljMOgab7qaGtQUpqjkl-p6OTv23BW-4gM6y7DNKvGeaMv_3NX\"," +
|
||||
"\"cookie\":\"b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; _UP_A4A_11_=wb9661c6dfb642f88f73d8e0c7edd398; b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; ctoken=wla6p3EUOLyn1FSB8IKp1SEW; grey-id=5583e32b-39df-4bf0-f39f-1adf83f604a2; grey-id.sig=p8ReBIMG2BeZu1sYvsuOAZxYbx-MVrsfKEiCv87MsTM; isQuark=true; isQuark.sig=hUgqObykqFom5Y09bll94T1sS9abT1X-4Df_lzgl8nM; _UP_F7E_8D_=ZkyvVHnrBLp1A1NFJIjWi0PwKLOVbxJPcg0RzQPI6KmBtV6ZMgPh38l93pgubgHDQqhaZ2Sfc0qv%2BRantbfg1mWGAUpRMP4RqXP78Wvu%2FCfvkWWGc5NhCTV71tGOIGgDBR3%2Bu6%2Fjj44KlE5biSNDOWW7Bigcz27lvOTidzNw8s%2FWtKAIxWbnCzZn4%2FJMBUub1SIMcW89g57k4mfPmDlCgpZKzxwl6beSfdtZ4RUWXmZOn5v5NkxVKhU4wR0Pq7NklczEGdRq2nIAcu7v22Uw2o%2FxMY0xBdeC9Korm5%2FNHnxl6K%2Bd6FXSoT9a3XIMQO359auZPiZWzrNlZe%2BqnOahXcx7KAhQIRqSOapSmL4ygJor4r5isJhRuDoXy7vJAVuH%2FRDtEJJ8rZTq0BdC23Bz%2B0MrsdgbK%2BiW; _UP_D_=pc; __wpkreporterwid_=3d3f74a7-99b7-4916-3f78-911fc2eb9d87; tfstk=fIoZNxjnbhKwPOu0TWZ4LsaRqirTcudSSmNbnxD0C5VgClMm8xMyB-GsnSu4tjpOflAOmSD-9PNiGl120XrgkVNb1SrqHbJBN3tSBAEYoQOWVUUg9qZ8n1bGGkD3CqGYINKSBABhjnXgp3_Vywz6gSc0Syj3BWf0mr2DLW24eZfiiovEKWefj1q0swq3E82iNEMinMy7SLrcpA4Fh3z_ZAViCfih3PbtdW5N_DuU77AaTijmYRkL2Wq54ENoy5a7ZXxCbok33XzS7QSZgxD-oyoVsdGotql0p2dVu7umC4nLStbiLmParc4FELHrI-c0u2dPVRrs8zoZWKCnIbNZrlHfUCMUz2z8KyXVSlgSFmUojh58OzeqTzgwaGll4YCYKwctDV5coP2LL79eKHxpNTXHmre1kZU32JPWCR_AkP2LL79eLZQY-WeUNdw1.; __pus=2051c82285199d8be553be41dd5a2100AAQ+mmv35G4FDDZ5x+3Mhe2OMbNgweQ1ODbW8zDt9YuP1LQVqHUuAAz9KWLsPjpNtim0AVGHusN4MCosTmbq/khM; __kp=e6604120-6051-11ef-bfe4-c31b6cdd0766; __kps=AATcZArVgS76EPn0FMaV4HEj; __ktd=sii/iz4ePzEaoVirXul7QQ==; __uid=AATcZArVgS76EPn0FMaV4HEj; __itrace_wid=5829b95d-dac1-48d3-bfd5-f60cd9462786; __puus=7da0b96cb710fa1b376934485f977e05AATp/q8/QupT7IiBR1GWqZhxlIRT677smMvoHlLxQA0Lk6CkP0YJBOTl+p9DZgzlMz6w4hPXPgWsokukk8PW7ZfhFfPmv8tKMgLpCGLW+tk57luhNghmSdTeVPkAF59STtyCPBEtiNzNAd/zZJ6qILJDi5ywEBAAAg+gOyWHoLHNUR+QxeHRuQa8g5WWA95J8jebIlrr8rCvI1vjTbtiYktT\",\"token\":\"26fc6787afff43e78b78992e782502f1\"}");
|
||||
// spider.init(mockContext, "");
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void homeContent() throws Exception {
|
||||
String content = spider.homeContent(true);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
System.out.println("homeContent--" + gson.toJson(map));
|
||||
|
||||
//Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void homeVideoContent() throws Exception {
|
||||
String content = spider.homeVideoContent();
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
System.out.println("homeVideoContent--" + gson.toJson(map));
|
||||
|
||||
// Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void categoryContent() throws Exception {
|
||||
String content = spider.categoryContent("2", "2", true, null);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("categoryContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void detailContent() throws Exception {
|
||||
|
||||
String content = spider.detailContent(Arrays.asList("/movies/113317/"));
|
||||
System.out.println("detailContent--" + content);
|
||||
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("detailContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void playerContent() throws Exception {
|
||||
String content = spider.playerContent("uc普画", "52fd84f0bfd44c93a1fca6c76d0b8d16++28d4a0a00ad96562f96506da49b988a0++5ae2d1c474024++yA4L8FmH06i8nfmmY4MwHNSsyhpVzLhzxqDixCp0xm4=", new ArrayList<>());
|
||||
System.out.println("playerContent--" + content);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("playerContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonPrimitive("url").getAsString().isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void searchContent() throws Exception {
|
||||
String content = spider.searchContent("红海", false);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("searchContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import android.app.Application;
|
||||
|
||||
import com.github.catvod.spider.DaGongRen;
|
||||
import com.github.catvod.spider.Init;
|
||||
import com.github.catvod.spider.Supjav;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class SupjavTest {
|
||||
// @Mock
|
||||
private Application mockContext;
|
||||
|
||||
private Supjav spider;
|
||||
|
||||
@org.junit.Before
|
||||
public void setUp() throws Exception {
|
||||
mockContext = RuntimeEnvironment.application;
|
||||
Init.init(mockContext);
|
||||
spider = new Supjav();
|
||||
spider.init(mockContext, "");
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void homeContent() throws Exception {
|
||||
String content = spider.homeContent(true);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
System.out.println("homeContent--" + gson.toJson(map));
|
||||
|
||||
//Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void homeVideoContent() throws Exception {
|
||||
String content = spider.homeVideoContent();
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
System.out.println("homeVideoContent--" + gson.toJson(map));
|
||||
|
||||
//Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void categoryContent() throws Exception {
|
||||
String content = spider.categoryContent("popular", "2", true, null);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("categoryContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void detailContent() throws Exception {
|
||||
|
||||
String content = spider.detailContent(Arrays.asList("288706.html"));
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("detailContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void playerContent() throws Exception {
|
||||
String froms = "FST$$$ST$$$VOE";
|
||||
String urls = "播放$7a39ff703f95e9c01ee6785def2cf624c8636748c26ab4afa219d49d98b7c77ebef268d993e34f9763bc07b2d690fb8d40ec53eb3cf4f17270830acf091765df$$$播放$a8a52ce3124daf8525aeaae8faf1a45e1e74d8b6e1b0db2ee59510d9a238d462be957d62dd34d708391cc6d394bc3bf326eeca43de00d2967a95ac96a12a3b94549b8fd2edab26b7049e1116b32c18c9$$$播放$0a38bff9ae3e860ff7cc5a760f2edd22604306efa019bf6d0adb9874e35d33b8a50955ac4154f2c25c073f23277513045b8c9b26fdfbb54fef4cad7eaf8a6b32"
|
||||
;
|
||||
for (int i = 0; i < urls.split("\\$\\$\\$").length; i++) {
|
||||
String content = spider.playerContent(froms.split("\\$\\$\\$")[i], urls.split("\\$\\$\\$")[i].split("\\$")[1], new ArrayList<>());
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("playerContent--" + gson.toJson(map));
|
||||
// Assert.assertFalse(map.getAsJsonPrimitive("url").getAsString().isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void searchContent() throws Exception {
|
||||
String content = spider.searchContent("fc", false);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("searchContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
import android.app.Application;
|
||||
import com.github.catvod.server.Server;
|
||||
import com.github.catvod.spider.Init;
|
||||
import com.github.catvod.spider.TgSearchBaidu;
|
||||
import com.github.catvod.spider.PanSearch;
|
||||
import com.github.catvod.spider.Tg189Search;
|
||||
import com.github.catvod.spider.TgQuarkSearch;
|
||||
import com.github.catvod.spider.TgSearch;
|
||||
import com.github.catvod.spider.TianYiSo;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
|
@ -11,7 +15,6 @@ import org.junit.runner.RunWith;
|
|||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
|
|
@ -19,23 +22,23 @@ public class TgSearchTest {
|
|||
|
||||
private Application mockContext;
|
||||
|
||||
private TgSearchBaidu spider;
|
||||
private TgQuarkSearch spider;
|
||||
|
||||
@org.junit.Before
|
||||
public void setUp() throws Exception {
|
||||
mockContext = RuntimeEnvironment.application;
|
||||
Init.init(mockContext);
|
||||
spider = new TgSearchBaidu();
|
||||
spider = new TgQuarkSearch();
|
||||
Server.get().start();
|
||||
// spider.init(mockContext, "{\"cookie\":\"b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; _UP_A4A_11_=wb9661c6dfb642f88f73d8e0c7edd398; b-user-id=89ede34e-0efc-e1dd-c997-f16aaa792d0c; ctoken=wla6p3EUOLyn1FSB8IKp1SEW; grey-id=5583e32b-39df-4bf0-f39f-1adf83f604a2; grey-id.sig=p8ReBIMG2BeZu1sYvsuOAZxYbx-MVrsfKEiCv87MsTM; isQuark=true; isQuark.sig=hUgqObykqFom5Y09bll94T1sS9abT1X-4Df_lzgl8nM; _UP_F7E_8D_=ZkyvVHnrBLp1A1NFJIjWi0PwKLOVbxJPcg0RzQPI6KmBtV6ZMgPh38l93pgubgHDQqhaZ2Sfc0qv%2BRantbfg1mWGAUpRMP4RqXP78Wvu%2FCfvkWWGc5NhCTV71tGOIGgDBR3%2Bu6%2Fjj44KlE5biSNDOWW7Bigcz27lvOTidzNw8s%2FWtKAIxWbnCzZn4%2FJMBUub1SIMcW89g57k4mfPmDlCgpZKzxwl6beSfdtZ4RUWXmZOn5v5NkxVKhU4wR0Pq7NklczEGdRq2nIAcu7v22Uw2o%2FxMY0xBdeC9Korm5%2FNHnxl6K%2Bd6FXSoT9a3XIMQO359auZPiZWzrNlZe%2BqnOahXcx7KAhQIRqSOapSmL4ygJor4r5isJhRuDoXy7vJAVuH%2FRDtEJJ8rZTq0BdC23Bz%2B0MrsdgbK%2BiW; _UP_D_=pc; __wpkreporterwid_=3d3f74a7-99b7-4916-3f78-911fc2eb9d87; tfstk=fIoZNxjnbhKwPOu0TWZ4LsaRqirTcudSSmNbnxD0C5VgClMm8xMyB-GsnSu4tjpOflAOmSD-9PNiGl120XrgkVNb1SrqHbJBN3tSBAEYoQOWVUUg9qZ8n1bGGkD3CqGYINKSBABhjnXgp3_Vywz6gSc0Syj3BWf0mr2DLW24eZfiiovEKWefj1q0swq3E82iNEMinMy7SLrcpA4Fh3z_ZAViCfih3PbtdW5N_DuU77AaTijmYRkL2Wq54ENoy5a7ZXxCbok33XzS7QSZgxD-oyoVsdGotql0p2dVu7umC4nLStbiLmParc4FELHrI-c0u2dPVRrs8zoZWKCnIbNZrlHfUCMUz2z8KyXVSlgSFmUojh58OzeqTzgwaGll4YCYKwctDV5coP2LL79eKHxpNTXHmre1kZU32JPWCR_AkP2LL79eLZQY-WeUNdw1.; __pus=2051c82285199d8be553be41dd5a2100AAQ+mmv35G4FDDZ5x+3Mhe2OMbNgweQ1ODbW8zDt9YuP1LQVqHUuAAz9KWLsPjpNtim0AVGHusN4MCosTmbq/khM; __kp=e6604120-6051-11ef-bfe4-c31b6cdd0766; __kps=AATcZArVgS76EPn0FMaV4HEj; __ktd=sii/iz4ePzEaoVirXul7QQ==; __uid=AATcZArVgS76EPn0FMaV4HEj; __itrace_wid=5829b95d-dac1-48d3-bfd5-f60cd9462786; __puus=7da0b96cb710fa1b376934485f977e05AATp/q8/QupT7IiBR1GWqZhxlIRT677smMvoHlLxQA0Lk6CkP0YJBOTl+p9DZgzlMz6w4hPXPgWsokukk8PW7ZfhFfPmv8tKMgLpCGLW+tk57luhNghmSdTeVPkAF59STtyCPBEtiNzNAd/zZJ6qILJDi5ywEBAAAg+gOyWHoLHNUR+QxeHRuQa8g5WWA95J8jebIlrr8rCvI1vjTbtiYktT\",\"token\":\"26fc6787afff43e78b78992e782502f1\"}");
|
||||
/* spider.init(mockContext,"{\n" +
|
||||
spider.init(mockContext,"{\n" +
|
||||
"\t\"username\":\"18896781601\" ,\"password\":\"Lushunming@0526\"\n" +
|
||||
"}"); */
|
||||
|
||||
spider.init(mockContext, "{\n" + " \"api_urls\": [\n" + " \"https://psweb.banye.tech:7777/api/search\",\n" + " \"https://so.566987.xyz/api/search\",\n" + " \"http://152.69.222.142:8088/api/search\"\n" + " ],\n" + " \"sources\": [\n" + " \"123盘\"\n" + " ]\n" + " }");
|
||||
"}"); // spider.init(mockContext, "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@org.junit.Test
|
||||
public void searchContent() throws Exception {
|
||||
String content = spider.searchContent("水饺皇后", false);
|
||||
|
|
@ -48,18 +51,7 @@ public class TgSearchTest {
|
|||
@org.junit.Test
|
||||
public void detailContent() throws Exception {
|
||||
|
||||
String content = spider.detailContent(Arrays.asList("https://123684.com/s/u9izjv-smUWv"));
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("detailContent--" + gson.toJson(map));
|
||||
Assert.assertFalse(map.getAsJsonArray("list").isEmpty());
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void playerContent() throws Exception {
|
||||
String content1 = spider.detailContent(Arrays.asList("https://123684.com/s/u9izjv-smUWv"));
|
||||
|
||||
String content = spider.playerContent("pan123原画", "eyJmaWxlbmFtZSI6IlRoZS5EdW1wbGluZy5RdWVlbi4yMDI1LjEwODBwLldFQi1ETC5IMjY0LkFBQy5tcDQiLCJzaGFyZUtleSI6InU5aXpqdi1zbVVXdiIsInNoYXJlUHdkIjoiIiwibmV4dCI6LTEsImZpbGVJZCI6MTg1NjgwODEsIlMzS2V5RmxhZyI6IjE4NDMwNTU4NTItMCIsIlNpemUiOjY0MDQyNTYzMTIsIkV0YWciOiIwYjNjZGIyOTYxZWM2NmQ5MjAyMTViOTRmZGY2MDZjNyJ9", new ArrayList<>());
|
||||
String content = spider.detailContent(Arrays.asList("/s/LEvn4lUGB6ufdQ"));
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("detailContent--" + gson.toJson(map));
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
package com.github.catvod.api;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import com.github.catvod.utils.Json;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class BaiDuYunHandlerTest {
|
||||
|
||||
private BaiDuYunHandler baiDuYunHandler;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
baiDuYunHandler = BaiDuYunHandler.get();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startScan() throws Exception {
|
||||
// Mock the OkHttp.get method to return a predefined OkResult
|
||||
// Execute the method under test
|
||||
FileUtil.writeBytes(baiDuYunHandler.startScan(), "c://qrcode.png");
|
||||
|
||||
while (true) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* @Test
|
||||
public void refreshCookie() throws Exception {
|
||||
|
||||
JsonObject obj = Json.safeObject("{\"open.e.189.cn\":{\"OPENINFO\":\"33c28688ef52ce9e3a9ef87388047efbde5e3e2e4c7ef6ef267632468c7dfaf294ff59fa59d34801\",\"pageOp\":\"f73420158c5c010491f1faa4fc91870e\",\"LT\":\"a8900fc0ecae0c59\",\"GUID\":\"b959026ffdf84080ae8567afd9ea4c32\",\"SSON\":\"dc466c8192e3109eaea837c1d136c1fd065253ce1c7d3a66ca1520d7d6d6307b10a1fe65c7becac73b95f24a6e681e654ec4f47c39533ebcc48bb78d6d6e63d1bbf3334e6e97eaa7092d34f87bf1209e256cd4822db68da051a0aeb532d94408c8e50486347fc713813dafc5776a7cfa665ddf96837151232745aa2957fb441d8a79ca7d86f46452060794e6f4b5873ab99ed476629aed2c7b36a44613c92f925dcfd221fce142cd1ecaab667236df697ece293e3ca24030918e5b357bc193118772278748606ade7262bf25ae7527d3c8a059bd48fc08b53b182e61e543a7e9bd1562b50bf80438\"},\"cloud.189.cn\":{\"JSESSIONID\":\"12088774C4B78E632EB944ECA2E6705F\",\"COOKIE_LOGIN_USER\":\"24DA4CBA27A8388982710C2F3D55EFAA84AEE67E9B3EF1B7AC1C565BEEF24C562052CB9B5EAC85E733C10C2704225133CD625407C352ED5D\"}}");
|
||||
baiDuYunHandler.setCookie(obj);
|
||||
baiDuYunHandler.refreshCookie();
|
||||
|
||||
while (true) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void download() throws Exception {
|
||||
// Mock the OkHttp.get method to return a predefined OkResult
|
||||
// Execute the method under test
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testgetUUID() throws Exception {
|
||||
JsonObject uuid = tianYiHandler.getUUID();
|
||||
System.out.println(uuid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testdownloadQRCode() throws Exception {
|
||||
*//*
|
||||
JsonObject uuidInfo = tianYiHandler.getUUID();
|
||||
String uuid = uuidInfo.get("uuid").getAsString();
|
||||
byte[] qrCode = tianYiHandler.downloadQRCode(uuid);
|
||||
FileUtil.writeBytes(qrCode, "c://qrcode.png");
|
||||
|
||||
System.out.println(uuid);*//*
|
||||
|
||||
String url = "https://cloud.189.cn/api/portal/callbackUnify.action?browserId=dff95dced0b03d9d972d920f03ddd05e&redirectURL=https%3A%2F%2Fcloud.189.cn%2Fweb%2Fredirect.html";
|
||||
|
||||
String encode = "https%3A%2F%2Fcloud.189.cn%2Fapi%2Fportal%2FcallbackUnify.action%3FbrowserId%3Ddff95dced0b03d9d972d920f03ddd05e%26redirectURL%3Dhttps%253A%252F%252Fcloud.189.cn%252Fweb%252Fredirect.html";
|
||||
assert URLEncoder.encode(url, "UTF-8").equals(encode);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void loginWithPassword() throws Exception {
|
||||
tianYiHandler.loginWithPassword("18896781601","Lushunming@0526");
|
||||
System.out.println("1111");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ class BaiduDriveTest {
|
|||
|
||||
runBlocking {
|
||||
val reslut =
|
||||
BaiduDrive.processShareLinks(listOf("https://pan.baidu.com/s/1So5RhSmNts0rWKEzjqinhQ?pwd=9527"))
|
||||
BaiduDrive.processShareLinks(listOf("https://pan.baidu.com/s/1Ov0S6S7rqnyW_S3AondhmQ?pwd=8888"))
|
||||
System.out.println(Json.toJson(reslut))
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ class BaiduDriveTest {
|
|||
System.out.println(reslut)
|
||||
}*/
|
||||
val jsonStr =
|
||||
com.github.catvod.utils.Util.base64Decode("eyJ1ayI6IjI0MDAxMjE2NzIiLCJzaGFyZWlkIjoiMjc2NTk2OTA4MTAiLCJmaWQiOjcxNzUwMDM4OTg1MjYzOSwicmFuZHNrIjoiNEdjMzFTejVsZHNpdHcwRW12ZDNzam9XYWFuVjFEQlFsUHk3VkdESHklMkI0JTNEIiwicG5hbWUiOiJUaGUuUmV0dXJuLm9mLnRoZS5MYW1lLkhlcm8uMjAyNS4yMTYwcC5XRUItREwuSDI2NS5IRFIuNjBmcHMuRERQNS4xLURyZWFtSEQubWt2IiwicXR5cGUiOiJvcmlnaW5hbCJ9")
|
||||
com.github.catvod.utils.Util.base64Decode("eyJ1ayI6IjExMDMyNzkxMjIzNDEiLCJzaGFyZWlkIjoiMjk1NzE4ODcyOTgiLCJmaWQiOjMxOTM5NTUxMTQyOTU4MCwicmFuZHNrIjoidkd4WXh4TVBRcXpucXZialRQeUQ2Q1FFT2VqemtJWmdFdXV2OUQ1Y3R6TSUzRCIsInBuYW1lIjoiRHJhZ29uIEJhbGwgREFJTUEuUzAxRTAxLjIwMjQuMTA4MHAuQ1IuV0VCLURMLngyNjQuQUFDLm1rdiIsInF0eXBlIjoib3JpZ2luYWwifQ==")
|
||||
val obj = Json.safeObject(jsonStr)
|
||||
runBlocking {
|
||||
val reslut = BaiduDrive.getVideoUrl(obj, "BD原画1")
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
package com.github.catvod.api
|
||||
|
||||
import com.github.catvod.utils.Util
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class Pan123Test {
|
||||
var pan123: Pan123Api? = null
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
pan123 = Pan123Api
|
||||
// pan123!!.login()
|
||||
}
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun login() {
|
||||
//pan123!!.login()
|
||||
"https://123684.com/s/u9izjv-smUWv".matches(Pan123Api.regex.toRegex())
|
||||
"https://www.123865.com/s/u9izjv-6hSWv".matches(Util.patternQuark.toRegex())
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun processShareData() {
|
||||
val result: Map<String, String> = pan123!!.getShareData("https://www.123865.com/s/u9izjv-6hSWv")
|
||||
println(result)
|
||||
|
||||
|
||||
val files= pan123!!.getFilesByShareUrl(result["key"]!!, result["sharePwd"]!!);
|
||||
println(files)
|
||||
|
||||
/* if (files != null) {
|
||||
for (file in files) {
|
||||
val playUrl = pan123!!.getDownload(result["key"]!!, file.fileId, file.S3KeyFlag, file.Size, file.Etag)
|
||||
println(playUrl)
|
||||
}
|
||||
}*/ if (files != null) {
|
||||
for (file in files) {
|
||||
val playUrl = pan123!!.getLiveTranscoding(result["key"]!!, file.fileId, file.S3KeyFlag, file.Size, file.Etag)
|
||||
println(playUrl)
|
||||
}
|
||||
}
|
||||
|
||||
/*for (String s : result.keySet()) {
|
||||
for (Map<String, String> stringStringMap : result.get(s)) {
|
||||
String playUrl = pan123.fetchPlayUrl(stringStringMap.get("contentId"), "");
|
||||
System.out.println(stringStringMap.get("name") + ":" + playUrl);
|
||||
}
|
||||
|
||||
|
||||
}*/
|
||||
} /* @Test
|
||||
public void download() throws Exception {
|
||||
|
||||
Map<String, List<Map<String, String>>> result = pan123.processShareData("https://caiyun.139.com/w/i/2nQQVZWCR24yf");
|
||||
System.out.println(result);
|
||||
for (String s : result.keySet()) {
|
||||
for (Map<String, String> stringStringMap : result.get(s)) {
|
||||
String playUrl = pan123.fetchPlayUrl(stringStringMap.get("contentId"), stringStringMap.get("linkID"));
|
||||
String url2 = pan123.get4kVideoInfo(stringStringMap.get("linkID"), stringStringMap.get("path"));
|
||||
System.out.println(stringStringMap.get("name") + ":" + playUrl);
|
||||
System.out.println(stringStringMap.get("url2") + ":" + url2);
|
||||
}
|
||||
}
|
||||
//;
|
||||
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
@ -21,9 +21,9 @@ public class TianyiApiTest {
|
|||
@Test
|
||||
public void getShareData() throws Exception {
|
||||
|
||||
// com.github.catvod.bean.tianyi.ShareData shareData = TianyiApi.get().getShareData("https://cloud.189.cn/web/share?code=ZvEjUvq6FNr2", "");
|
||||
com.github.catvod.bean.tianyi.ShareData shareData = TianyiApi.get().getShareData("https://cloud.189.cn/web/share?code=ZvEjUvq6FNr2", "");
|
||||
// TianyiApi.get().getVod(shareData);
|
||||
com.github.catvod.bean.tianyi.ShareData shareData1 = TianyiApi.get().getShareData("http://cloud.189.cn/t/3uIFJrzIFJV3(访问码:qf4b)", "");
|
||||
com.github.catvod.bean.tianyi.ShareData shareData1 = TianyiApi.get().getShareData("https://cloud.189.cn/web/share?code=2eyARfBzURZj(访问码:kz6y)", "");
|
||||
|
||||
// TianyiApi.get().getVod(shareData1);
|
||||
ShareData shareData2 = TianyiApi.get().getShareData("https://cloud.189.cn/t/ZvEjUvq6FNr2", "");
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public class ProxyVideoTest {
|
|||
// "https://js.shipin520.com/pc/images/new/banner20250225.mp4", new HashMap<>());
|
||||
"http://172.16.1.217:18089/ng-grid/video.mp4", new HashMap<>());
|
||||
System.out.println(url);*/
|
||||
System.out.println(ProxyServer.INSTANCE.buildProxyUrl("http://172.16.1.217:18089/ng-grid/video.mp4", Map.of("header","2","header2","2")));
|
||||
System.out.println(ProxyServer.INSTANCE.buildProxyUrl("https://media.w3.org/2010/05/sintel/trailer.mp4", Map.of("header","2","header2","2")));
|
||||
ProxyServer.INSTANCE.start();
|
||||
|
||||
while (true) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@echo off
|
||||
|
||||
call "%~dp0\gradlew" clean
|
||||
|
||||
call "%~dp0\gradlew" assembleRelease --no-daemon
|
||||
|
||||
|
|
|
|||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
5cca7cdb874fb79dee68e08a876fc8ec
|
||||
851711824c28c744517e650d914bf07d
|
||||
|
|
|
|||
156
json/index.json
156
json/index.json
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"spider": "http://gh.halonice.com/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/refs/heads/multiThread/jar/custom_spider.jar;md5;5cca7cdb874fb79dee68e08a876fc8ec",
|
||||
"spider": "https://andoridspidermt.netlify.app/jar/custom_spider.jar;md5;49c24003ea2a52abb468ad7661ae1730",
|
||||
"lives": [
|
||||
{
|
||||
"name": "电视直播",
|
||||
|
|
@ -66,15 +66,6 @@
|
|||
"changeable": 1,
|
||||
"ext": "{\"site\": [\"https://www.wogg.net/\",\"https://wogg.xxooo.cf/\"]}"
|
||||
},
|
||||
{
|
||||
"key": "SeedHub",
|
||||
"name": "SeedHub",
|
||||
"type": 3,
|
||||
"api": "csp_SeedHub",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "PanTa",
|
||||
"name": "盘他|139Pan",
|
||||
|
|
@ -103,68 +94,31 @@
|
|||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "Qupans",
|
||||
"name": "Qupans|Pan",
|
||||
"key": "TgSearch",
|
||||
"name": "TgSearch|Pan",
|
||||
"type": 3,
|
||||
"api": "csp_Qupans",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "Tg123Search",
|
||||
"name": "Tg123Search",
|
||||
"type": 3,
|
||||
"api": "csp_Tg123Search",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "TgbaiduSearch",
|
||||
"name": "TgbaiduSearch",
|
||||
"type": 3,
|
||||
"api": "csp_TgbaiduSearch",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "Tg189Search",
|
||||
"name": "Tg189Search",
|
||||
"type": 3,
|
||||
"api": "csp_Tg189Search",
|
||||
"api": "csp_TgSearch",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "TgQuarkSearch",
|
||||
"name": "TgQuarkSearch",
|
||||
"name": "TgQuarkSearch|Pan",
|
||||
"type": 3,
|
||||
"api": "csp_TgQuarkSearch",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},{
|
||||
"key": "TgSearchQuark",
|
||||
"name": "☁TgSearchQuark┃网盘",
|
||||
},
|
||||
{
|
||||
"key": "Tg189Search",
|
||||
"name": "Tg189Search|Pan",
|
||||
"type": 3,
|
||||
"api": "csp_TgSearchQuark",
|
||||
"api": "csp_Tg189Search",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": {
|
||||
"api_urls": [
|
||||
"https://api.jkai.de/api/search",
|
||||
"https://so.252035.xyz/api/search",
|
||||
"https://psweb.banye.tech:7777/api/search",
|
||||
"https://so.566987.xyz/api/search",
|
||||
"http://152.69.222.142:8088/api/search"
|
||||
],
|
||||
"sources": [
|
||||
"夸克"
|
||||
]
|
||||
}
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "TgSearchBaidu",
|
||||
|
|
@ -175,69 +129,12 @@
|
|||
"filterable": 0,
|
||||
"ext": {
|
||||
"api_urls": [
|
||||
"https://api.jkai.de/api/search","https://so.252035.xyz/api/search",
|
||||
"https://psweb.banye.tech:7777/api/search",
|
||||
"https://so.566987.xyz/api/search",
|
||||
"http://152.69.222.142:8088/api/search"
|
||||
],
|
||||
"sources": [
|
||||
"百度"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "TgSearch123",
|
||||
"name": "☁TgSearch123┃网盘",
|
||||
"type": 3,
|
||||
"api": "csp_TgSearch123",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": {
|
||||
"api_urls": [
|
||||
"https://api.jkai.de/api/search","https://so.252035.xyz/api/search",
|
||||
"https://psweb.banye.tech:7777/api/search",
|
||||
"https://so.566987.xyz/api/search",
|
||||
"http://152.69.222.142:8088/api/search"
|
||||
],
|
||||
"sources": [
|
||||
"123盘"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "TgSearch189",
|
||||
"name": "☁TgSearch189┃网盘",
|
||||
"type": 3,
|
||||
"api": "csp_TgSearch189",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": {
|
||||
"api_urls": [
|
||||
"https://api.jkai.de/api/search","https://so.252035.xyz/api/search",
|
||||
"https://psweb.banye.tech:7777/api/search",
|
||||
"https://so.566987.xyz/api/search",
|
||||
"http://152.69.222.142:8088/api/search"
|
||||
],
|
||||
"sources": [
|
||||
"天翼"
|
||||
]
|
||||
}
|
||||
},{
|
||||
"key": "TgSearch139",
|
||||
"name": "☁TgSearch139┃网盘",
|
||||
"type": 3,
|
||||
"api": "csp_TgSearch139",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": {
|
||||
"api_urls": [
|
||||
"https://api.jkai.de/api/search","https://so.252035.xyz/api/search",
|
||||
"https://psweb.banye.tech:7777/api/search",
|
||||
"https://so.566987.xyz/api/search",
|
||||
"http://152.69.222.142:8088/api/search"
|
||||
],
|
||||
"sources": [
|
||||
"移动"
|
||||
"百度"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
@ -457,34 +354,7 @@
|
|||
"api": "csp_TianYiSo",
|
||||
"searchable": 1,
|
||||
"timeout": 30
|
||||
},
|
||||
{
|
||||
"key": "local",
|
||||
"name": "Local",
|
||||
"type": 3,
|
||||
"api": "csp_Local",
|
||||
"searchable": 0,
|
||||
"changeable": 0
|
||||
},
|
||||
{
|
||||
"key": "market",
|
||||
"name": "Market",
|
||||
"type": 3,
|
||||
"api": "csp_Market",
|
||||
"searchable": 0,
|
||||
"changeable": 0,
|
||||
"ext": "./market.json"
|
||||
},
|
||||
{
|
||||
"key": "push_agent",
|
||||
"name": "Push",
|
||||
"type": 3,
|
||||
"api": "csp_Push",
|
||||
"searchable": 0,
|
||||
"changeable": 0,
|
||||
"timeout": 60
|
||||
}
|
||||
|
||||
],
|
||||
"parses": [
|
||||
{
|
||||
|
|
|
|||
622
json/test.json
622
json/test.json
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"spider": "https://gh.llkk.cc/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/123/jar/custom_spider.jar;md5;77ff0d77d6fccecddd174ee82161f3bd",
|
||||
"spider": "https://gh.llkk.cc/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/multiThreadNew/jar/custom_spider.jar;md5;8c76ee60eb0363060a2d78fb8dc2f0b6",
|
||||
"lives": [
|
||||
{
|
||||
"name": "电视直播",
|
||||
|
|
@ -41,26 +41,620 @@
|
|||
"type": 3,
|
||||
"api": "csp_Introduce"
|
||||
},
|
||||
{
|
||||
"key": "Douban",
|
||||
"name": " 豆瓣仅推荐",
|
||||
"type": 3,
|
||||
"api": "csp_Douban",
|
||||
"searchable": 0,
|
||||
"filterable": 1
|
||||
},
|
||||
{
|
||||
"key": "Jianpian",
|
||||
"name": "荐片视频",
|
||||
"type": 3,
|
||||
"api": "csp_Jianpian",
|
||||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
{
|
||||
"key": "玩偶",
|
||||
"name": "玩偶哥哥",
|
||||
"type": 3,
|
||||
"api": "csp_Wogg",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": "{\"site\": [\"https://www.wogg.net/\",\"https://wogg.xxooo.cf/\"]}"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "TgSearchBaidu",
|
||||
"name": "☁TgSearchBaidu┃网盘",
|
||||
"key": "PanTa",
|
||||
"name": "盘他|139Pan",
|
||||
"type": 3,
|
||||
"api": "csp_TgSearchBaidu",
|
||||
"api": "csp_PanTa",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "LeiJing",
|
||||
"name": "雷鲸|189Pan",
|
||||
"type": 3,
|
||||
"api": "csp_LeiJing",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "BiXin",
|
||||
"name": "彼心|139Pan",
|
||||
"type": 3,
|
||||
"api": "csp_BiXin",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
}, {
|
||||
"key": "TgSearch",
|
||||
"name": "TgSearch|Pan",
|
||||
"type": 3,
|
||||
"api": "csp_TgSearch",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "KuaKeBa",
|
||||
"name": "夸克吧",
|
||||
"type": 3,
|
||||
"api": "csp_KuaKeBa",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "DianYingYunJi",
|
||||
"name": "电影云集",
|
||||
"type": 3,
|
||||
"api": "csp_DianYingYunJi",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "KuaKeS",
|
||||
"name": "夸克网盘社",
|
||||
"type": 3,
|
||||
"api": "csp_KuaKeS",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
|
||||
{
|
||||
"key": "XuanFeng",
|
||||
"name": "旋风影视",
|
||||
"type": 3,
|
||||
"api": "csp_XuanFeng",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "NCat",
|
||||
"name": "网飞猫影视",
|
||||
"type": 3,
|
||||
"api": "csp_NCat",
|
||||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
{
|
||||
"key": "ChangZhang",
|
||||
"name": "厂长影视",
|
||||
"type": 3,
|
||||
"api": "csp_ChangZhang",
|
||||
"searchable": "1",
|
||||
"filterable": "0",
|
||||
"changeable": 0,
|
||||
"ext": "https://www.czzy.site/"
|
||||
},
|
||||
{
|
||||
"key": "Zxzj",
|
||||
"name": "在线之家",
|
||||
"type": 3,
|
||||
"api": "csp_Zxzj",
|
||||
"searchable": "1",
|
||||
"filterable": "0",
|
||||
"changeable": 0,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "TvDy",
|
||||
"name": "电影天堂影视",
|
||||
"type": 3,
|
||||
"api": "csp_TvDy",
|
||||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
{
|
||||
"key": "W55Movie",
|
||||
"name": "555电影",
|
||||
"type": 3,
|
||||
"api": "csp_W55Movie",
|
||||
"searchable": 0,
|
||||
"filterable": 1,
|
||||
"ext": "https://w55xy.com/"
|
||||
},
|
||||
{
|
||||
"key": "DaGongRen",
|
||||
"name": "打工人电影",
|
||||
"type": 3,
|
||||
"api": "csp_DaGongRen",
|
||||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
{
|
||||
"key": "HkTv",
|
||||
"name": "TVB云播影视",
|
||||
"type": 3,
|
||||
"api": "csp_HkTv",
|
||||
"searchable": 0,
|
||||
"filterable": 1,
|
||||
"ext": "http://www.hktvyb.vip/"
|
||||
},
|
||||
{
|
||||
"key": "NGkt",
|
||||
"name": "瓜瓜",
|
||||
"type": 3,
|
||||
"api": "csp_NG",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "JustLive",
|
||||
"name": "JustLive直播",
|
||||
"type": 3,
|
||||
"api": "csp_JustLive",
|
||||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
{
|
||||
"key": "Xb6v",
|
||||
"name": "新版6V视频",
|
||||
"type": 3,
|
||||
"api": "csp_Xb6v",
|
||||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
{
|
||||
"key": "ikanbot",
|
||||
"name": "爱看机器人",
|
||||
"type": 3,
|
||||
"api": "csp_Ikanbot",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": "{\"box\": \"TVBox\", \"danmu\": false}"
|
||||
},
|
||||
{
|
||||
"key": "Libvio",
|
||||
"name": "立播影视",
|
||||
"type": 3,
|
||||
"api": "csp_Libvio",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": "{ \"site\": \"https://www.libvio.app\" }"
|
||||
},
|
||||
{
|
||||
"key": "Ddrk",
|
||||
"name": "低端影视",
|
||||
"type": 3,
|
||||
"api": "csp_Ddrk",
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": " {\"site\":\"https://ddys.info/\"}"
|
||||
},
|
||||
{
|
||||
"key": "Ysj",
|
||||
"name": "异世界动漫(不稳定)",
|
||||
"type": 3,
|
||||
"api": "csp_Ysj",
|
||||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
{
|
||||
"key": "QxiTv",
|
||||
"name": "七喜影视",
|
||||
"type": 3,
|
||||
"api": "csp_QxiTv",
|
||||
"searchable": 1,
|
||||
"changeable": 0,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "glod",
|
||||
"name": "金牌 | 影视",
|
||||
"type": 3,
|
||||
"api": "csp_Glod",
|
||||
"searchable": 1,
|
||||
"changeable": 0,
|
||||
"ext": {}
|
||||
},
|
||||
{
|
||||
"key": "YunPanBa",
|
||||
"name": "云盘吧",
|
||||
"type": 3,
|
||||
"api": "csp_YunPanBa",
|
||||
"searchable": 1,
|
||||
"timeout": 30
|
||||
},
|
||||
{
|
||||
"key": "QiLeSo",
|
||||
"name": "奇乐搜┃搜索",
|
||||
"type": 3,
|
||||
"api": "csp_QiLeSo",
|
||||
"searchable": 1,
|
||||
"timeout": 30
|
||||
},
|
||||
{
|
||||
"key": "PanSearch",
|
||||
"name": "盘搜┃搜索",
|
||||
"type": 3,
|
||||
"api": "csp_PanSearch",
|
||||
"searchable": 1,
|
||||
"timeout": 30
|
||||
},
|
||||
{
|
||||
"key": "TianYiSo",
|
||||
"name": "天翼┃搜索",
|
||||
"type": 3,
|
||||
"api": "csp_TianYiSo",
|
||||
"searchable": 1,
|
||||
"timeout": 30
|
||||
},
|
||||
{
|
||||
"key": "newvision",
|
||||
"name": "(js)新视觉影院(不稳定)",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/newvision.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"api_urls": [
|
||||
"https://psweb.banye.tech:7777/api/search",
|
||||
"https://so.566987.xyz/api/search",
|
||||
"http://152.69.222.142:8088/api/search"
|
||||
],
|
||||
"sources": [
|
||||
"123盘"
|
||||
]
|
||||
}
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "kankan70",
|
||||
"name": "(js)70看看┃📺",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/kankan70.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "jpyy",
|
||||
"name": "(js)金牌影院",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/jpyy.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "jpyy2",
|
||||
"name": "(js)金牌影院",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/jpyy2.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "tiantian",
|
||||
"name": "(js)天天影视┃⛄",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/tiantian.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "xb6v",
|
||||
"name": "(js)磁力新6V┃🧲",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/xb6v.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "mp4movie",
|
||||
"name": "(js)Mp4电影┃🍚",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/mp4movie.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "jianpian",
|
||||
"name": "(js)荐片┃🌼",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/jianpian.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "alipansou",
|
||||
"name": "(js)阿里猫狸┃😸",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/alipansou.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox",
|
||||
"aliToken": "26fc6787afff43e78b78992e782502f1",
|
||||
"quarkCookie": "_UP_A4A_11_=wb965111521e45ffa80410c24a071a54; _UP_D_=pc; tfstk=fXFith4nnRk114LAjWc1TT-OQUXL5hGjqodxDjnVLDoBBchYujR4Drht3GaYxmqYlcPtWc34mknIMcFTB-Y_tuAv6G6_uIcxggIRw_U15jGV2EjCXmnslyoqlSMN9PGjgMEW0dR85uVOAjYmgwcEoqOqgIrqLyoIlq-ZuC738DgqgCJZgH8EuqxZNmAqqSPQTaC3h7bb2rFnSvW87D8jTW0iX0zasIR2zVDi4Poh2svabvzjnSTXixaaFogzbhS-Cry3xVcc9dlz--roR55Jj2wT8znUrEdYrfV3t-kh71znscDo-vYWpf24fSD_IE_78frQF0MNdMg367HmVvxFbyUnbY20XMOqX84UxYFpvQhbA-rqok-G4A9eUc4wG27YtK9jQ2gnVNJioG_mbu_h-wv5CAuIWgQh-K9jQ2gn2wbHFhMZRVIR.; __pus=c81f57897dafcb65d4ecb501bc299199AARcqF72zsatdbsCbiT3qVqsk36caaycoPQW7hz8rbEf+UY7f5aGgH1e90lsONAUwCAW8y27u5A/KXyYqkHCWgjS; __kp=99fa2760-1669-11ef-90cf-8f7a59c3b86e; __kps=AATSt4xuf6r6bqes3LdJvxvy; __ktd=c2e+aLICIvFoeklXXz36VA==; __uid=AATSt4xuf6r6bqes3LdJvxvy; Video-Auth=smob3MOUslklDq2MutANJYZCVo50sLv0GFelx3+cu1nK2fkdL2kvkdpT5yNOhNz0NLTyi5ThWRL47+ztJA4kXQ==; __puus=72f667c533c9a22496f88d2f1bb7ae71AAQ7mrvFw7s9AUPUXvnuGPkcDU3RRTVPdYaYQfsM9Cje2doYXgRZXbImg02EaUaEG+G9ikpo3xubGGdElArOuYvUtJzIXb6yHDnSZbtEUxkwvjfQRNEnDnVwLQ6LL2ORjRaxa9OUfwk/WppWvy6OcDqQtHYkaqB+Poxn5kFs7ZVdAtX7ZQks1czD+g9gAZjsbeBHxHQ1AP5MGc1s3M4RhwZQ"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "huya",
|
||||
"name": "(js)虎牙直播┃🐯",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/huya.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "star",
|
||||
"name": "(js)星视界┃墙☄️",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/star.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "nivod",
|
||||
"name": "(js)泥视频┃墙👑",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/nivod.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox",
|
||||
"code": 0
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "aiyingshi",
|
||||
"name": "(js)爱影视┃🚀",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/aiyingshi.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "sp360",
|
||||
"name": "(js)360影视┃🥎",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/sp360.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "mxanime",
|
||||
"name": "(js)MX动漫┃🍒",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/mxanime.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "cntv",
|
||||
"name": "(js)中央影视┃🤵♂️",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/cntv.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "douban",
|
||||
"name": "(js)豆瓣┃🍥",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/douban.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "pan_search",
|
||||
"name": "(js)阿里盘搜┃🗂️",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/pan_search.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox",
|
||||
"aliToken": "26fc6787afff43e78b78992e782502f1",
|
||||
"quarkCookie": "_UP_A4A_11_=wb965111521e45ffa80410c24a071a54; _UP_D_=pc; tfstk=fXFith4nnRk114LAjWc1TT-OQUXL5hGjqodxDjnVLDoBBchYujR4Drht3GaYxmqYlcPtWc34mknIMcFTB-Y_tuAv6G6_uIcxggIRw_U15jGV2EjCXmnslyoqlSMN9PGjgMEW0dR85uVOAjYmgwcEoqOqgIrqLyoIlq-ZuC738DgqgCJZgH8EuqxZNmAqqSPQTaC3h7bb2rFnSvW87D8jTW0iX0zasIR2zVDi4Poh2svabvzjnSTXixaaFogzbhS-Cry3xVcc9dlz--roR55Jj2wT8znUrEdYrfV3t-kh71znscDo-vYWpf24fSD_IE_78frQF0MNdMg367HmVvxFbyUnbY20XMOqX84UxYFpvQhbA-rqok-G4A9eUc4wG27YtK9jQ2gnVNJioG_mbu_h-wv5CAuIWgQh-K9jQ2gn2wbHFhMZRVIR.; __pus=c81f57897dafcb65d4ecb501bc299199AARcqF72zsatdbsCbiT3qVqsk36caaycoPQW7hz8rbEf+UY7f5aGgH1e90lsONAUwCAW8y27u5A/KXyYqkHCWgjS; __kp=99fa2760-1669-11ef-90cf-8f7a59c3b86e; __kps=AATSt4xuf6r6bqes3LdJvxvy; __ktd=c2e+aLICIvFoeklXXz36VA==; __uid=AATSt4xuf6r6bqes3LdJvxvy; Video-Auth=smob3MOUslklDq2MutANJYZCVo50sLv0GFelx3+cu1nK2fkdL2kvkdpT5yNOhNz0NLTyi5ThWRL47+ztJA4kXQ==; __puus=72f667c533c9a22496f88d2f1bb7ae71AAQ7mrvFw7s9AUPUXvnuGPkcDU3RRTVPdYaYQfsM9Cje2doYXgRZXbImg02EaUaEG+G9ikpo3xubGGdElArOuYvUtJzIXb6yHDnSZbtEUxkwvjfQRNEnDnVwLQ6LL2ORjRaxa9OUfwk/WppWvy6OcDqQtHYkaqB+Poxn5kFs7ZVdAtX7ZQks1czD+g9gAZjsbeBHxHQ1AP5MGc1s3M4RhwZQ"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "bilibili",
|
||||
"name": "(js)哔哩哔哩┃🏰",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/bilibili.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox",
|
||||
"cookie": "buvid3=02675249-8ED3-C418-87F5-59E18316459714816infoc; b_nut=1704421014; _uuid=5D435F74-F574-D9AB-62C1-B9294DE465D913102infoc; buvid_fp=e8c5650c749398e9b5cad3f3ddb5081e; buvid4=007E85D1-52C1-7E6E-07CF-837FFBC9349516677-024010502-J5vTDSZDCw4fNnXRejbSVg%3D%3D; rpdid=|()kYJmulRu0J'u~|RRJl)JR; PVID=1; SESSDATA=3be091d3%2C1720332009%2C699ed%2A11CjAcCdwXG5kY1umhCOpQHOn_WP7L9xFBfWO7KKd4BPweodpR6VyIfeNyPiRmkr5jCqsSVjg0R0dZOVVHRUo3RnhPRTZFc3JPbGdiUjFCdHpiRDhiTkticmdKTjVyS1VhbDdvNjFMSDJlbUJydUlRdjFUNGFBNkJlV2ZTa0N1Q1BEVi1QYTQzTUh3IIEC; bili_jct=b0ee7b5d3f27df893545d811d95506d4; DedeUserID=78014638; DedeUserID__ckMd5=4c8c5d65065e468a; enable_web_push=DISABLE; header_theme_version=CLOSE; home_feed_column=5; CURRENT_BLACKGAP=0; CURRENT_FNVAL=4048; b_lsid=75E916AA_18EA1A8D995; bsource=search_baidu; FEED_LIVE_VERSION=V_HEADER_LIVE_NO_POP; browser_resolution=1507-691; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTIzNjk5MTMsImlhdCI6MTcxMjExMDY1MywicGx0IjotMX0.8zQW_fNTCSBlK_JkHnzu3gDw62wuTK1qgKcbGec3swM; bili_ticket_expires=171236985"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "changzhang",
|
||||
"name": "(js)厂长直连┃🏭️",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/changzhang.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox",
|
||||
"aliToken": "26fc6787afff43e78b78992e782502f1",
|
||||
"quarkCookie": "_UP_A4A_11_=wb965111521e45ffa80410c24a071a54; _UP_D_=pc; tfstk=fXFith4nnRk114LAjWc1TT-OQUXL5hGjqodxDjnVLDoBBchYujR4Drht3GaYxmqYlcPtWc34mknIMcFTB-Y_tuAv6G6_uIcxggIRw_U15jGV2EjCXmnslyoqlSMN9PGjgMEW0dR85uVOAjYmgwcEoqOqgIrqLyoIlq-ZuC738DgqgCJZgH8EuqxZNmAqqSPQTaC3h7bb2rFnSvW87D8jTW0iX0zasIR2zVDi4Poh2svabvzjnSTXixaaFogzbhS-Cry3xVcc9dlz--roR55Jj2wT8znUrEdYrfV3t-kh71znscDo-vYWpf24fSD_IE_78frQF0MNdMg367HmVvxFbyUnbY20XMOqX84UxYFpvQhbA-rqok-G4A9eUc4wG27YtK9jQ2gnVNJioG_mbu_h-wv5CAuIWgQh-K9jQ2gn2wbHFhMZRVIR.; __pus=c81f57897dafcb65d4ecb501bc299199AARcqF72zsatdbsCbiT3qVqsk36caaycoPQW7hz8rbEf+UY7f5aGgH1e90lsONAUwCAW8y27u5A/KXyYqkHCWgjS; __kp=99fa2760-1669-11ef-90cf-8f7a59c3b86e; __kps=AATSt4xuf6r6bqes3LdJvxvy; __ktd=c2e+aLICIvFoeklXXz36VA==; __uid=AATSt4xuf6r6bqes3LdJvxvy; Video-Auth=smob3MOUslklDq2MutANJYZCVo50sLv0GFelx3+cu1nK2fkdL2kvkdpT5yNOhNz0NLTyi5ThWRL47+ztJA4kXQ==; __puus=72f667c533c9a22496f88d2f1bb7ae71AAQ7mrvFw7s9AUPUXvnuGPkcDU3RRTVPdYaYQfsM9Cje2doYXgRZXbImg02EaUaEG+G9ikpo3xubGGdElArOuYvUtJzIXb6yHDnSZbtEUxkwvjfQRNEnDnVwLQ6LL2ORjRaxa9OUfwk/WppWvy6OcDqQtHYkaqB+Poxn5kFs7ZVdAtX7ZQks1czD+g9gAZjsbeBHxHQ1AP5MGc1s3M4RhwZQ"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "wogg",
|
||||
"name": "(js)阿里玩偶┃💂",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/wogg.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox",
|
||||
"aliToken": "26fc6787afff43e78b78992e782502f1",
|
||||
"quarkCookie": "_UP_A4A_11_=wb965111521e45ffa80410c24a071a54; _UP_D_=pc; tfstk=fXFith4nnRk114LAjWc1TT-OQUXL5hGjqodxDjnVLDoBBchYujR4Drht3GaYxmqYlcPtWc34mknIMcFTB-Y_tuAv6G6_uIcxggIRw_U15jGV2EjCXmnslyoqlSMN9PGjgMEW0dR85uVOAjYmgwcEoqOqgIrqLyoIlq-ZuC738DgqgCJZgH8EuqxZNmAqqSPQTaC3h7bb2rFnSvW87D8jTW0iX0zasIR2zVDi4Poh2svabvzjnSTXixaaFogzbhS-Cry3xVcc9dlz--roR55Jj2wT8znUrEdYrfV3t-kh71znscDo-vYWpf24fSD_IE_78frQF0MNdMg367HmVvxFbyUnbY20XMOqX84UxYFpvQhbA-rqok-G4A9eUc4wG27YtK9jQ2gnVNJioG_mbu_h-wv5CAuIWgQh-K9jQ2gn2wbHFhMZRVIR.; __pus=c81f57897dafcb65d4ecb501bc299199AARcqF72zsatdbsCbiT3qVqsk36caaycoPQW7hz8rbEf+UY7f5aGgH1e90lsONAUwCAW8y27u5A/KXyYqkHCWgjS; __kp=99fa2760-1669-11ef-90cf-8f7a59c3b86e; __kps=AATSt4xuf6r6bqes3LdJvxvy; __ktd=c2e+aLICIvFoeklXXz36VA==; __uid=AATSt4xuf6r6bqes3LdJvxvy; Video-Auth=smob3MOUslklDq2MutANJYZCVo50sLv0GFelx3+cu1nK2fkdL2kvkdpT5yNOhNz0NLTyi5ThWRL47+ztJA4kXQ==; __puus=72f667c533c9a22496f88d2f1bb7ae71AAQ7mrvFw7s9AUPUXvnuGPkcDU3RRTVPdYaYQfsM9Cje2doYXgRZXbImg02EaUaEG+G9ikpo3xubGGdElArOuYvUtJzIXb6yHDnSZbtEUxkwvjfQRNEnDnVwLQ6LL2ORjRaxa9OUfwk/WppWvy6OcDqQtHYkaqB+Poxn5kFs7ZVdAtX7ZQks1czD+g9gAZjsbeBHxHQ1AP5MGc1s3M4RhwZQ"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "nangua",
|
||||
"name": "(js)南瓜影视┃🎃",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/nangua.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "aliyunpanshare",
|
||||
"name": "(js)阿里云盘分享┃🥏",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/aliyunpanshare.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox",
|
||||
"aliToken": "26fc6787afff43e78b78992e782502f1",
|
||||
"quarkCookie": "_UP_A4A_11_=wb965111521e45ffa80410c24a071a54; _UP_D_=pc; tfstk=fXFith4nnRk114LAjWc1TT-OQUXL5hGjqodxDjnVLDoBBchYujR4Drht3GaYxmqYlcPtWc34mknIMcFTB-Y_tuAv6G6_uIcxggIRw_U15jGV2EjCXmnslyoqlSMN9PGjgMEW0dR85uVOAjYmgwcEoqOqgIrqLyoIlq-ZuC738DgqgCJZgH8EuqxZNmAqqSPQTaC3h7bb2rFnSvW87D8jTW0iX0zasIR2zVDi4Poh2svabvzjnSTXixaaFogzbhS-Cry3xVcc9dlz--roR55Jj2wT8znUrEdYrfV3t-kh71znscDo-vYWpf24fSD_IE_78frQF0MNdMg367HmVvxFbyUnbY20XMOqX84UxYFpvQhbA-rqok-G4A9eUc4wG27YtK9jQ2gnVNJioG_mbu_h-wv5CAuIWgQh-K9jQ2gn2wbHFhMZRVIR.; __pus=c81f57897dafcb65d4ecb501bc299199AARcqF72zsatdbsCbiT3qVqsk36caaycoPQW7hz8rbEf+UY7f5aGgH1e90lsONAUwCAW8y27u5A/KXyYqkHCWgjS; __kp=99fa2760-1669-11ef-90cf-8f7a59c3b86e; __kps=AATSt4xuf6r6bqes3LdJvxvy; __ktd=c2e+aLICIvFoeklXXz36VA==; __uid=AATSt4xuf6r6bqes3LdJvxvy; Video-Auth=smob3MOUslklDq2MutANJYZCVo50sLv0GFelx3+cu1nK2fkdL2kvkdpT5yNOhNz0NLTyi5ThWRL47+ztJA4kXQ==; __puus=72f667c533c9a22496f88d2f1bb7ae71AAQ7mrvFw7s9AUPUXvnuGPkcDU3RRTVPdYaYQfsM9Cje2doYXgRZXbImg02EaUaEG+G9ikpo3xubGGdElArOuYvUtJzIXb6yHDnSZbtEUxkwvjfQRNEnDnVwLQ6LL2ORjRaxa9OUfwk/WppWvy6OcDqQtHYkaqB+Poxn5kFs7ZVdAtX7ZQks1czD+g9gAZjsbeBHxHQ1AP5MGc1s3M4RhwZQ"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "dubo",
|
||||
"name": "(js)独播影视┃🛶",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/dubo.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "haiwaikan",
|
||||
"name": "(js)海外看┃☕墙",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/haiwaikan.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "dygangs",
|
||||
"name": "(js)电影港┃🏖️",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/dygangs.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "cilixiong",
|
||||
"name": "(js)磁力熊┃🐻",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/cilixiong.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "lovemovie",
|
||||
"name": "(js)爱情电影网┃💕",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/lovemovie.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "gitcafe",
|
||||
"name": "(js)阿里纸条┃🦊",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/gitcafe.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox",
|
||||
"aliToken": "26fc6787afff43e78b78992e782502f1",
|
||||
"quarkCookie": "_UP_A4A_11_=wb965111521e45ffa80410c24a071a54; _UP_D_=pc; tfstk=fXFith4nnRk114LAjWc1TT-OQUXL5hGjqodxDjnVLDoBBchYujR4Drht3GaYxmqYlcPtWc34mknIMcFTB-Y_tuAv6G6_uIcxggIRw_U15jGV2EjCXmnslyoqlSMN9PGjgMEW0dR85uVOAjYmgwcEoqOqgIrqLyoIlq-ZuC738DgqgCJZgH8EuqxZNmAqqSPQTaC3h7bb2rFnSvW87D8jTW0iX0zasIR2zVDi4Poh2svabvzjnSTXixaaFogzbhS-Cry3xVcc9dlz--roR55Jj2wT8znUrEdYrfV3t-kh71znscDo-vYWpf24fSD_IE_78frQF0MNdMg367HmVvxFbyUnbY20XMOqX84UxYFpvQhbA-rqok-G4A9eUc4wG27YtK9jQ2gnVNJioG_mbu_h-wv5CAuIWgQh-K9jQ2gn2wbHFhMZRVIR.; __pus=c81f57897dafcb65d4ecb501bc299199AARcqF72zsatdbsCbiT3qVqsk36caaycoPQW7hz8rbEf+UY7f5aGgH1e90lsONAUwCAW8y27u5A/KXyYqkHCWgjS; __kp=99fa2760-1669-11ef-90cf-8f7a59c3b86e; __kps=AATSt4xuf6r6bqes3LdJvxvy; __ktd=c2e+aLICIvFoeklXXz36VA==; __uid=AATSt4xuf6r6bqes3LdJvxvy; Video-Auth=smob3MOUslklDq2MutANJYZCVo50sLv0GFelx3+cu1nK2fkdL2kvkdpT5yNOhNz0NLTyi5ThWRL47+ztJA4kXQ==; __puus=72f667c533c9a22496f88d2f1bb7ae71AAQ7mrvFw7s9AUPUXvnuGPkcDU3RRTVPdYaYQfsM9Cje2doYXgRZXbImg02EaUaEG+G9ikpo3xubGGdElArOuYvUtJzIXb6yHDnSZbtEUxkwvjfQRNEnDnVwLQ6LL2ORjRaxa9OUfwk/WppWvy6OcDqQtHYkaqB+Poxn5kFs7ZVdAtX7ZQks1czD+g9gAZjsbeBHxHQ1AP5MGc1s3M4RhwZQ"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"key": "kuaikan",
|
||||
"name": "(js)快看视频┃🛥︎",
|
||||
"api": "https://androidcatvodspider.netlify.app/json/js/kuaikan.js",
|
||||
"timeout": 30,
|
||||
"ext": {
|
||||
"box": "TVBox"
|
||||
},
|
||||
"playerType": 0,
|
||||
"type": 3
|
||||
}
|
||||
|
||||
],
|
||||
"parses": [
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue