libvio 暂无夸克
This commit is contained in:
parent
d218a71471
commit
a4bc07a717
|
|
@ -0,0 +1,326 @@
|
|||
package com.github.catvod.api;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class QuarkApi {
|
||||
/* constructor() {
|
||||
this.apiUrl = "https://drive-pc.quark.cn/1/clouddrive/"
|
||||
this.cookie = ""
|
||||
this.ckey = ""
|
||||
this.shareTokenCache = {}
|
||||
this.pr = "pr=ucpro&fr=pc"
|
||||
this.subtitleExts = ['.srt', '.ass', '.scc', '.stl', '.ttml'];
|
||||
this.saveFileIdCaches = {}
|
||||
this.saveDirId = null
|
||||
this.saveDirName = 'TV';
|
||||
|
||||
}
|
||||
|
||||
async initQuark(cookie) {
|
||||
this.ckey = Crypto.enc.Hex.stringify(Crypto.MD5(cookie)).toString();
|
||||
let localCfg = await local.get("quark", "cookie");
|
||||
if (!_.isEmpty(localCfg)) {
|
||||
this.cookie = JSON.parse(localCfg)[this.ckey]
|
||||
} else {
|
||||
this.cookie = cookie
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getHeaders() {
|
||||
return Map.of(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch",
|
||||
"Referer", "https://pan.quark.cn/",
|
||||
"Content-Type", "application/json",
|
||||
"Cookie", this.cookie,
|
||||
"Host", "drive-pc.quark.cn"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
async api(url, data, retry, method) {
|
||||
const leftRetry = retry || 3;
|
||||
let resp = await req(this.apiUrl + url, {
|
||||
method:method || "post",
|
||||
data:data,
|
||||
headers:this.getHeaders()
|
||||
})
|
||||
if (resp.headers['set-cookie']) {
|
||||
const puus = [resp.headers['set-cookie']].join(';;;').match( / __puus = ([ ^;]+)/);
|
||||
if (puus) {
|
||||
if ( this.cookie.match( / __puus = ([ ^;]+)/)[1] !=puus[1]){
|
||||
this.cookie = this.cookie.replace( / __puus =[^;]+ /, `__puus = $ {
|
||||
puus[1]
|
||||
}`);
|
||||
let cookieDic = {}
|
||||
cookieDic[this.ckey] = this.cookie
|
||||
await local.set("quark", this.cookie, JSON.stringify(cookieDic));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (resp.code != = 200 && leftRetry > 0) {
|
||||
Utils.sleep(1)
|
||||
return await this.api(url, data, leftRetry - 1);
|
||||
}
|
||||
return JSON.parse(resp.content) || {};
|
||||
}
|
||||
|
||||
getShareData(url) {
|
||||
let regex = /https:\/\/pan\.quark\.cn\/s\/([ ^\\|#/]+)/;
|
||||
let matches = regex.exec(url);
|
||||
if (matches) {
|
||||
return {
|
||||
shareId:matches[1],
|
||||
folderId:'0',
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async getShareToken(shareData) {
|
||||
if (!this.shareTokenCache[shareData.shareId]) {
|
||||
delete this.shareTokenCache[shareData.shareId];
|
||||
const shareToken = await this.api(`share / sharepage / token ? $ {
|
||||
this.pr
|
||||
}`,{
|
||||
pwd_id:
|
||||
shareData.shareId,
|
||||
passcode:shareData.sharePwd || '',
|
||||
});
|
||||
if (shareToken.data && shareToken.data.stoken) {
|
||||
this.shareTokenCache[shareData.shareId] = shareToken.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async listFile(shareIndex, shareData, videos, subtitles, shareId, folderId, page) {
|
||||
const prePage = 200;
|
||||
page = page || 1;
|
||||
const listData = await this.api(`share / sharepage / detail ? $ {
|
||||
this.pr
|
||||
}&pwd_id = $ {
|
||||
shareId
|
||||
}&stoken = $ {
|
||||
encodeURIComponent(this.shareTokenCache[shareId].stoken)
|
||||
}&pdir_fid = $ {
|
||||
folderId
|
||||
}&force = 0 & _page = $ {
|
||||
page
|
||||
}&_size = $ {
|
||||
prePage
|
||||
}&_sort = file_type:asc, file_name:asc`,null, null, 'get');
|
||||
if (!listData.data) return [];
|
||||
const items = listData.data.list;
|
||||
if (!items) return [];
|
||||
const subDir = [];
|
||||
for (const item of items){
|
||||
if (item.dir == = true) {
|
||||
subDir.push(item);
|
||||
} else if (item.file == = true && item.obj_category == = 'video') {
|
||||
if (item.size < 1024 * 1024 * 5) continue;
|
||||
item.stoken = this.shareTokenCache[shareData.shareId].stoken;
|
||||
videos.push(Item.objectFrom(item, shareData.shareId, shareIndex));
|
||||
} else if (item.type == = 'file' && this.subtitleExts.some((x) = > item.file_name.endsWith(x)))
|
||||
{
|
||||
subtitles.push(Item.objectFrom(item, shareData, shareIndex));
|
||||
}
|
||||
}
|
||||
if (page < Math.ceil(listData.metadata._total / prePage)) {
|
||||
const nextItems = await
|
||||
this.listFile(shareIndex, shareData.shareId, videos, subtitles, shareId, folderId, page + 1);
|
||||
for (const item of nextItems){
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
for (const dir of subDir){
|
||||
const subItems = await
|
||||
this.listFile(shareIndex, shareData, videos, subtitles, shareId, dir.fid);
|
||||
for (const item of subItems){
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
findBestLCS(mainItem, targetItems) {
|
||||
const results = [];
|
||||
let bestMatchIndex = 0;
|
||||
for (let i = 0; i < targetItems.length; i++) {
|
||||
const currentLCS = Utils.lcs(mainItem.name, targetItems[i].name);
|
||||
results.push({target:targetItems[i], lcs:currentLCS });
|
||||
if (currentLCS.length > results[bestMatchIndex].lcs.length) {
|
||||
bestMatchIndex = i;
|
||||
}
|
||||
}
|
||||
const bestMatch = results[bestMatchIndex];
|
||||
return {allLCS:results, bestMatch:bestMatch, bestMatchIndex:bestMatchIndex };
|
||||
}
|
||||
|
||||
async getFilesByShareUrl(shareIndex, shareInfo, videos, subtitles) {
|
||||
const shareData = typeof shareInfo == = 'string' ? this.getShareData(shareInfo) : shareInfo;
|
||||
if (!shareData) return [];
|
||||
await this.getShareToken(shareData);
|
||||
if (!this.shareTokenCache[shareData.shareId]) return [];
|
||||
await
|
||||
this.listFile(shareIndex, shareData, videos, subtitles, shareData.shareId, shareData.folderId);
|
||||
if (subtitles.length > 0) {
|
||||
videos.forEach((item) = > {
|
||||
var matchSubtitle = this.findBestLCS(item, subtitles);
|
||||
if (matchSubtitle.bestMatch) {
|
||||
item.subtitle = matchSubtitle.bestMatch.target;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
clean() {
|
||||
const saves = Object.keys(this.saveFileIdCaches);
|
||||
for (const save of saves){
|
||||
delete this.saveFileIdCaches[save];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async clearSaveDir() {
|
||||
const listData = await this.api(`file / sort ? $ {
|
||||
this.pr
|
||||
}&pdir_fid = $ {
|
||||
this.saveDirId
|
||||
}&_page = 1 & _size = 200 & _sort = file_type:asc, updated_at:desc`,{
|
||||
},{
|
||||
},'get');
|
||||
if (listData.data && listData.data.list && listData.data.list.length > 0) {
|
||||
await this.api(`file / delete ? $ {
|
||||
this.pr
|
||||
}`,{
|
||||
action_type:
|
||||
2,
|
||||
filelist:listData.data.list.map((v) = > v.fid),
|
||||
exclude_fids: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async createSaveDir(clean) {
|
||||
if (this.saveDirId) {
|
||||
// 删除所有子文件
|
||||
if (clean) await this.clearSaveDir();
|
||||
return;
|
||||
}
|
||||
const listData = await this.api(`file / sort ? $ {
|
||||
this.pr
|
||||
}&pdir_fid = 0 & _page = 1 & _size = 200 & _sort = file_type:asc, updated_at:desc`,{
|
||||
},{
|
||||
},'get');
|
||||
if (listData.data && listData.data.list)
|
||||
for (const item of listData.data.list){
|
||||
if (item.file_name == = this.saveDirName) {
|
||||
this.saveDirId = item.fid;
|
||||
await this.clearSaveDir();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!this.saveDirId) {
|
||||
const create = await this.api(`file ? $ {
|
||||
this.pr
|
||||
}`,{
|
||||
pdir_fid:
|
||||
'0',
|
||||
file_name:this.saveDirName,
|
||||
dir_path:'',
|
||||
dir_init_lock:false,
|
||||
});
|
||||
if (create.data && create.data.fid) {
|
||||
this.saveDirId = create.data.fid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async save(shareId, stoken, fileId, fileToken, clean) {
|
||||
await this.createSaveDir(clean);
|
||||
if (clean) {
|
||||
this.clean()
|
||||
}
|
||||
if (!this.saveDirId) return null;
|
||||
if (!stoken) {
|
||||
await this.getShareToken({
|
||||
shareId:shareId,
|
||||
});
|
||||
if (!this.shareTokenCache[shareId]) return null;
|
||||
}
|
||||
const saveResult = await this.api(`share / sharepage / save ? $ {
|
||||
this.pr
|
||||
}`,{
|
||||
fid_list: [fileId],
|
||||
fid_token_list: [fileToken],
|
||||
to_pdir_fid:
|
||||
this.saveDirId,
|
||||
pwd_id:shareId,
|
||||
stoken:stoken || this.shareTokenCache[shareId].stoken,
|
||||
pdir_fid:'0',
|
||||
scene:'link',
|
||||
});
|
||||
if (saveResult.data && saveResult.data.task_id) {
|
||||
let retry = 0;
|
||||
// wait task finish
|
||||
while (true) {
|
||||
const taskResult = await this.api(`task ? $ {
|
||||
this.pr
|
||||
}&task_id = $ {
|
||||
saveResult.data.task_id
|
||||
}&retry_index = $ {
|
||||
retry
|
||||
}`,{
|
||||
},{
|
||||
},'get');
|
||||
if (taskResult.data && taskResult.data.save_as && taskResult.data.save_as.save_as_top_fids && taskResult.data.save_as.save_as_top_fids.length > 0) {
|
||||
return taskResult.data.save_as.save_as_top_fids[0];
|
||||
}
|
||||
retry++;
|
||||
if (retry > 2) break;
|
||||
Utils.sleep(1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
async getLiveTranscoding(shareId, stoken, fileId, fileToken) {
|
||||
if (!this.saveFileIdCaches[fileId]) {
|
||||
const saveFileId = await this.save(shareId, stoken, fileId, fileToken, true);
|
||||
if (!saveFileId) return null;
|
||||
this.saveFileIdCaches[fileId] = saveFileId;
|
||||
}
|
||||
const transcoding = await this.api(`file / v2 / play ? $ {
|
||||
this.pr
|
||||
}`,{
|
||||
fid:
|
||||
this.saveFileIdCaches[fileId],
|
||||
resolutions:'normal,low,high,super,2k,4k',
|
||||
supports:'fmp4',
|
||||
});
|
||||
if (transcoding.data && transcoding.data.video_list) {
|
||||
return transcoding.data.video_list;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async getDownload(shareId, stoken, fileId, fileToken, clean) {
|
||||
if (!this.saveFileIdCaches[fileId]) {
|
||||
const saveFileId = await this.save(shareId, stoken, fileId, fileToken, clean);
|
||||
if (!saveFileId) return null;
|
||||
this.saveFileIdCaches[fileId] = saveFileId;
|
||||
}
|
||||
const down = await this.api(`file / download ? $ {
|
||||
this.pr
|
||||
}&uc_param_str =`,{
|
||||
fids: [this.saveFileIdCaches[fileId]],
|
||||
});
|
||||
if (down.data) {
|
||||
return down.data[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ 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.crawler.Spider;
|
||||
|
|
@ -17,13 +16,11 @@ import org.jsoup.nodes.Document;
|
|||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
|
@ -31,21 +28,20 @@ import java.util.regex.Pattern;
|
|||
public class Libvio extends Spider {
|
||||
|
||||
private static String siteUrl = "";
|
||||
private static final String cateUrl = siteUrl + "/list/";
|
||||
private static final String detailUrl = siteUrl + "/play/";
|
||||
private static final String playUrl = siteUrl + "/play/";
|
||||
private static final String searchUrl = siteUrl + "/search--------------.html?wd=";
|
||||
|
||||
|
||||
private static final String MOBILE_UA = "Mozilla/5.0 (Linux; Android 11; M2007J3SC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045714 Mobile Safari/537.36";
|
||||
|
||||
private HashMap<String, String> getHeaders() {
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("User-Agent", Util.CHROME);
|
||||
headers.put("User-Agent", MOBILE_UA);
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
private HashMap<String, String> getHeaders(String refer) {
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("User-Agent", Util.CHROME);
|
||||
headers.put("User-Agent", MOBILE_UA);
|
||||
headers.put("Referer", refer);
|
||||
|
||||
return headers;
|
||||
|
|
@ -148,6 +144,9 @@ public class Libvio extends Spider {
|
|||
String PlayUrl = "";
|
||||
for (int i = 0; i < tabs.size(); i++) {
|
||||
String tabName = tabs.get(i).text();
|
||||
if (tabName.contains("夸克")) {
|
||||
continue;
|
||||
}
|
||||
if (!"".equals(PlayFrom)) {
|
||||
PlayFrom = PlayFrom + "$$$" + tabName;
|
||||
} else {
|
||||
|
|
@ -181,19 +180,18 @@ public class Libvio extends Spider {
|
|||
@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)), getHeaders()));
|
||||
for (Element element : doc.select("div.searchlist_img")) {
|
||||
try {
|
||||
String pic = element.select("a").attr("data-original");
|
||||
String url = element.select("a").attr("href");
|
||||
String name = element.select("a").attr("title");
|
||||
if (!pic.startsWith("http")) {
|
||||
pic = siteUrl + pic;
|
||||
}
|
||||
String id = url.replace("/video/", "").replace(".html", "-1-1.html");
|
||||
list.add(new Vod(id, name, pic));
|
||||
} catch (Exception e) {
|
||||
Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat("/search/-------------.html?wd=").concat(URLEncoder.encode(key)), getHeaders()));
|
||||
for (Element element : doc.select("ul.stui-vodlist > li > div > a")) {
|
||||
|
||||
String pic = element.attr("data-original");
|
||||
String url = element.attr("href");
|
||||
String name = element.attr("title");
|
||||
if (!pic.startsWith("http")) {
|
||||
pic = siteUrl + pic;
|
||||
}
|
||||
String id = url.split("/")[2];
|
||||
list.add(new Vod(id, name, pic));
|
||||
|
||||
}
|
||||
return Result.string(list);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ public class LibvioTest {
|
|||
|
||||
@org.junit.Test
|
||||
public void playerContent() throws Exception {
|
||||
String froms = "BD播放$$$视频下载 (夸克)";
|
||||
String urls = "第01集$714891769-1-1.html#第02集$714891769-1-2.html#第03集$714891769-1-3.html#第04集$714891769-1-4.html$$$合集$714891769-2-1.html";
|
||||
String froms = "BD播放";
|
||||
String urls = "第01集$714891769-1-1.html#第02集$714891769-1-2.html#第03集$714891769-1-3.html#第04集$714891769-1-4.html";
|
||||
for (int i = 0; i < urls.split("\\$\\$\\$").length; i++) {
|
||||
String content = spider.playerContent(froms.split("\\$\\$\\$")[i], urls.split("\\$\\$\\$")[i].split("#")[0].split("\\$")[1], new ArrayList<>());
|
||||
JsonObject map = Json.safeObject(content);
|
||||
|
|
@ -87,7 +87,7 @@ public class LibvioTest {
|
|||
|
||||
@org.junit.Test
|
||||
public void searchContent() throws Exception {
|
||||
String content = spider.searchContent("红海", false);
|
||||
String content = spider.searchContent("唐朝", false);
|
||||
JsonObject map = Json.safeObject(content);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
System.out.println("searchContent--" + gson.toJson(map));
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
01e1c90f1873a3e193bc494b9eab2d83
|
||||
e3bc7843d766de40c20a38dd72c989cd
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"spider": "../jar/custom_spider.jar;md5;01e1c90f1873a3e193bc494b9eab2d83",
|
||||
"spider": "../jar/custom_spider.jar;md5;e3bc7843d766de40c20a38dd72c989cd",
|
||||
"lives": [
|
||||
{
|
||||
"name": "直播ipv6",
|
||||
|
|
@ -70,7 +70,6 @@
|
|||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
|
||||
{
|
||||
"key": "W55Movie",
|
||||
"name": "\uD83C\uDF9E\uFE0F 555电影 | 搜索×",
|
||||
|
|
@ -111,26 +110,23 @@
|
|||
"searchable": 1,
|
||||
"filterable": 1
|
||||
},
|
||||
|
||||
{
|
||||
"key": "ikanbot",
|
||||
"name": "🤖┃爱看机器人┃🤖",
|
||||
|
||||
"type": 3,
|
||||
"api": "csp_Ikanbot",
|
||||
|
||||
"searchable": 1,
|
||||
"filterable": 0,
|
||||
"ext": "{\"box\": \"TVBox\", \"danmu\": false}"
|
||||
},
|
||||
{
|
||||
"key": "nangua",
|
||||
"name": "🎃┃南瓜影视┃🎃",
|
||||
"playerType": 0,
|
||||
"key": "Libvio",
|
||||
"name": "立播",
|
||||
"type": 3,
|
||||
"api": "./js/nangua.js",
|
||||
"timeout": 30,
|
||||
"ext": "{\"box\": \"TVBox\", \"danmu\": false}"
|
||||
"api": "csp_Libvio",
|
||||
"searchable": 1,
|
||||
"filterable": 0
|
||||
},
|
||||
|
||||
{
|
||||
"key": "Ysj",
|
||||
"name": "\uD83C\uDF0F\uFE0F 异世界动漫 | 动漫(不稳定)",
|
||||
|
|
|
|||
Loading…
Reference in New Issue