libvio 暂无夸克

This commit is contained in:
lushunming 2024-08-02 10:01:38 +08:00
parent d218a71471
commit a4bc07a717
6 changed files with 357 additions and 37 deletions

View File

@ -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;
}
*/
}

View File

@ -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);
}

View File

@ -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.

View File

@ -1 +1 @@
01e1c90f1873a3e193bc494b9eab2d83
e3bc7843d766de40c20a38dd72c989cd

View File

@ -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 异世界动漫 | 动漫(不稳定)",