123盘基本完成

This commit is contained in:
lushunming 2025-10-21 10:44:20 +08:00
parent fc1403c4a8
commit 0fd1d6df7c
17 changed files with 976 additions and 63 deletions

View File

@ -0,0 +1,394 @@
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 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): String? {
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("登录成功")
return token
}
}
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 = pwdMatcher.value
}
}
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()}"
)
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();
}
}

View File

@ -0,0 +1,140 @@
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 = ""
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
if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(passwd)) {
if (StringUtils.isBlank(auth)) {
SpiderDebug.log("userName passwd 不为空,auth 为空")
this.loginWithPassword(userName, passwd)
}
} else {
SpiderDebug.log("userName passwd 为空")
startFlow()
}
}
}
fun loginWithPassword(uname: String?, passwd: String?) {
SpiderDebug.log("loginWithPassword uname: $unamepasswd$passwd")
try {
//保存的账号密码
val auth = login(uname!!, passwd!!)
if (StringUtils.isNotBlank(auth)) {
val user = User()
user.cookie = auth
user.password = passwd
user.userName = uname
this.auth = auth ?: ""
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) {
}
}
}

View File

@ -0,0 +1,46 @@
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);
}
}

View File

@ -0,0 +1,12 @@
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
)

View File

@ -0,0 +1,53 @@
package com.github.catvod.bean.pan123;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class User {
@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 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 = "";
}
}

View File

@ -2,8 +2,10 @@ 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;
@ -19,11 +21,12 @@ import static com.github.catvod.api.TianyiApi.URL_START;
*/
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;
@Override
public void init(Context context, String extend) throws Exception {
@ -34,6 +37,7 @@ public class Cloud extends Spider {
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() : "");
@ -41,43 +45,52 @@ public class Cloud extends Spider {
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)) {
return uc.detailContent(shareUrl);
} */else if (shareUrl.get(0).startsWith(TianyiApi.URL_START)) {
} */ 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")) {
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;
}
@ -89,17 +102,19 @@ public class Cloud extends Spider {
i++;
/*if (shareLink.matches(Util.patternUC)) {
from.add(uc.detailContentVodPlayFrom(List.of(shareLink), i));
} else*/ if (shareLink.matches(Util.patternQuark)) {
} 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)) {
} */ 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)) {
} else if (shareLink.contains(BaiDuPan.URL_START)) {
from.add(baiDuPan.detailContentVodPlayFrom(List.of(shareLink), i));
} else if (shareLink.matches(Pan123Api.regex)) {
from.add(pan123.detailContentVodPlayFrom(List.of(shareLink), i));
}
}
@ -111,16 +126,19 @@ public class Cloud extends Spider {
for (String shareLink : shareLinks) {
/* if (shareLink.matches(Util.patternUC)) {
urls.add(uc.detailContentVodPlayUrl(List.of(shareLink)));
} else */if (shareLink.matches(Util.patternQuark)) {
} 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.startsWith(URL_START)) {
} */ 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)) {
} else if (shareLink.contains(BaiDuPan.URL_START)) {
urls.add(baiDuPan.detailContentVodPlayUrl(List.of(shareLink)));
} else if (shareLink.matches(Pan123Api.regex)) {
urls.add(pan123.detailContentVodPlayUrl(List.of(shareLink)));
}
}
return TextUtils.join("$$$", urls);

View File

@ -0,0 +1,89 @@
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) throws Exception {
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());
}
}
return TextUtils.join("$$$", playUrl);
}
}

View File

@ -8,6 +8,7 @@ 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;
@ -19,31 +20,54 @@ import java.util.List;
public class Push extends Spider {
private final Ali ali;
private Cloud cloud;
public Push() {
ali = new Ali();
cloud = new Cloud();
}
@Override
public void init(Context context, String extend) {
ali.init(context, extend);
try {
cloud.init(context, extend);
} catch (Exception e) {
SpiderDebug.log("Cloud init error: " + e.getMessage());
}
}
@Override
public String detailContent(List<String> ids) throws Exception {
if (Ali.pattern.matcher(ids.get(0)).find()) return ali.detailContent(ids);
return Result.string(vod(ids.get(0)));
String url = ids.get(0);
// 使用Cloud类处理各种云盘链接
String cloudResult = cloud.detailContent(ids);
if (cloudResult != null) {
return cloudResult;
}
// 如果不是云盘链接返回普通链接处理结果
return Result.string(vod(url));
}
@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 ali.playerContent(flag, id, vipFlags);
return Result.get().url(id).string();
}
private Vod vod(String url) {

View File

@ -4,28 +4,22 @@ 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.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.*
import okhttp3.Response
import org.apache.commons.lang3.StringUtils
import java.io.InputStream
import java.io.SequenceInputStream
import java.util.Vector
import java.util.*
import kotlin.math.min
object DownloadMT {
private val THREAD_NUM: Int = Runtime.getRuntime().availableProcessors() * 2
private val THREAD_NUM: Int = 16
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块
@ -52,11 +46,10 @@ 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
@ -78,8 +71,7 @@ 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(
@ -128,8 +120,7 @@ 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(
@ -156,12 +147,10 @@ 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()

View File

@ -11,7 +11,7 @@ import kotlinx.coroutines.runBlocking
object ProxyServer {
private val THREAD_NUM = Runtime.getRuntime().availableProcessors()
private const val THREAD_NUM = 16
private val partSize = 1024 * 1024 * 2
private var port = 12345
private var httpServer: AdvancedHttpServer? = null

View File

@ -0,0 +1,65 @@
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){
}
}
}

View File

@ -1,11 +1,7 @@
import android.app.Application;
import com.github.catvod.server.Server;
import com.github.catvod.spider.Init;
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.spider.TgSearchBaidu;
import com.github.catvod.utils.Json;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@ -15,6 +11,7 @@ import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.Arrays;
@RunWith(RobolectricTestRunner.class)
@ -22,23 +19,23 @@ public class TgSearchTest {
private Application mockContext;
private TgQuarkSearch spider;
private TgSearchBaidu spider;
@org.junit.Before
public void setUp() throws Exception {
mockContext = RuntimeEnvironment.application;
Init.init(mockContext);
spider = new TgQuarkSearch();
spider = new TgSearchBaidu();
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, "");
"}"); */
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" + " }");
}
@org.junit.Test
public void searchContent() throws Exception {
String content = spider.searchContent("水饺皇后", false);
@ -51,7 +48,18 @@ public class TgSearchTest {
@org.junit.Test
public void detailContent() throws Exception {
String content = spider.detailContent(Arrays.asList("/s/LEvn4lUGB6ufdQ"));
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<>());
JsonObject map = Json.safeObject(content);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println("detailContent--" + gson.toJson(map));

View File

@ -0,0 +1,75 @@
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);
}
}
//;
}
*/
}

View File

@ -1,5 +1,5 @@
@echo off
call "%~dp0\gradlew" clean
call "%~dp0\gradlew" assembleRelease --no-daemon

Binary file not shown.

View File

@ -1 +1 @@
8a1cc4b31a331b1937bf6a449e94e4de
77ff0d77d6fccecddd174ee82161f3bd

View File

@ -1,5 +1,5 @@
{
"spider": "https://gh.llkk.cc/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/123/jar/custom_spider.jar;md5;8a1cc4b31a331b1937bf6a449e94e4de",
"spider": "https://gh.llkk.cc/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/123/jar/custom_spider.jar;md5;77ff0d77d6fccecddd174ee82161f3bd",
"lives": [
{
"name": "电视直播",