夸克部分
This commit is contained in:
parent
a4bc07a717
commit
98cadeb8a5
|
|
@ -1,326 +1,254 @@
|
|||
/*
|
||||
package com.github.catvod.api;
|
||||
|
||||
import com.github.catvod.bean.quark.Item;
|
||||
import com.github.catvod.utils.Util;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
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';
|
||||
|
||||
private static final String API_URL = "https://drive-pc.QuarkApi.cn/1/clouddrive/";
|
||||
private String cookie;
|
||||
private String ckey;
|
||||
private Map<String, String> shareTokenCache;
|
||||
private String pr = "pr=ucpro&fr=pc";
|
||||
private List<String> subtitleExts;
|
||||
private Map<String, String> saveFileIdCaches;
|
||||
private String saveDirId;
|
||||
private String saveDirName = "TV";
|
||||
|
||||
public QuarkApi() {
|
||||
this.shareTokenCache = new HashMap<>();
|
||||
this.subtitleExts = List.of(".srt", ".ass", ".scc", ".stl", ".ttml");
|
||||
this.saveFileIdCaches = new HashMap<>();
|
||||
}
|
||||
|
||||
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]
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
}
|
||||
|
||||
public void initQuark(String cookie) {
|
||||
|
||||
this.ckey = bytesToHex(Util.MD5(cookie).getBytes());
|
||||
String localCfg = local.get("quark", "cookie");
|
||||
if (!localCfg.isEmpty()) {
|
||||
Map<String, String> cookieMap = new HashMap<>();
|
||||
JSONObject localCookie = new JSONObject(localCfg);
|
||||
cookieMap.put(this.ckey, localCookie.getString(this.ckey));
|
||||
this.cookie = cookieMap.get(this.ckey);
|
||||
} else {
|
||||
this.cookie = cookie
|
||||
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"
|
||||
);
|
||||
|
||||
public 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.QuarkApi.cn/", "Content-Type", "application/json", "Cookie", this.cookie, "Host", "drive-pc.QuarkApi.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));
|
||||
}
|
||||
public JSONObject api(String url, String data, int retry, String method) throws ExecutionException, InterruptedException {
|
||||
int leftRetry = retry != null ? retry : 3;
|
||||
JSONObject resp = req(API_URL + url, method != null ? method : "post", data, getHeaders());
|
||||
if (resp.headers().get("set-cookie") != null) {
|
||||
String[] puus = resp.headers().get("set-cookie").split(";;;").stream().map(String::trim).filter(s -> s.startsWith("__puus=")).map(s -> s.substring(s.indexOf('=') + 1)).collect(Collectors.toList()).toArray(new String[0]);
|
||||
if (puus.length > 0 && !this.cookie.matches("__puus=[^;]+") || !this.cookie.replace("__puus=[^;]+", "__puus=" + puus[0]).equals(this.cookie)) {
|
||||
this.cookie = this.cookie.replace("__puus=[^;]+", "__puus=" + puus[0]);
|
||||
Map<String, String> cookieDic = new HashMap<>();
|
||||
cookieDic.put(this.ckey, this.cookie);
|
||||
local.set("quark", this.cookie, new JSONObject(cookieDic).toString());
|
||||
}
|
||||
}
|
||||
if (resp.code != = 200 && leftRetry > 0) {
|
||||
Utils.sleep(1)
|
||||
return await this.api(url, data, leftRetry - 1);
|
||||
if (resp.code() != 200 && leftRetry > 0) {
|
||||
Utils.sleep(1);
|
||||
return api(url, data, leftRetry - 1, method);
|
||||
}
|
||||
return JSON.parse(resp.content) || {};
|
||||
return resp;
|
||||
}
|
||||
|
||||
getShareData(url) {
|
||||
let regex = /https:\/\/pan\.quark\.cn\/s\/([ ^\\|#/]+)/;
|
||||
let matches = regex.exec(url);
|
||||
if (matches) {
|
||||
return {
|
||||
shareId:matches[1],
|
||||
folderId:'0',
|
||||
};
|
||||
public Map<String, String> getShareData(String url) {
|
||||
Pattern regex = Pattern.compile("https://pan\\.quark\\.cn\\/s\\/([^\\|#/]+)");
|
||||
Matcher matches = regex.matcher(url);
|
||||
if (matches.find()) {
|
||||
return Map.of("shareId", matches.group(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;
|
||||
public void getShareToken(QuarkApi.ShareData shareData) throws ExecutionException, InterruptedException {
|
||||
if (!shareTokenCache.containsKey(shareData.shareId)) {
|
||||
JSONObject shareToken = api("share/sharepage/token?" + pr, Map.of("pwd_id", shareData.shareId, "passcode", shareData.sharePwd), null, "get");
|
||||
if (shareToken != null && shareToken.has("data") && shareToken.getJSONObject("data").has("stoken")) {
|
||||
shareTokenCache.put(shareData.shareId, shareToken.getJSONObject("data").getJSONObject("stoken").toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
public List<Item> listFile(QuarkApi.ShareData shareData, List<Item> videos, List<Item> subtitles, String shareId, String folderId, int page) throws ExecutionException, InterruptedException {
|
||||
int prePage = 200;
|
||||
page = page != 0 ? page : 1;
|
||||
JSONObject listData = api("share/sharepage/detail?" + pr + "&pwd_id=" + shareId + "&stoken=" + URLEncoder.encode(shareTokenCache.get(shareData.shareId).get("stoken")) + "&pdir_fid=" + folderId + "&force=0&_page=" + page + "&_size=" + prePage + "&_sort=file_type:asc,file_name:asc", null, null, "get");
|
||||
if (listData != null && listData.has("data") && listData.getJSONObject("data").has("list")) {
|
||||
List<Item> items = listData.getJSONObject("data").getJSONArray("list").toList().stream().map(item -> Item.objectFrom(item, shareData, page)).collect(Collectors.toList());
|
||||
if (page < Math.ceil(listData.getJSONObject("metadata").getJSONObject("_total").toString() / prePage)) {
|
||||
List<Item> nextItems = listFile(shareData, videos, subtitles, shareId, folderId, page + 1);
|
||||
items.addAll(nextItems);
|
||||
}
|
||||
for (Item dir : items) {
|
||||
if (dir.dir()) {
|
||||
List<Item> subItems = listFile(shareData, videos, subtitles, shareId, dir.fid);
|
||||
items.addAll(subItems);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public JSONObject findBestLCS(Item mainItem, List<Item> targetItems) {
|
||||
List<JSONObject> results = targetItems.stream().map(targetItem -> new JSONObject().put("target", targetItem).put("lcs", Utils.lcs(mainItem.name, targetItem.name))).collect(Collectors.toList());
|
||||
int bestMatchIndex = 0;
|
||||
for (int i = 1; i < results.size(); i++) {
|
||||
if (results.get(i).getJSONObject("lcs").length() > results.get(bestMatchIndex).getJSONObject("lcs").length()) {
|
||||
bestMatchIndex = i;
|
||||
}
|
||||
}
|
||||
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 results.get(bestMatchIndex);
|
||||
}
|
||||
|
||||
public List<Item> getFilesByShareUrl(int shareIndex, QuarkApi.ShareData shareInfo, List<Item> videos, List<Item> subtitles) throws ExecutionException, InterruptedException {
|
||||
QuarkApi.ShareData shareData = shareInfo instanceof String ? getShareData((String) shareInfo) : (QuarkApi.ShareData) shareInfo;
|
||||
if (shareData == null) return Collections.emptyList();
|
||||
getShareToken(shareData);
|
||||
if (shareTokenCache.get(shareData.shareId) == null) return Collections.emptyList();
|
||||
List<Item> items = listFile(shareIndex, shareData, videos, subtitles, shareData.shareId, shareData.folderId);
|
||||
if (subtitles.size() > 0) {
|
||||
videos.forEach(item -> {
|
||||
JSONObject matchSubtitle = findBestLCS(item, subtitles);
|
||||
if (matchSubtitle != null) {
|
||||
item.subtitle = matchSubtitle.getJSONObject("target");
|
||||
}
|
||||
});
|
||||
}
|
||||
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;
|
||||
}
|
||||
});
|
||||
public void clean() {
|
||||
Map<String, String> saves = new HashMap<>(saveFileIdCaches);
|
||||
for (String save : saves.keySet()) {
|
||||
saveFileIdCaches.remove(save);
|
||||
}
|
||||
}
|
||||
|
||||
clean() {
|
||||
const saves = Object.keys(this.saveFileIdCaches);
|
||||
for (const save of saves){
|
||||
delete this.saveFileIdCaches[save];
|
||||
public void clearSaveDir() throws ExecutionException, InterruptedException {
|
||||
JSONObject listData = api("file/sort?" + pr + "&pdir_fid=" + saveDirId + "&_page=1&_size=200&_sort=file_type:asc,updated_at:desc", null, null, "get");
|
||||
if (listData != null && listData.has("data") && listData.getJSONObject("data").has("list") && listData.getJSONObject("data").getJSONArray("list").length() > 0) {
|
||||
api("file/delete?" + pr, Map.of("action_type", 2, "filelist", listData.getJSONObject("data").getJSONArray("list").toList().stream().map(f -> f.getString("fid")).collect(Collectors.toList()), "exclude_fids", new JSONArray()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
public void createSaveDir(boolean clean) throws ExecutionException, InterruptedException {
|
||||
if (saveDirId != null) {
|
||||
if (clean) 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;
|
||||
JSONObject listData = api("file/sort?" + pr + "&pdir_fid=0&_page=1&_size=200&_sort=file_type:asc,updated_at:desc", null, null, "get");
|
||||
if (listData != null && listData.has("data") && listData.getJSONObject("data").has("list")) {
|
||||
for (JSONObject item : listData.getJSONObject("data").getJSONArray("list").toList()) {
|
||||
if (item.getString("file_name").equals(saveDirName)) {
|
||||
saveDirId = item.getString("fid");
|
||||
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;
|
||||
if (saveDirId == null) {
|
||||
JSONObject create = api("file?" + pr, Map.of("pdir_fid", "0", "file_name", saveDirName, "dir_path", "", "dir_init_lock", false));
|
||||
if (create != null && create.has("data") && create.getJSONObject("data").has("fid")) {
|
||||
saveDirId = create.getJSONObject("data").getString("fid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async save(shareId, stoken, fileId, fileToken, clean) {
|
||||
await this.createSaveDir(clean);
|
||||
if (clean) {
|
||||
this.clean()
|
||||
public String save(String shareId, String stoken, String fileId, String fileToken, boolean clean) throws ExecutionException, InterruptedException {
|
||||
createSaveDir(clean);
|
||||
if (clean) clean();
|
||||
if (saveDirId == null) return null;
|
||||
if (stoken == null) {
|
||||
getShareToken(Map.of("shareId", shareId));
|
||||
if (shareTokenCache.get(shareId) == null) return null;
|
||||
}
|
||||
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
|
||||
JSONObject saveResult = api("share/sharepage/save?" + pr, Map.of("fid_list", new JSONArray().put(fileId), "fid_token_list", new JSONArray().put(fileToken), "to_pdir_fid", saveDirId, "pwd_id", shareId, "stoken", stoken != null ? stoken : shareTokenCache.get(shareId).getJSONObject("stoken").toString(), "pdir_fid", "0", "scene", "link"));
|
||||
if (saveResult != null && saveResult.has("data") && saveResult.getJSONObject("data").has("task_id")) {
|
||||
int retry = 0;
|
||||
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];
|
||||
JSONObject taskResult = api("task?" + pr + "&task_id=" + saveResult.getJSONObject("data").getString("task_id") + "&retry_index=" + retry, null, null, "get");
|
||||
if (taskResult != null && taskResult.has("data") && taskResult.getJSONObject("data").has("save_as") && taskResult.getJSONObject("data").getJSONObject("save_as").has("save_as_top_fids") && taskResult.getJSONObject("data").getJSONObject("save_as").getJSONArray("save_as_top_fids").length() > 0) {
|
||||
return taskResult.getJSONObject("data").getJSONObject("save_as").getJSONArray("save_as_top_fids").getJSONObject(0).getString("fid");
|
||||
}
|
||||
retry++;
|
||||
if (retry > 2) break;
|
||||
Utils.sleep(1);
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
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;
|
||||
public List<JSONObject> getLiveTranscoding(String shareId, String stoken, String fileId, String fileToken) throws ExecutionException, InterruptedException {
|
||||
if (!saveFileIdCaches.containsKey(fileId)) {
|
||||
String saveFileId = save(shareId, stoken, fileId, fileToken, true);
|
||||
if (saveFileId == null) return null;
|
||||
saveFileIdCaches.put(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;
|
||||
JSONObject transcoding = api("file/v2/play?" + pr, Map.of("fid", saveFileIdCaches.get(fileId), "resolutions", "normal,low,high,super,2k,4k", "supports", "fmp4"));
|
||||
if (transcoding != null && transcoding.has("data") && transcoding.getJSONObject("data").has("video_list")) {
|
||||
return transcoding.getJSONObject("data").getJSONArray("video_list").toList();
|
||||
}
|
||||
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;
|
||||
public JSONObject getDownload(String shareId, String stoken, String fileId, String fileToken, boolean clean) throws ExecutionException, InterruptedException {
|
||||
if (!saveFileIdCaches.containsKey(fileId)) {
|
||||
String saveFileId = save(shareId, stoken, fileId, fileToken, clean);
|
||||
if (saveFileId == null) return null;
|
||||
saveFileIdCaches.put(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];
|
||||
JSONObject down = api("file/download?" + pr + "&uc_param_str", Map.of("fids", new JSONArray().put(saveFileIdCaches.get(fileId))));
|
||||
if (down != null && down.has("data")) {
|
||||
return down.getJSONObject("data").getJSONObject(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
public static class ShareData {
|
||||
private String shareId;
|
||||
private String folderId;
|
||||
private String sharePwd;
|
||||
|
||||
public ShareData(String shareId, String folderId, String sharePwd) {
|
||||
this.shareId = shareId;
|
||||
this.folderId = folderId;
|
||||
this.sharePwd = sharePwd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
package com.github.catvod.bean.quark;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Item {
|
||||
private String fileId;
|
||||
private String shareId;
|
||||
private String shareToken;
|
||||
private String shareFileToken;
|
||||
private String seriesId;
|
||||
private String name;
|
||||
private String type;
|
||||
private String formatType;
|
||||
private String size;
|
||||
private String parent;
|
||||
private String shareData;
|
||||
private int shareIndex;
|
||||
private long lastUpdateAt;
|
||||
|
||||
public Item() {
|
||||
this.fileId = "";
|
||||
this.shareId = "";
|
||||
this.shareToken = "";
|
||||
this.shareFileToken = "";
|
||||
this.seriesId = "";
|
||||
this.name = "";
|
||||
this.type = "";
|
||||
this.formatType = "";
|
||||
this.size = "";
|
||||
this.parent = "";
|
||||
this.shareData = null;
|
||||
this.shareIndex = 0;
|
||||
this.lastUpdateAt = 0;
|
||||
}
|
||||
|
||||
public static Item objectFrom(String item_json, String shareId, int shareIndex) {
|
||||
Item item = new Item();
|
||||
item.fileId = item_json.contains("fid") ? item_json.split("fid=")[1].split("&")[0] : "";
|
||||
item.shareId = shareId;
|
||||
item.shareToken = item_json.contains("stoken") ? item_json.split("stoken=")[1].split("&")[0] : "";
|
||||
item.shareFileToken = item_json.contains("share_fid_token") ? item_json.split("share_fid_token=")[1].split("&")[0] : "";
|
||||
item.seriesId = item_json.contains("series_id") ? item_json.split("series_id=")[1].split("&")[0] : "";
|
||||
item.name = item_json.contains("file_name") ? item_json.split("file_name=")[1].split("&")[0] : "";
|
||||
item.type = item_json.contains("obj_category") ? item_json.split("obj_category=")[1].split("&")[0] : "";
|
||||
item.formatType = item_json.contains("format_type") ? item_json.split("format_type=")[1].split("&")[0] : "";
|
||||
item.size = item_json.contains("size") ? item_json.split("size=")[1].split("&")[0] : "";
|
||||
item.parent = item_json.contains("pdir_fid") ? item_json.split("pdir_fid=")[1].split("&")[0] : "";
|
||||
item.lastUpdateAt = item_json.contains("last_update_at") ? Long.parseLong(item_json.split("last_update_at=")[1].split("&")[0]) : 0;
|
||||
item.shareIndex = shareIndex;
|
||||
return item;
|
||||
}
|
||||
|
||||
public String getFileExtension() {
|
||||
String[] arr = name.split("\\.");
|
||||
return arr[arr.length - 1];
|
||||
}
|
||||
|
||||
public String getFileId() {
|
||||
return fileId.isEmpty() ? "" : fileId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name.isEmpty() ? "" : name;
|
||||
}
|
||||
|
||||
public String getParent() {
|
||||
return parent.isEmpty() ? "" : "[" + parent + "]";
|
||||
}
|
||||
|
||||
public String getSize() {
|
||||
return size.equals("0") ? "" : "[" + size + "]";
|
||||
}
|
||||
|
||||
|
||||
public int getShareIndex() {
|
||||
return shareIndex;
|
||||
}
|
||||
|
||||
public String getDisplayName(String type_name) {
|
||||
String name = getName();
|
||||
if (type_name.equals("电视剧")) {
|
||||
String[] replaceNameList = {"4k", "4K"};
|
||||
name = name.replaceAll("\\." + getFileExtension(), "");
|
||||
for (String replaceName : replaceNameList) {
|
||||
name = name.replaceAll(replaceName, "");
|
||||
}
|
||||
name = Pattern.compile("/\\.S01E(.*?)\\./").matcher(name).find() ? name.split("/\\.S01E(.*?)\\./")[1] : name;
|
||||
String[] numbers = name.split("\\d+");
|
||||
if (numbers.length > 0) {
|
||||
name = numbers[0];
|
||||
}
|
||||
}
|
||||
return name + " " + size;
|
||||
}
|
||||
|
||||
public String getEpisodeUrl(String type_name) {
|
||||
return getDisplayName(type_name) + "$" + getFileId() + "++" + shareFileToken + "++" + shareId + "++" + shareToken;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue