Merge branch 'FongMi:main' into main

This commit is contained in:
李耀东 2023-05-01 10:51:55 +08:00 committed by GitHub
commit a41c5ce2b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 2567 additions and 12174 deletions

View File

@ -3,9 +3,3 @@
### Based on CatVod
https://github.com/CatVodTVOfficial/CatVodTVSpider
### Usage
[fastgit](https://raw.fastgit.org/FongMi/CatVodSpider/main/json/config.json)
[gh-proxy](https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/config.json)
[https://fongmi.page.link/cat](https://fongmi.page.link/cat)

View File

@ -11,6 +11,7 @@ android {
minSdk 17
targetSdk 29
ndk { abiFilters "armeabi-v7a" }
buildConfigField("String", "CLIENT_ID", "\"${clientId}\"")
}
buildTypes {
@ -27,17 +28,17 @@ android {
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
//Debug For HTTP/3
//implementation 'org.chromium.net:cronet-embedded:101.4951.41'
debugImplementation 'org.chromium.net:cronet-embedded:101.4951.41'
implementation('com.github.thegrizzlylabs:sardine-android:0.8') { exclude group: 'com.squareup.okhttp3', module: 'okhttp' }
implementation('com.squareup.okhttp3:okhttp:3.12.13') { force = true }
implementation 'com.google.net.cronet:cronet-okhttp:0.1.0'
implementation 'androidx.annotation:annotation:1.5.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'cn.wanghaomiao:JsoupXpath:2.5.1'
implementation 'com.google.zxing:core:3.3.0'

View File

@ -20,16 +20,20 @@
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
# Cronet
-keep class org.chromium.net.** { *; }
-keep class com.google.net.cronet.** { *; }
# OkHttp
-dontwarn okhttp3.**
-keep class okio.** { *; }
-keep class okhttp3.** { *; }
# Sardine
-keep class com.thegrizzlylabs.sardineandroid.** { *; }
# Zxing
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# OkHttp
-keep class okio.**{*;}
-keep class okhttp3.**{*;}
# Cronet
-keep class org.chromium.net.**{*;}
-keep class com.google.net.cronet.**{*;}

View File

@ -0,0 +1,483 @@
package com.github.catvod.ali;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.github.catvod.BuildConfig;
import com.github.catvod.bean.Sub;
import com.github.catvod.bean.Vod;
import com.github.catvod.bean.ali.Code;
import com.github.catvod.bean.ali.Data;
import com.github.catvod.bean.ali.Item;
import com.github.catvod.bean.ali.OAuth;
import com.github.catvod.bean.ali.Sorter;
import com.github.catvod.bean.ali.User;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.net.OkHttp;
import com.github.catvod.spider.Init;
import com.github.catvod.spider.Proxy;
import com.github.catvod.utils.Prefers;
import com.github.catvod.utils.QRCode;
import com.github.catvod.utils.Utils;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class API {
private final Map<String, String> quality;
private ScheduledExecutorService service;
private final List<String> tempIds;
private AlertDialog dialog;
private String refreshToken;
private String shareToken;
private String shareId;
private OAuth oauth;
private User user;
private static class Loader {
static volatile API INSTANCE = new API();
}
public static API get() {
return Loader.INSTANCE;
}
private API() {
tempIds = new ArrayList<>();
oauth = OAuth.objectFrom(Prefers.getString("aliyundrive_oauth"));
user = User.objectFrom(Prefers.getString("aliyundrive_user"));
quality = new HashMap<>();
quality.put("4K", "UHD");
quality.put("2k", "QHD");
quality.put("超清", "FHD");
quality.put("高清", "HD");
quality.put("標清", "SD");
quality.put("流暢", "LD");
}
public void setRefreshToken(String token) {
this.refreshToken = token;
}
public void setShareId(String shareId) {
this.shareId = shareId;
refreshShareToken();
checkAccessToken();
}
public HashMap<String, String> getHeader() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Utils.CHROME);
headers.put("Referer", "https://www.aliyundrive.com/");
return headers;
}
private HashMap<String, String> getHeaderAuth() {
HashMap<String, String> headers = getHeader();
headers.put("authorization", user.getAuthorization());
headers.put("x-share-token", shareToken);
return headers;
}
private HashMap<String, String> getHeaderOpen() {
HashMap<String, String> headers = getHeader();
headers.put("authorization", oauth.getAuthorization());
return headers;
}
private String post(String url, JSONObject body) {
url = url.startsWith("https") ? url : "https://api.aliyundrive.com/" + url;
return OkHttp.postJson(url, body.toString(), getHeader());
}
private String auth(String url, String json, boolean retry) {
url = url.startsWith("https") ? url : "https://api.aliyundrive.com/" + url;
String result = OkHttp.postJson(url, json, getHeaderAuth());
if (retry && checkAuth(result)) return auth(url, json, false);
return result;
}
private String oauth(String url, String json, boolean retry) {
url = url.startsWith("https") ? url : "https://open.aliyundrive.com/adrive/v1.0/" + url;
String result = OkHttp.postJson(url, json, getHeaderOpen());
if (retry && checkOpen(result)) return oauth(url, json, false);
return result;
}
private boolean checkAuth(String result) {
if (result.contains("AccessTokenInvalid")) return refreshAccessToken();
if (result.contains("ShareLinkTokenInvalid") || result.contains("InvalidParameterNotMatch")) return refreshShareToken();
return checkQuotaExhausted(result);
}
private boolean checkOpen(String result) {
if (result.contains("AccessTokenInvalid")) return refreshOpenToken();
return false;
}
private boolean checkQuotaExhausted(String result) {
if (!result.contains("QuotaExhausted")) return false;
Init.show("容量不夠拉。");
user.clean().save();
refreshAccessToken();
return false;
}
private boolean isManyRequest(String result) {
if (!result.contains("Too Many Requests")) return false;
Init.show("洗洗睡吧Too Many Requests。");
return true;
}
private boolean isInvalidOpenToken(String result) {
if (!result.contains("invalid refresh_token")) return false;
oauth.clean().save();
oauthRequest();
return true;
}
public void checkAccessToken() {
if (user.getAccessToken().isEmpty()) refreshAccessToken();
}
private boolean refreshAccessToken() {
try {
SpiderDebug.log("refreshAccessToken...");
JSONObject body = new JSONObject();
String token = user.getRefreshToken();
if (token.isEmpty()) token = refreshToken;
if (token.startsWith("http")) token = OkHttp.string(token).trim();
body.put("refresh_token", token);
body.put("grant_type", "refresh_token");
String result = post("https://auth.aliyundrive.com/v2/account/token", body);
user = User.objectFrom(result).save();
SpiderDebug.log(user.toString());
if (user.getAccessToken().isEmpty()) throw new Exception(result);
if (oauth.getAccessToken().isEmpty()) oauthRequest();
return true;
} catch (Exception e) {
user.clean().save();
SpiderDebug.log(e);
stopService();
getQRCode();
return true;
} finally {
while (user.getAccessToken().isEmpty()) SystemClock.sleep(250);
}
}
private void oauthRequest() {
try {
SpiderDebug.log("OAuth Request...");
JSONObject body = new JSONObject();
body.put("authorize", 1);
body.put("scope", "user:base,file:all:read,file:all:write");
String url = "https://open.aliyundrive.com/oauth/users/authorize?client_id=" + BuildConfig.CLIENT_ID + "&redirect_uri=https://alist.nn.ci/tool/aliyundrive/callback&scope=user:base,file:all:read,file:all:write&state=";
String result = auth(url, body.toString(), true);
oauthRedirect(Code.objectFrom(result).getCode());
} catch (Exception e) {
SpiderDebug.log(e);
}
}
private void oauthRedirect(String code) {
try {
SpiderDebug.log("OAuth Redirect...");
JSONObject body = new JSONObject();
body.put("code", code);
body.put("grant_type", "authorization_code");
String result = post("https://api.nn.ci/alist/ali_open/code", body);
if (isManyRequest(result)) return;
oauth = OAuth.objectFrom(result).save();
SpiderDebug.log(oauth.toString());
} catch (Exception e) {
SpiderDebug.log(e);
}
}
private boolean refreshOpenToken() {
try {
SpiderDebug.log("refreshOpenToken...");
JSONObject body = new JSONObject();
body.put("grant_type", "refresh_token");
body.put("refresh_token", oauth.getRefreshToken());
String result = post("https://api.nn.ci/alist/ali_open/token", body);
if (isManyRequest(result)) return false;
if (isInvalidOpenToken(result)) return true;
oauth = OAuth.objectFrom(result).save();
SpiderDebug.log(oauth.toString());
return true;
} catch (Exception e) {
SpiderDebug.log(e);
return false;
}
}
public boolean refreshShareToken() {
try {
SpiderDebug.log("refreshShareToken...");
JSONObject body = new JSONObject();
body.put("share_id", shareId);
body.put("share_pwd", "");
JSONObject object = new JSONObject(post("v2/share_link/get_share_token", body));
shareToken = object.getString("share_token");
return true;
} catch (Exception e) {
Init.show("來晚啦,該分享已失效。");
e.printStackTrace();
return false;
}
}
public Vod getVod(String url, String fileId) throws Exception {
JSONObject body = new JSONObject();
body.put("share_id", shareId);
String json = post("adrive/v3/share_link/get_share_by_anonymous", body);
JSONObject object = new JSONObject(json);
List<Item> files = new ArrayList<>();
LinkedHashMap<String, List<String>> subMap = new LinkedHashMap<>();
listFiles(new Item(getParentFileId(fileId, object)), files, subMap);
List<String> playFrom = Arrays.asList("原畫", "超清", "高清");
List<String> episode = new ArrayList<>();
List<String> playUrl = new ArrayList<>();
Sorter.sort(files);
for (Item file : files) episode.add(file.getDisplayName() + "$" + file.getFileId() + findSubs(file.getName(), subMap));
for (int i = 0; i < playFrom.size(); i++) playUrl.add(TextUtils.join("#", episode));
Vod vod = new Vod();
vod.setVodId(url);
vod.setVodContent(url);
vod.setVodPic(object.getString("avatar"));
vod.setVodName(object.getString("share_name"));
vod.setVodPlayUrl(TextUtils.join("$$$", playUrl));
vod.setVodPlayFrom(TextUtils.join("$$$", playFrom));
vod.setTypeName("阿里雲盤");
return vod;
}
private void listFiles(Item folder, List<Item> files, LinkedHashMap<String, List<String>> subMap) throws Exception {
listFiles(folder, files, subMap, "");
}
private void listFiles(Item parent, List<Item> files, LinkedHashMap<String, List<String>> subMap, String marker) throws Exception {
JSONObject body = new JSONObject();
List<Item> folders = new ArrayList<>();
body.put("limit", 200);
body.put("share_id", shareId);
body.put("parent_file_id", parent.getFileId());
body.put("order_by", "name");
body.put("order_direction", "ASC");
if (marker.length() > 0) body.put("marker", marker);
Item item = Item.objectFrom(auth("adrive/v3/file/list", body.toString(), true));
for (Item file : item.getItems()) {
if (file.getType().equals("folder")) {
folders.add(file);
} else if (file.getCategory().equals("video") || file.getCategory().equals("audio")) {
files.add(file.parent(parent.getName()));
} else if (Utils.isSub(file.getExt())) {
String key = Utils.removeExt(file.getName());
if (!subMap.containsKey(key)) subMap.put(key, new ArrayList<>());
subMap.get(key).add(key + "@@@" + file.getExt() + "@@@" + file.getFileId());
}
}
if (item.getNextMarker().length() > 0) {
listFiles(parent, files, subMap, item.getNextMarker());
}
for (Item folder : folders) {
listFiles(folder, files, subMap);
}
}
private String getParentFileId(String fileId, JSONObject shareInfo) throws Exception {
JSONArray array = shareInfo.getJSONArray("file_infos");
if (!TextUtils.isEmpty(fileId)) return fileId;
if (array.length() == 0) return "";
JSONObject fileInfo = array.getJSONObject(0);
if (fileInfo.getString("type").equals("folder")) return fileInfo.getString("file_id");
if (fileInfo.getString("type").equals("file") && fileInfo.getString("category").equals("video")) return "root";
return "";
}
private String findSubs(String name, Map<String, List<String>> subMap) {
name = name.substring(0, name.lastIndexOf("."));
List<String> subs = subMap.get(name);
if (subs != null && subs.size() > 0) return combineSubs(subs);
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<String>> entry : subMap.entrySet()) sb.append(combineSubs(entry.getValue()));
return sb.toString();
}
private String combineSubs(List<String> subs) {
StringBuilder sb = new StringBuilder();
for (String sub : subs) sb.append("+").append(sub);
return sb.toString();
}
public List<Sub> getSub(String[] ids) {
List<Sub> sub = new ArrayList<>();
for (String text : ids) {
if (!text.contains("@@@")) continue;
String[] split = text.split("@@@");
String name = split[0];
String ext = split[1];
String url = Proxy.getUrl() + "?do=ali&type=sub" + "&file_id=" + split[2];
sub.add(Sub.create().name(name).ext(ext).url(url));
}
return sub;
}
public String getDownloadUrl(String fileId) {
try {
SpiderDebug.log("getDownloadUrl..." + fileId);
tempIds.add(0, copy(fileId));
JSONObject body = new JSONObject();
body.put("file_id", tempIds.get(0));
body.put("drive_id", user.getDriveId());
String json = oauth("openFile/getDownloadUrl", body.toString(), true);
SpiderDebug.log(json);
return new JSONObject(json).getString("url");
} catch (Exception e) {
Init.execute(this::deleteAll);
e.printStackTrace();
return "";
} finally {
Init.execute(this::deleteAll);
}
}
public String getPreviewUrl(String fileId, String flag) {
try {
SpiderDebug.log("getPreviewUrl..." + fileId);
tempIds.add(0, copy(fileId));
JSONObject body = new JSONObject();
body.put("file_id", tempIds.get(0));
body.put("drive_id", user.getDriveId());
body.put("category", "live_transcoding");
body.put("url_expire_sec", "14400");
String json = oauth("openFile/getVideoPreviewPlayInfo", body.toString(), true);
SpiderDebug.log(json);
JSONArray taskList = new JSONObject(json).getJSONObject("video_preview_play_info").getJSONArray("live_transcoding_task_list");
return getPreviewQuality(taskList, flag);
} catch (Exception e) {
Init.execute(this::deleteAll);
e.printStackTrace();
return "";
} finally {
Init.execute(this::deleteAll);
}
}
private String getPreviewQuality(JSONArray taskList, String flag) throws Exception {
for (int i = 0; i < taskList.length(); ++i) {
JSONObject task = taskList.getJSONObject(i);
if (task.getString("template_id").equals(quality.get(flag))) {
return task.getString("url");
}
}
return taskList.getJSONObject(0).getString("url");
}
private String copy(String fileId) throws Exception {
SpiderDebug.log("Copy..." + fileId);
String json = "{\"requests\":[{\"body\":{\"file_id\":\"%s\",\"share_id\":\"%s\",\"auto_rename\":true,\"to_parent_file_id\":\"root\",\"to_drive_id\":\"%s\"},\"headers\":{\"Content-Type\":\"application/json\"},\"id\":\"0\",\"method\":\"POST\",\"url\":\"/file/copy\"}],\"resource\":\"file\"}";
json = String.format(json, fileId, shareId, user.getDriveId());
String result = auth("adrive/v2/batch", json, true);
return new JSONObject(result).getJSONArray("responses").getJSONObject(0).getJSONObject("body").getString("file_id");
}
private void deleteAll() {
Iterator<String> iterator = tempIds.iterator();
while (iterator.hasNext()) {
boolean deleted = delete(iterator.next());
if (deleted) iterator.remove();
}
}
private boolean delete(String fileId) {
try {
SpiderDebug.log("Delete..." + fileId);
String json = "{\"requests\":[{\"body\":{\"drive_id\":\"%s\",\"file_id\":\"%s\"},\"headers\":{\"Content-Type\":\"application/json\"},\"id\":\"%s\",\"method\":\"POST\",\"url\":\"/file/delete\"}],\"resource\":\"file\"}";
json = String.format(json, user.getDriveId(), fileId, fileId);
String result = auth("adrive/v2/batch", json, true);
return result.length() == 211;
} catch (Exception ignored) {
return false;
}
}
public Object[] proxySub(Map<String, String> params) {
String fileId = params.get("file_id");
String text = OkHttp.string(getDownloadUrl(fileId), getHeaderAuth());
Object[] result = new Object[3];
result[0] = 200;
result[1] = "application/octet-stream";
result[2] = new ByteArrayInputStream(text.getBytes());
return result;
}
private void getQRCode() {
Data data = Data.objectFrom(OkHttp.string("https://passport.aliyundrive.com/newlogin/qrcode/generate.do?appName=aliyun_drive&fromSite=52&appName=aliyun_drive&appEntrance=web&isMobile=false&lang=zh_CN&returnUrl=&bizParams=&_bx-v=2.2.3")).getContent().getData();
Init.run(() -> showQRCode(data));
}
private void showQRCode(Data data) {
try {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(Utils.dp2px(240), Utils.dp2px(240));
ImageView image = new ImageView(Init.context());
image.setScaleType(ImageView.ScaleType.CENTER_CROP);
image.setImageBitmap(QRCode.getBitmap(data.getCodeContent(), 240, 2));
FrameLayout frame = new FrameLayout(Init.context());
params.gravity = Gravity.CENTER;
frame.addView(image, params);
dialog = new AlertDialog.Builder(Init.getActivity()).setView(frame).setOnDismissListener(this::dismiss).show();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Init.execute(() -> startService(data.getParams()));
Init.show("請使用阿里雲盤 App 掃描二維碼");
} catch (Exception ignored) {
}
}
private void startService(Map<String, String> params) {
service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(() -> {
Data result = Data.objectFrom(OkHttp.post("https://passport.aliyundrive.com/newlogin/qrcode/query.do?appName=aliyun_drive&fromSite=52&_bx-v=2.2.3", params)).getContent().getData();
if (result.hasToken()) setToken(result.getToken());
}, 1, 1, TimeUnit.SECONDS);
}
private void setToken(String value) {
Init.show("請重新進入播放頁");
this.refreshToken = value;
refreshAccessToken();
stopService();
}
private void stopService() {
if (service != null) service.shutdownNow();
Init.run(this::dismiss);
}
private void dismiss(DialogInterface dialog) {
stopService();
}
private void dismiss() {
try {
if (dialog != null) dialog.dismiss();
} catch (Exception ignored) {
}
}
}

View File

@ -1,6 +1,5 @@
package com.github.catvod.bean;
import com.github.catvod.utils.Trans;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
@ -19,9 +18,7 @@ public class Class {
public static List<Class> arrayFrom(String str) {
Type listType = new TypeToken<List<Class>>() {}.getType();
List<Class> items = new Gson().fromJson(str, listType);
for (Class item : items) item.typeName = Trans.get(item.typeName);
return items;
return new Gson().fromJson(str, listType);
}
public Class(String typeId) {
@ -34,7 +31,7 @@ public class Class {
public Class(String typeId, String typeName, String typeFlag) {
this.typeId = typeId;
this.typeName = Trans.get(typeName);
this.typeName = typeName;
this.typeFlag = typeFlag;
}

View File

@ -1,6 +1,5 @@
package com.github.catvod.bean;
import com.github.catvod.utils.Trans;
import com.google.gson.annotations.SerializedName;
import java.util.List;
@ -16,15 +15,10 @@ public class Filter {
public Filter(String key, String name, List<Value> value) {
this.key = key;
this.name = Trans.get(name);
this.name = name;
this.value = value;
}
public void trans() {
name = Trans.get(name);
for (Value item : value) item.n = Trans.get(item.n);
}
public static class Value {
@SerializedName("n")
@ -33,12 +27,12 @@ public class Filter {
private String v;
public Value(String value) {
this.n = Trans.get(value);
this.n = value;
this.v = value;
}
public Value(String n, String v) {
this.n = Trans.get(n);
this.n = n;
this.v = v;
}
}

View File

@ -1,7 +1,5 @@
package com.github.catvod.bean;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
@ -11,7 +9,6 @@ import org.json.JSONObject;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -43,6 +40,10 @@ public class Result {
@SerializedName("total")
private int total;
public static Result objectFrom(String str) {
return new Gson().fromJson(str, Result.class);
}
public static String string(List<Class> classes, List<Vod> list, LinkedHashMap<String, List<Filter>> filters) {
return Result.get().classes(classes).vod(list).filters(filters).string();
}
@ -97,15 +98,12 @@ public class Result {
public Result filters(JSONObject object) {
if (object == null) return this;
Type listType = new TypeToken<LinkedHashMap<String, List<Filter>>>() {
}.getType();
LinkedHashMap<String, List<Filter>> filters = new Gson().fromJson(object.toString(), listType);
for (Map.Entry<String, List<Filter>> entry : filters.entrySet()) for (Filter filter : entry.getValue()) filter.trans();
this.filters = filters;
Type listType = new TypeToken<LinkedHashMap<String, List<Filter>>>() {}.getType();
this.filters = new Gson().fromJson(object.toString(), listType);
return this;
}
public Result header(HashMap<String, String> header) {
public Result header(Map<String, String> header) {
if (header.isEmpty()) return this;
this.header = new Gson().toJson(header);
return this;
@ -156,7 +154,6 @@ public class Result {
return toString();
}
@NonNull
@Override
public String toString() {
return new Gson().toJson(this);

View File

@ -1,6 +1,5 @@
package com.github.catvod.bean;
import com.github.catvod.utils.Trans;
import com.google.gson.annotations.SerializedName;
public class Sub {
@ -19,7 +18,7 @@ public class Sub {
}
public Sub name(String name) {
this.name = Trans.get(name);
this.name = name;
return this;
}

View File

@ -1,6 +1,5 @@
package com.github.catvod.bean;
import com.github.catvod.utils.Trans;
import com.google.gson.annotations.SerializedName;
public class Vod {
@ -48,16 +47,16 @@ public class Vod {
setVodRemarks(vodRemarks);
}
public Vod(String vodId, String vodName, String vodPic, String vodRemarks, String vodTag) {
public Vod(String vodId, String vodName, String vodPic, String vodRemarks, boolean folder) {
setVodId(vodId);
setVodName(vodName);
setVodPic(vodPic);
setVodRemarks(vodRemarks);
setVodTag(vodTag);
setVodTag(folder ? "folder" : "file");
}
public void setTypeName(String typeName) {
this.typeName = Trans.get(typeName);
this.typeName = typeName;
}
public void setVodId(String vodId) {
@ -65,7 +64,7 @@ public class Vod {
}
public void setVodName(String vodName) {
this.vodName = Trans.get(vodName);
this.vodName = vodName;
}
public void setVodPic(String vodPic) {
@ -73,31 +72,35 @@ public class Vod {
}
public void setVodRemarks(String vodRemarks) {
this.vodRemarks = Trans.get(vodRemarks);
this.vodRemarks = vodRemarks;
}
public void setVodYear(String vodYear) {
this.vodYear = Trans.get(vodYear);
this.vodYear = vodYear;
}
public void setVodArea(String vodArea) {
this.vodArea = Trans.get(vodArea);
this.vodArea = vodArea;
}
public void setVodActor(String vodActor) {
this.vodActor = Trans.get(vodActor);
this.vodActor = vodActor;
}
public void setVodDirector(String vodDirector) {
this.vodDirector = Trans.get(vodDirector);
this.vodDirector = vodDirector;
}
public void setVodContent(String vodContent) {
this.vodContent = Trans.get(vodContent);
this.vodContent = vodContent;
}
public String getVodContent() {
return vodContent;
}
public void setVodPlayFrom(String vodPlayFrom) {
this.vodPlayFrom = Trans.get(vodPlayFrom);
this.vodPlayFrom = vodPlayFrom;
}
public void setVodPlayUrl(String vodPlayUrl) {

View File

@ -1,63 +0,0 @@
package com.github.catvod.bean.ali;
import android.text.TextUtils;
import android.widget.ImageView;
public class Auth {
private String refreshToken;
private String accessToken;
private String shareToken;
private String shareId;
private ImageView view;
public String getRefreshToken() {
return TextUtils.isEmpty(refreshToken) ? "" : refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getAccessToken() {
return TextUtils.isEmpty(accessToken) ? "" : accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getShareToken() {
return TextUtils.isEmpty(shareToken) ? "" : shareToken;
}
public void setShareToken(String shareToken) {
this.shareToken = shareToken;
}
public String getShareId() {
return TextUtils.isEmpty(shareId) ? "" : shareId;
}
public void setShareId(String shareId) {
this.shareId = shareId;
}
public ImageView getView() {
return view;
}
public void setView(ImageView view) {
this.view = view;
}
public boolean isEmpty() {
return getAccessToken().isEmpty();
}
public void clean() {
setRefreshToken("");
setAccessToken("");
setShareId("");
}
}

View File

@ -0,0 +1,66 @@
package com.github.catvod.bean.ali;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Biz {
@SerializedName("pds_login_result")
private Biz pdsLoginResult;
@SerializedName("role")
private String role;
@SerializedName("isFirstLogin")
private Boolean isFirstLogin;
@SerializedName("needLink")
private Boolean needLink;
@SerializedName("loginType")
private String loginType;
@SerializedName("nickName")
private String nickName;
@SerializedName("needRpVerify")
private Boolean needRpVerify;
@SerializedName("avatar")
private String avatar;
@SerializedName("accessToken")
private String accessToken;
@SerializedName("userName")
private String userName;
@SerializedName("userId")
private String userId;
@SerializedName("defaultDriveId")
private String defaultDriveId;
@SerializedName("existLink")
private List<?> existLink;
@SerializedName("expiresIn")
private Integer expiresIn;
@SerializedName("expireTime")
private String expireTime;
@SerializedName("requestId")
private String requestId;
@SerializedName("dataPinSetup")
private Boolean dataPinSetup;
@SerializedName("state")
private String state;
@SerializedName("tokenType")
private String tokenType;
@SerializedName("dataPinSaved")
private Boolean dataPinSaved;
@SerializedName("refreshToken")
private String refreshToken;
@SerializedName("status")
private String status;
public static Biz objectFrom(String str) {
return new Gson().fromJson(str, Biz.class);
}
public Biz getPdsLoginResult() {
return pdsLoginResult;
}
public String getRefreshToken() {
return refreshToken;
}
}

View File

@ -0,0 +1,24 @@
package com.github.catvod.bean.ali;
import android.text.TextUtils;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class Code {
@SerializedName("redirectUri")
private String redirectUri;
public static Code objectFrom(String str) {
return new Gson().fromJson(str, Code.class);
}
public String getRedirectUri() {
return TextUtils.isEmpty(redirectUri) ? "" : redirectUri;
}
public String getCode() {
return getRedirectUri().split("code=")[1];
}
}

View File

@ -1,24 +1,34 @@
package com.github.catvod.bean.ali;
import android.util.Base64;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.Map;
public class Data {
@SerializedName(value = "data", alternate = "pds_login_result")
@SerializedName("data")
private Data data;
@SerializedName("content")
private Data content;
@SerializedName("t")
private String t;
@SerializedName("ck")
private String ck;
@SerializedName("codeContent")
private String codeContent;
@SerializedName("refreshToken")
private String refreshToken;
@SerializedName("qrCodeStatus")
private String qrCodeStatus;
@SerializedName("bizExt")
private String bizExt;
public static Data objectFrom(String str) {
try {
return new Gson().fromJson(str, Data.class);
Data data = new Gson().fromJson(str, Data.class);
return data == null ? new Data() : data;
} catch (Exception e) {
return new Data();
}
@ -28,8 +38,8 @@ public class Data {
return data == null ? new Data() : data;
}
public boolean hasToken() {
return getData().getRefreshToken().length() > 0;
public Data getContent() {
return content == null ? new Data() : content;
}
public String getT() {
@ -44,7 +54,35 @@ public class Data {
return codeContent == null ? "" : codeContent;
}
public String getRefreshToken() {
return refreshToken == null ? "" : refreshToken;
public String getQrCodeStatus() {
return qrCodeStatus == null ? "" : qrCodeStatus;
}
public String getBizExt() {
return bizExt == null ? "" : bizExt;
}
public String getToken() {
return Biz.objectFrom(new String(Base64.decode(getBizExt(), Base64.DEFAULT))).getPdsLoginResult().getRefreshToken();
}
public boolean hasToken() {
return getQrCodeStatus().equals("CONFIRMED") && getBizExt().length() > 0;
}
public Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("t", getT());
params.put("ck", getCk());
params.put("appName", "aliyun_drive");
params.put("appEntrance", "web");
params.put("isMobile", "false");
params.put("lang", "zh_CN");
params.put("returnUrl", "");
params.put("fromSite", "52");
params.put("bizParams", "");
params.put("navlanguage", "zh-CN");
params.put("navPlatform", "MacIntel");
return params;
}
}

View File

@ -2,7 +2,7 @@ package com.github.catvod.bean.ali;
import android.text.TextUtils;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
@ -70,7 +70,7 @@ public class Item {
}
public String getSize() {
return size == 0 ? "" : "[" + Misc.getSize(size) + "]";
return size == 0 ? "" : "[" + Utils.getSize(size) + "]";
}
public String getParent() {
@ -85,8 +85,4 @@ public class Item {
public String getDisplayName() {
return TextUtils.join(" ", Arrays.asList(getParent(), getName(), getSize())).trim();
}
public String removeExt() {
return getName().indexOf(".") > 0 ? getName().substring(0, getName().lastIndexOf(".")) : getName();
}
}

View File

@ -0,0 +1,54 @@
package com.github.catvod.bean.ali;
import android.text.TextUtils;
import com.github.catvod.utils.Prefers;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class OAuth {
@SerializedName("token_type")
private String tokenType;
@SerializedName("access_token")
private String accessToken;
@SerializedName("refresh_token")
private String refreshToken;
public static OAuth objectFrom(String str) {
OAuth item = new Gson().fromJson(str, OAuth.class);
return item == null ? new OAuth() : item;
}
public String getTokenType() {
return TextUtils.isEmpty(tokenType) ? "" : tokenType;
}
public String getAccessToken() {
return TextUtils.isEmpty(accessToken) ? "" : accessToken;
}
public String getRefreshToken() {
return TextUtils.isEmpty(refreshToken) ? "" : refreshToken;
}
public String getAuthorization() {
return getTokenType() + " " + getAccessToken();
}
public OAuth clean() {
this.refreshToken = "";
this.accessToken = "";
return this;
}
public OAuth save() {
Prefers.put("aliyundrive_oauth", toString());
return this;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}

View File

@ -0,0 +1,27 @@
package com.github.catvod.bean.ali;
import com.github.catvod.utils.Utils;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Sorter implements Comparator<Item> {
public static void sort(List<Item> items) {
Collections.sort(items, new Sorter());
}
@Override
public int compare(Item o1, Item o2) {
try {
return Integer.compare(getDigit(o1.getDisplayName()), getDigit(o2.getDisplayName()));
} catch (NumberFormatException e) {
return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName());
}
}
private int getDigit(String text) throws NumberFormatException {
return Integer.parseInt(Utils.removeExt(text).replaceAll("\\D+", ""));
}
}

View File

@ -0,0 +1,66 @@
package com.github.catvod.bean.ali;
import android.text.TextUtils;
import com.github.catvod.utils.Prefers;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class User {
@SerializedName("default_drive_id")
private String driveId;
@SerializedName("user_id")
private String userId;
@SerializedName("token_type")
private String tokenType;
@SerializedName("access_token")
private String accessToken;
@SerializedName("refresh_token")
private String refreshToken;
public static User objectFrom(String str) {
User item = new Gson().fromJson(str, User.class);
return item == null ? new User() : item;
}
public String getDriveId() {
return TextUtils.isEmpty(driveId) ? "" : driveId;
}
public String getUserId() {
return TextUtils.isEmpty(userId) ? "" : userId;
}
public String getTokenType() {
return TextUtils.isEmpty(tokenType) ? "" : tokenType;
}
public String getAccessToken() {
return TextUtils.isEmpty(accessToken) ? "" : accessToken;
}
public String getRefreshToken() {
return TextUtils.isEmpty(refreshToken) ? "" : refreshToken;
}
public String getAuthorization() {
return getTokenType() + " " + getAccessToken();
}
public User clean() {
this.refreshToken = "";
this.accessToken = "";
return this;
}
public User save() {
Prefers.put("aliyundrive_user", toString());
return this;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}

View File

@ -1,5 +1,6 @@
package com.github.catvod.bean.alist;
import android.net.Uri;
import android.text.TextUtils;
import com.github.catvod.bean.Class;
@ -16,6 +17,8 @@ public class Drive {
@SerializedName("drives")
private List<Drive> drives;
@SerializedName("vodPic")
private String vodPic;
@SerializedName("name")
private String name;
@SerializedName("server")
@ -24,6 +27,8 @@ public class Drive {
private String password;
@SerializedName("version")
private int version;
@SerializedName("path")
private String path;
public static Drive objectFrom(String str) {
return new Gson().fromJson(str, Drive.class);
@ -37,6 +42,10 @@ public class Drive {
this.name = name;
}
public String getVodPic() {
return TextUtils.isEmpty(vodPic) ? "https://s1.ax1x.com/2023/04/03/pp4F4bT.png" : vodPic;
}
public String getName() {
return TextUtils.isEmpty(name) ? "" : name;
}
@ -57,6 +66,14 @@ public class Drive {
this.version = version;
}
public String getPath() {
return TextUtils.isEmpty(path) ? "" : path;
}
public void setPath(String path) {
this.path = TextUtils.isEmpty(path) ? "" : path;
}
public boolean isNew() {
return getVersion() == 3;
}
@ -65,24 +82,29 @@ public class Drive {
return new Class(getName(), getName(), "1");
}
public String getHost() {
return getServer().replace(getPath(), "");
}
public String settingsApi() {
return getServer() + "/api/public/settings";
return getHost() + "/api/public/settings";
}
public String listApi() {
return getServer() + (isNew() ? "/api/fs/list" : "/api/public/path");
return getHost() + (isNew() ? "/api/fs/list" : "/api/public/path");
}
public String getApi() {
return getServer() + (isNew() ? "/api/fs/get" : "/api/public/path");
return getHost() + (isNew() ? "/api/fs/get" : "/api/public/path");
}
public String searchApi() {
return getServer() + (isNew() ? "/api/fs/search" : "/api/public/search");
return getHost() + (isNew() ? "/api/fs/search" : "/api/public/search");
}
public Drive check() {
if (getVersion() == 0) setVersion(OkHttp.string(settingsApi()).contains("v2.") ? 2 : 3);
if (path == null) setPath(Uri.parse(getServer()).getPath());
if (version == 0) setVersion(OkHttp.string(settingsApi()).contains("v2.") ? 2 : 3);
return this;
}

View File

@ -3,7 +3,7 @@ package com.github.catvod.bean.alist;
import android.text.TextUtils;
import com.github.catvod.bean.Vod;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
@ -99,6 +99,7 @@ public class Item {
}
public boolean ignore(boolean isNew) {
if (getName().endsWith(".ts")) return false;
if (isNew) return getType() == 0 || getType() == 4;
return getType() == 0 || getType() == 2 || getType() == 5;
}
@ -111,23 +112,19 @@ public class Item {
return id + getPath() + "/" + getName();
}
public String getPic() {
return getThumb().isEmpty() && isFolder() ? "http://img1.3png.com/281e284a670865a71d91515866552b5f172b.png" : getThumb();
public String getPic(String pic) {
return getThumb().isEmpty() && isFolder() ? pic : getThumb();
}
public String getRemark() {
return Misc.getSize(getSize()) + (isFolder() ? " 文件夹" : "");
return Utils.getSize(getSize());
}
public String getVodTag() {
return isFolder() ? "folder" : "file";
public Vod getVod(String id, String pic) {
return new Vod(getVodId(id), getName(), getPic(pic), getRemark(), isFolder());
}
public Vod getVod(String id) {
return new Vod(getVodId(id), getName(), getPic(), getRemark(), getVodTag());
}
public Vod getVod(Drive drive) {
return new Vod(getVodId(drive.getName()), getName(), getPic(), drive.getName(), getVodTag());
public Vod getVod(Drive drive, String pic) {
return new Vod(getVodId(drive.getName()), getName(), getPic(pic), drive.getName(), isFolder());
}
}

View File

@ -15,7 +15,7 @@ public class Item {
private String insertTime;
public String getTitle() {
return TextUtils.isEmpty(title) ? "" : title;
return TextUtils.isEmpty(title) ? "" : title.replaceAll("<em>", "").replaceAll("</em>", "");
}
public String getPageUrl() {
@ -26,8 +26,9 @@ public class Item {
return TextUtils.isEmpty(insertTime) ? "" : insertTime;
}
public boolean isAli() {
return getPageUrl().contains("www.aliyundrive.com");
public Item url(String pageUrl) {
this.pageUrl = pageUrl;
return this;
}
public Vod getVod() {

View File

@ -0,0 +1,107 @@
package com.github.catvod.bean.webdav;
import android.net.Uri;
import android.text.TextUtils;
import com.github.catvod.bean.Class;
import com.github.catvod.bean.Vod;
import com.github.catvod.utils.Utils;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.thegrizzlylabs.sardineandroid.DavResource;
import com.thegrizzlylabs.sardineandroid.Sardine;
import com.thegrizzlylabs.sardineandroid.impl.OkHttpSardine;
import java.util.ArrayList;
import java.util.List;
public class Drive {
@SerializedName("vodPic")
private String vodPic;
@SerializedName("drives")
private List<Drive> drives;
@SerializedName("name")
private String name;
@SerializedName("server")
private String server;
@SerializedName("user")
private String user;
@SerializedName("pass")
private String pass;
@SerializedName("path")
private String path;
@SerializedName("webdav")
private Sardine webdav;
public static Drive objectFrom(String str) {
return new Gson().fromJson(str, Drive.class);
}
public Drive(String name) {
this.name = name;
}
public List<Drive> getDrives() {
return drives == null ? new ArrayList<>() : drives;
}
public String getVodPic() {
return TextUtils.isEmpty(vodPic) ? "" : vodPic;
}
public String getName() {
return TextUtils.isEmpty(name) ? "" : name;
}
public String getServer() {
return TextUtils.isEmpty(server) ? "" : server;
}
public String getUser() {
return TextUtils.isEmpty(user) ? "" : user;
}
public String getPass() {
return TextUtils.isEmpty(pass) ? "" : pass;
}
public String getPath() {
return TextUtils.isEmpty(path) ? "" : path;
}
public void setPath(String path) {
this.path = TextUtils.isEmpty(path) ? "" : path;
}
public String getHost() {
return getServer().replace(getPath(), "");
}
public Sardine getWebdav() {
if (webdav == null) init();
return webdav;
}
public Class toType() {
return new Class(getName(), getName(), "1");
}
private void init() {
webdav = new OkHttpSardine();
webdav.setCredentials(getUser(), getPass());
setPath(Uri.parse(getServer()).getPath());
}
public Vod vod(DavResource item, String vodPic) {
return new Vod(getName() + item.getPath(), item.getName(), vodPic, Utils.getSize(item.getContentLength()), item.isDirectory());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Drive)) return false;
Drive it = (Drive) obj;
return getName().equals(it.getName());
}
}

View File

@ -0,0 +1,37 @@
package com.github.catvod.bean.webdav;
import com.thegrizzlylabs.sardineandroid.DavResource;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Sorter implements Comparator<DavResource> {
private final String type;
private final String order;
public static void sort(String type, String order, List<DavResource> items) {
Collections.sort(items, new Sorter(type, order));
}
public Sorter(String type, String order) {
this.type = type;
this.order = order;
}
@Override
public int compare(DavResource o1, DavResource o2) {
boolean asc = order.equals("asc");
switch (type) {
case "name":
return asc ? o1.getName().compareTo(o2.getName()) : o2.getName().compareTo(o1.getName());
case "size":
return asc ? Long.compare(o1.getContentLength(), o2.getContentLength()) : Long.compare(o2.getContentLength(), o1.getContentLength());
case "date":
return asc ? o1.getModified().compareTo(o2.getModified()) : o2.getModified().compareTo(o1.getModified());
default:
return -1;
}
}
}

View File

@ -1,4 +1,4 @@
package com.github.catvod.xpath;
package com.github.catvod.bean.xpath;
import com.github.catvod.crawler.SpiderDebug;
@ -9,7 +9,7 @@ import java.util.LinkedHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class XPathRule {
public class Rule {
/**
* user-agent
*/
@ -325,10 +325,10 @@ public class XPathRule {
return src;
}
public static XPathRule fromJson(String json) {
public static Rule fromJson(String json) {
try {
JSONObject jsonObj = new JSONObject(json);
XPathRule rule = new XPathRule();
Rule rule = new Rule();
rule.ua = jsonObj.optString("ua");
rule.homeUrl = jsonObj.optString("homeUrl").trim();
rule.cateNode = jsonObj.optString("cateNode").trim();

View File

@ -2,13 +2,17 @@ package com.github.catvod.net;
import com.github.catvod.crawler.Spider;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Dns;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttp {
@ -32,10 +36,10 @@ public class OkHttp {
}
public static OkHttpClient.Builder getBuilder() {
return new OkHttpClient.Builder().dns(safeDns()).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).connectTimeout(30, TimeUnit.SECONDS).retryOnConnectionFailure(true).hostnameVerifier(SSLSocketFactoryCompat.hostnameVerifier).sslSocketFactory(new SSLSocketFactoryCompat(), SSLSocketFactoryCompat.trustAllCert);
return new OkHttpClient.Builder().dns(safeDns()).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).connectTimeout(30, TimeUnit.SECONDS).hostnameVerifier(SSLSocketFactoryCompat.hostnameVerifier).sslSocketFactory(new SSLSocketFactoryCompat(), SSLSocketFactoryCompat.trustAllCert);
}
private static OkHttpClient client() {
public static OkHttpClient client() {
return get().client;
}
@ -51,6 +55,10 @@ public class OkHttp {
}
}
public static Response newCall(String url, Map<String, String> header) throws IOException {
return client().newCall(new Request.Builder().url(url).headers(Headers.of(header)).build()).execute();
}
public static void stringNoRedirect(String url, Map<String, String> header, Map<String, List<String>> respHeader) {
string(noRedirect(), GET, url, null, null, header, respHeader);
}

View File

@ -2,7 +2,7 @@ package com.github.catvod.net;
import android.text.TextUtils;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import java.io.IOException;
import java.util.List;
@ -50,12 +50,12 @@ class OkRequest {
}
private void getInstance() {
Request.Builder builder = new Request.Builder().url(url);
Request.Builder builder = new Request.Builder();
if (method.equals(OkHttp.GET) && params != null) setParams();
if (method.equals(OkHttp.POST)) builder.post(getRequestBody());
if (header != null) for (String key : header.keySet()) builder.addHeader(key, header.get(key));
if (tag != null) builder.tag(tag);
request = builder.build();
request = builder.url(url).build();
}
private RequestBody getRequestBody() {
@ -68,7 +68,7 @@ class OkRequest {
private void setParams() {
url = url + "?";
for (String key : params.keySet()) url = url.concat(key + "=" + params.get(key) + "&");
url = Misc.substring(url);
url = Utils.substring(url);
}
public String execute(OkHttpClient client) {

View File

@ -1,65 +0,0 @@
package com.github.catvod.parser;
import android.util.Base64;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
public class JsonBasic {
public static JSONObject parse(LinkedHashMap<String, String> jx, String url) {
SpiderDebug.log("Load Json Parse Basic...");
if (jx.isEmpty()) return new JSONObject();
Set<String> jxNames = jx.keySet();
for (String jxName : jxNames) {
String parseUrl = jx.get(jxName);
HashMap<String, String> reqHeaders = getReqHeader(parseUrl);
try {
String realUrl = reqHeaders.get("url");
reqHeaders.remove("url");
SpiderDebug.log(realUrl + url);
String json = OkHttp.string(realUrl + url, reqHeaders);
JSONObject taskResult = Misc.jsonParse(url, json);
if (taskResult == null) continue;
taskResult.put("jxFrom", jxName);
SpiderDebug.log(taskResult.toString());
return taskResult;
} catch (Exception ignored) {
}
}
return new JSONObject();
}
public static HashMap<String, String> getReqHeader(String url) {
HashMap<String, String> reqHeaders = new HashMap<>();
reqHeaders.put("url", url);
if (!url.contains("cat_ext")) return reqHeaders;
try {
int start = url.indexOf("cat_ext=");
int end = url.indexOf("&", start);
String ext = url.substring(start + 8, end);
ext = new String(Base64.decode(ext, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP));
String newUrl = url.substring(0, start) + url.substring(end + 1);
JSONObject jsonObject = new JSONObject(ext);
if (jsonObject.has("header")) {
JSONObject headerJson = jsonObject.optJSONObject("header");
Iterator<String> keys = headerJson.keys();
while (keys.hasNext()) {
String key = keys.next();
reqHeaders.put(key, headerJson.optString(key, ""));
}
}
reqHeaders.put("url", newUrl);
} catch (Exception ignored) {
}
return reqHeaders;
}
}

View File

@ -1,71 +0,0 @@
package com.github.catvod.parser;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class JsonParallel {
private static final String ParseOKTag = "p_json_parse";
public static JSONObject parse(LinkedHashMap<String, String> jx, String url) {
if (jx.isEmpty()) return new JSONObject();
ExecutorService service = Executors.newFixedThreadPool(3);
CompletionService<JSONObject> completionService = new ExecutorCompletionService<>(service);
List<Future<JSONObject>> futures = new ArrayList<>();
Set<String> jxNames = jx.keySet();
for (String jxName : jxNames) {
String parseUrl = jx.get(jxName);
futures.add(completionService.submit(() -> {
try {
HashMap<String, String> reqHeaders = JsonBasic.getReqHeader(parseUrl);
String realUrl = reqHeaders.get("url");
reqHeaders.remove("url");
SpiderDebug.log(realUrl + url);
String json = OkHttp.string(realUrl + url, ParseOKTag, reqHeaders);
JSONObject taskResult = Misc.jsonParse(url, json);
taskResult.put("jxFrom", jxName);
SpiderDebug.log(taskResult.toString());
return taskResult;
} catch (Exception ignored) {
return null;
}
}));
}
JSONObject pTaskResult = null;
for (int i = 0; i < futures.size(); ++i) {
try {
Future<JSONObject> completed = completionService.take();
pTaskResult = completed.get();
if (pTaskResult != null) {
OkHttp.cancel(ParseOKTag);
for (int j = 0; j < futures.size(); j++) {
try {
futures.get(j).cancel(true);
} catch (Exception e) {
SpiderDebug.log(e);
}
}
futures.clear();
break;
}
} catch (Exception ignored) {
}
}
service.shutdownNow();
return pTaskResult != null ? pTaskResult : new JSONObject();
}
}

View File

@ -1,35 +0,0 @@
package com.github.catvod.parser;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Set;
public class JsonSequence {
public static JSONObject parse(LinkedHashMap<String, String> jx, String url) {
if (jx.isEmpty()) return new JSONObject();
Set<String> jxNames = jx.keySet();
for (String jxName : jxNames) {
try {
String parseUrl = jx.get(jxName);
HashMap<String, String> reqHeaders = JsonBasic.getReqHeader(parseUrl);
String realUrl = reqHeaders.get("url");
reqHeaders.remove("url");
SpiderDebug.log(realUrl + url);
String json = OkHttp.string(realUrl + url, reqHeaders);
JSONObject taskResult = Misc.jsonParse(url, json);
if (taskResult == null) continue;
taskResult.put("jxFrom", jxName);
return taskResult;
} catch (Exception ignored) {
}
}
return new JSONObject();
}
}

View File

@ -1,88 +0,0 @@
package com.github.catvod.parser;
import android.util.Base64;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class MixDemo {
private static final HashMap<String, ArrayList<String>> flagWebJx = new HashMap<>();
private static HashMap<String, ArrayList<String>> configs = null;
private static void setConfigs(LinkedHashMap<String, HashMap<String, String>> jx) {
configs = new HashMap<>();
for (String key : jx.keySet()) {
HashMap<String, String> parseBean = jx.get(key);
String type = parseBean.get("type");
if (type.equals("1") || type.equals("0")) {
try {
JSONArray flags = new JSONObject(parseBean.get("ext")).getJSONArray("flag");
for (int j = 0; j < flags.length(); j++) {
String flagKey = flags.getString(j);
ArrayList<String> flagJx = configs.get(flagKey);
if (flagJx == null) {
flagJx = new ArrayList<>();
configs.put(flagKey, flagJx);
}
flagJx.add(key);
}
} catch (Exception ignored) {
}
}
}
}
public static JSONObject parse(LinkedHashMap<String, HashMap<String, String>> jx, String nameMe, String flag, String url) {
try {
if (configs == null) setConfigs(jx);
LinkedHashMap<String, String> jsonJx = new LinkedHashMap<>();
ArrayList<String> webJx = new ArrayList<>();
ArrayList<String> flagJx = configs.get(flag);
if (flagJx != null && !flagJx.isEmpty()) {
for (int i = 0; i < flagJx.size(); i++) {
String key = flagJx.get(i);
HashMap<String, String> parseBean = jx.get(key);
String type = parseBean.get("type");
if (type.equals("1")) {
jsonJx.put(key, mixUrl(parseBean.get("url"), parseBean.get("ext")));
} else if (type.equals("0")) {
webJx.add(parseBean.get("url"));
}
}
} else {
for (String key : jx.keySet()) {
HashMap<String, String> parseBean = jx.get(key);
String type = parseBean.get("type");
if (type.equals("1")) {
jsonJx.put(key, mixUrl(parseBean.get("url"), parseBean.get("ext")));
} else if (type.equals("0")) {
webJx.add(parseBean.get("url"));
}
}
}
if (!webJx.isEmpty()) flagWebJx.put(flag, webJx);
JSONObject jsonResult = JsonParallel.parse(jsonJx, url);
if (jsonResult.has("url")) return jsonResult;
if (!webJx.isEmpty()) {
JSONObject webResult = new JSONObject();
webResult.put("url", "proxy://do=parseMix&flag=" + flag + "&url=" + Base64.encodeToString(url.getBytes(), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP));
webResult.put("parse", 1);
return webResult;
}
} catch (Exception ignored) {
}
return new JSONObject();
}
private static String mixUrl(String url, String ext) {
if (ext.trim().isEmpty()) return url;
int index = url.indexOf("?");
if (index == -1) return url;
return url.substring(0, index + 1) + "cat_ext=" + Base64.encodeToString(ext.getBytes(), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP) + "&" + url.substring(index + 1);
}
}

View File

@ -21,8 +21,7 @@ import com.github.catvod.bean.alist.Item;
import com.github.catvod.bean.alist.Sorter;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Trans;
import com.github.catvod.utils.Utils;
import org.json.JSONObject;
@ -38,6 +37,7 @@ import java.util.concurrent.CountDownLatch;
public class AList extends Spider {
private List<Drive> drives;
private String vodPic;
private String ext;
private Activity mActivity;
@ -51,7 +51,9 @@ public class AList extends Spider {
private void fetchRule() {
if (drives != null && !drives.isEmpty()) return;
if (ext.startsWith("http")) ext = OkHttp.string(ext);
drives = Drive.objectFrom(ext).getDrives();
Drive drive = Drive.objectFrom(ext);
drives = drive.getDrives();
vodPic = drive.getVodPic();
}
private Drive getDrive(String name) {
@ -152,8 +154,8 @@ public class AList extends Spider {
Sorter.sort(type, order, folders);
Sorter.sort(type, order, files);
}
for (Item item : folders) list.add(item.getVod(tid));
for (Item item : files) list.add(item.getVod(tid));
for (Item item : folders) list.add(item.getVod(tid, vodPic));
for (Item item : files) list.add(item.getVod(tid, vodPic));
return Result.get().vod(list).page().string();
}
@ -170,15 +172,15 @@ public class AList extends Spider {
List<String> playUrls = new ArrayList<>();
for (Item item : parents) {
if (item.isMedia(drive.isNew())) {
playUrls.add(Trans.get(item.getName()) + "$" + item.getVodId(path) + findSubs(path, parents));
playUrls.add(item.getName() + "$" + item.getVodId(path) + findSubs(path, parents));
}
}
Vod vod = new Vod();
vod.setVodId(id);
vod.setVodName(name);
vod.setVodPic(vodPic);
vod.setVodPlayFrom(key);
vod.setVodPlayUrl(TextUtils.join("#", playUrls));
vod.setVodPic("http://img1.3png.com/281e284a670865a71d91515866552b5f172b.png");
return Result.string(vod);
}
@ -204,8 +206,8 @@ public class AList extends Spider {
String path = id.contains("/") ? id.substring(id.indexOf("/")) : "";
Drive drive = getDrive(key);
JSONObject params = new JSONObject();
params.put("path", path);
params.put("password", drive.getPassword());
params.put("path", path.startsWith(drive.getPath()) ? path : drive.getPath() + path);
String response = OkHttp.postJson(drive.getApi(), params.toString());
return Item.objectFrom(getDetailJson(drive.isNew(), response));
} catch (Exception e) {
@ -219,8 +221,8 @@ public class AList extends Spider {
String path = id.contains("/") ? id.substring(id.indexOf("/")) : "";
Drive drive = getDrive(key);
JSONObject params = new JSONObject();
params.put("path", path);
params.put("password", drive.getPassword());
params.put("path", path.startsWith(drive.getPath()) ? path : drive.getPath() + path);
String response = OkHttp.postJson(drive.listApi(), params.toString());
List<Item> items = Item.arrayFrom(getListJson(drive.isNew(), response));
Iterator<Item> iterator = items.iterator();
@ -235,7 +237,7 @@ public class AList extends Spider {
try {
String response = OkHttp.postJson(drive.searchApi(), drive.params(keyword));
List<Item> items = Item.arrayFrom(getSearchJson(drive.isNew(), response));
for (Item item : items) if (!item.ignore(drive.isNew())) list.add(item.getVod(drive));
for (Item item : items) if (!item.ignore(drive.isNew())) list.add(item.getVod(drive, vodPic));
} catch (Exception ignored) {
} finally {
cd.countDown();
@ -268,7 +270,7 @@ public class AList extends Spider {
private String findSubs(String path, List<Item> items) {
StringBuilder sb = new StringBuilder();
for (Item item : items) if (Misc.isSub(item.getExt())) sb.append("~~~").append(item.getName()).append("@@@").append(item.getExt()).append("@@@").append(item.getVodId(path));
for (Item item : items) if (Utils.isSub(item.getExt())) sb.append("~~~").append(item.getName()).append("@@@").append(item.getExt()).append("@@@").append(item.getVodId(path));
return sb.toString();
}

View File

@ -1,346 +1,49 @@
package com.github.catvod.spider;
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.content.Context;
import com.github.catvod.ali.API;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Sub;
import com.github.catvod.bean.Vod;
import com.github.catvod.bean.ali.Auth;
import com.github.catvod.bean.ali.Data;
import com.github.catvod.bean.ali.Item;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Prefers;
import com.github.catvod.utils.QRCode;
import com.github.catvod.utils.Trans;
import com.google.gson.JsonObject;
import com.github.catvod.crawler.Spider;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author ColaMint & Adam & FongMi
*/
public class Ali {
public class Ali extends Spider {
private final Pattern pattern = Pattern.compile("www.aliyundrive.com/s/([^/]+)(/folder/([^/]+))?");
private ScheduledExecutorService service;
private final Auth auth;
public static final Pattern pattern = Pattern.compile("www.aliyundrive.com/s/([^/]+)(/folder/([^/]+))?");
private static class Loader {
static volatile Ali INSTANCE = new Ali();
}
public static Ali get() {
return Loader.INSTANCE;
}
public Ali() {
this.auth = new Auth();
}
public Ali init(String token) {
auth.setRefreshToken(Prefers.getString("token", token));
return this;
}
private HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("Referer", "https://www.aliyundrive.com/");
return headers;
}
private HashMap<String, String> getAuthHeader() {
HashMap<String, String> headers = getHeaders();
headers.put("authorization", auth.getAccessToken());
headers.put("x-share-token", auth.getShareToken());
return headers;
}
private String post(String url, JSONObject body) {
url = url.startsWith("https") ? url : "https://api.aliyundrive.com/" + url;
return OkHttp.postJson(url, body.toString(), getHeaders());
}
private String postAuth(String url, JSONObject body) {
url = url.startsWith("https") ? url : "https://api.aliyundrive.com/" + url;
String result = OkHttp.postJson(url, body.toString(), getAuthHeader());
if (check401(result)) return postAuth(url, body);
return result;
}
private boolean check401(String result) {
if (result.contains("AccessTokenInvalid")) return refreshAccessToken();
if (result.contains("ShareLinkTokenInvalid")) return refreshShareToken();
if (result.contains("InvalidParameterNotMatch")) return refreshShareToken();
return false;
@Override
public void init(Context context, String extend) {
API.get().setRefreshToken(extend);
}
@Override
public String detailContent(List<String> ids) throws Exception {
String url = ids.get(0).trim();
Matcher matcher = pattern.matcher(url);
if (!matcher.find()) return "";
String shareId = matcher.group(1);
String fileId = matcher.groupCount() == 3 ? matcher.group(3) : "";
auth.setShareId(shareId); refreshShareToken();
return Result.string(getVod(url, fileId));
API.get().setShareId(shareId);
return Result.string(API.get().getVod(url, fileId));
}
public String playerContent(String flag, String id) {
@Override
public String playerContent(String flag, String id, List<String> vipFlags) {
String[] ids = id.split("\\+");
if (auth.isEmpty()) refreshAccessToken();
if (flag.equals("原畫")) {
return Result.get().url(getDownloadUrl(ids[0])).subs(getSub(ids)).header(getHeaders()).string();
} else {
return Result.get().url(getPreviewUrl(ids[0])).subs(getSub(ids)).header(getHeaders()).string();
}
String url = flag.equals("原畫") ? API.get().getDownloadUrl(ids[0]) : API.get().getPreviewUrl(ids[0], flag);
return Result.get().url(url).subs(API.get().getSub(ids)).header(API.get().getHeader()).parse(0).string();
}
private Vod getVod(String url, String fileId) throws Exception {
JSONObject body = new JSONObject();
body.put("share_id", auth.getShareId());
String json = post("adrive/v3/share_link/get_share_by_anonymous", body);
JSONObject object = new JSONObject(json);
List<Item> files = new ArrayList<>();
LinkedHashMap<String, List<String>> subMap = new LinkedHashMap<>();
listFiles(new Item(getParentFileId(fileId, object)), files, subMap);
List<String> playUrls = new ArrayList<>();
for (Item file : files) playUrls.add(Trans.get(file.getDisplayName()) + "$" + file.getFileId() + findSubs(file.getName(), subMap));
List<String> sourceUrls = new ArrayList<>();
sourceUrls.add(TextUtils.join("#", playUrls));
sourceUrls.add(TextUtils.join("#", playUrls));
Vod vod = new Vod();
vod.setVodId(url);
vod.setVodContent(url);
vod.setVodPic(object.getString("avatar"));
vod.setVodName(object.getString("share_name"));
vod.setVodPlayUrl(TextUtils.join("$$$", sourceUrls));
vod.setVodPlayFrom("原畫$$$普畫");
vod.setTypeName("阿里雲盤");
return vod;
}
private void listFiles(Item folder, List<Item> files, LinkedHashMap<String, List<String>> subMap) throws Exception {
listFiles(folder, files, subMap, "");
}
private void listFiles(Item parent, List<Item> files, LinkedHashMap<String, List<String>> subMap, String marker) throws Exception {
JSONObject body = new JSONObject();
List<Item> folders = new ArrayList<>();
body.put("limit", 200);
body.put("share_id", auth.getShareId());
body.put("parent_file_id", parent.getFileId());
body.put("order_by", "name");
body.put("order_direction", "ASC");
if (marker.length() > 0) body.put("marker", marker);
Item item = Item.objectFrom(postAuth("adrive/v3/file/list", body));
for (Item file : item.getItems()) {
if (file.getType().equals("folder")) {
folders.add(file);
} else if (file.getCategory().equals("video") || file.getCategory().equals("audio")) {
files.add(file.parent(parent.getName()));
} else if (Misc.isSub(file.getExt())) {
String key = file.removeExt();
if (!subMap.containsKey(key)) subMap.put(key, new ArrayList<>());
subMap.get(key).add(key + "@@@" + file.getExt() + "@@@" + file.getFileId());
}
}
if (item.getNextMarker().length() > 0) {
listFiles(parent, files, subMap, item.getNextMarker());
}
for (Item folder : folders) {
listFiles(folder, files, subMap);
}
}
private String getParentFileId(String fileId, JSONObject shareInfo) throws Exception {
JSONArray array = shareInfo.getJSONArray("file_infos");
if (!TextUtils.isEmpty(fileId)) return fileId;
if (array.length() == 0) return "";
JSONObject fileInfo = array.getJSONObject(0);
if (fileInfo.getString("type").equals("folder")) return fileInfo.getString("file_id");
if (fileInfo.getString("type").equals("file") && fileInfo.getString("category").equals("video")) return "root";
return "";
}
private boolean refreshAccessToken() {
try {
JSONObject body = new JSONObject();
String token = auth.getRefreshToken();
if (token.startsWith("http")) token = OkHttp.string(token).replaceAll("[^A-Za-z0-9]", "");
body.put("refresh_token", token);
body.put("grant_type", "refresh_token");
JSONObject object = new JSONObject(post("https://auth.aliyundrive.com/v2/account/token", body));
auth.setAccessToken(object.getString("token_type") + " " + object.getString("access_token"));
auth.setRefreshToken(object.getString("refresh_token"));
return true;
} catch (Exception e) {
checkService();
auth.clean();
getQRCode();
return true;
} finally {
while (auth.isEmpty()) SystemClock.sleep(250);
}
}
private boolean refreshShareToken() {
try {
JSONObject body = new JSONObject();
body.put("share_id", auth.getShareId());
body.put("share_pwd", "");
JSONObject object = new JSONObject(post("v2/share_link/get_share_token", body));
auth.setShareToken(object.getString("share_token"));
return true;
} catch (Exception e) {
Init.show("來晚啦,該分享已失效。");
e.printStackTrace();
return false;
}
}
private String findSubs(String name, Map<String, List<String>> subMap) {
name = name.substring(0, name.lastIndexOf("."));
List<String> subs = subMap.get(name);
if (subs != null && subs.size() > 0) return combineSubs(subs);
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<String>> entry : subMap.entrySet()) sb.append(combineSubs(entry.getValue()));
return sb.toString();
}
private String combineSubs(List<String> subs) {
StringBuilder sb = new StringBuilder();
for (String sub : subs) sb.append("+").append(sub);
return sb.toString();
}
private List<Sub> getSub(String[] ids) {
List<Sub> sub = new ArrayList<>();
for (String text : ids) {
if (!text.contains("@@@")) continue;
String[] split = text.split("@@@");
String name = split[0];
String ext = split[1];
String url = Proxy.getUrl() + "?do=ali&type=sub" + "&file_id=" + split[2];
sub.add(Sub.create().name(name).ext(ext).url(url));
}
return sub;
}
private String getPreviewQuality(JSONArray taskList) throws Exception {
for (String templateId : Arrays.asList("FHD", "HD", "SD", "LD")) {
for (int i = 0; i < taskList.length(); ++i) {
JSONObject task = taskList.getJSONObject(i);
if (task.getString("template_id").equals(templateId)) {
return task.getString("url");
}
}
}
return taskList.getJSONObject(0).getString("url");
}
private String getPreviewUrl(String fileId) {
try {
JSONObject body = new JSONObject();
body.put("file_id", fileId);
body.put("share_id", auth.getShareId());
body.put("template_id", "");
body.put("category", "live_transcoding");
String json = postAuth("v2/file/get_share_link_video_preview_play_info", body);
JSONArray taskList = new JSONObject(json).getJSONObject("video_preview_play_info").getJSONArray("live_transcoding_task_list");
Map<String, List<String>> respHeaders = new HashMap<>();
OkHttp.stringNoRedirect(getPreviewQuality(taskList), getHeaders(), respHeaders);
return OkHttp.getRedirectLocation(respHeaders);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
private String getDownloadUrl(String fileId) {
try {
JSONObject body = new JSONObject();
body.put("file_id", fileId);
body.put("share_id", auth.getShareId());
body.put("expire_sec", 600);
String json = postAuth("v2/file/get_share_link_download_url", body);
String url = new JSONObject(json).optString("download_url");
Map<String, List<String>> respHeaders = new HashMap<>();
OkHttp.stringNoRedirect(url, getHeaders(), respHeaders);
return OkHttp.getRedirectLocation(respHeaders);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public Object[] vod(Map<String, String> params) {
String fileId = params.get("file_id");
String text = OkHttp.string(getDownloadUrl(fileId), getAuthHeader());
Object[] result = new Object[3];
result[0] = 200;
result[1] = "application/octet-stream";
result[2] = new ByteArrayInputStream(text.getBytes());
return result;
}
private void checkService() {
if (service != null) service.shutdownNow();
if (auth.getView() != null) Init.run(() -> Misc.removeView(auth.getView()));
}
private void getQRCode() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
Data data = Data.objectFrom(OkHttp.string("https://easy-token.cooluc.com/qr", headers));
if (data != null) Init.run(() -> showCode(data));
service = Executors.newScheduledThreadPool(1);
if (data != null) service.scheduleAtFixedRate(() -> {
JsonObject params = new JsonObject();
params.addProperty("t", data.getData().getT());
params.addProperty("ck", data.getData().getCk());
Data result = Data.objectFrom(OkHttp.postJson("https://easy-token.cooluc.com/ck", params.toString(), headers));
if (result.hasToken()) setToken(result.getData().getRefreshToken());
}, 1, 1, TimeUnit.SECONDS);
}
private void setToken(String value) {
Prefers.put("token", value);
Init.show("請重新進入播放頁");
auth.setRefreshToken(value);
checkService();
}
private void showCode(Data data) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
Misc.addView(create(data.getData().getCodeContent()), params);
Init.show("請使用阿里雲盤 App 掃描二維碼");
}
private ImageView create(String value) {
ImageView view = new ImageView(Init.context());
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setImageBitmap(QRCode.getBitmap(value, 250, 2));
auth.setView(view);
return view;
public static Object[] vod(Map<String, String> params) {
String type = params.get("type");
if (type.equals("sub")) return API.get().proxySub(params);
return null;
}
}

View File

@ -1,15 +1,23 @@
package com.github.catvod.spider;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.text.TextUtils;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.github.catvod.bean.Class;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Trans;
import com.github.catvod.utils.Prefers;
import com.github.catvod.utils.QRCode;
import com.github.catvod.utils.Utils;
import org.json.JSONArray;
import org.json.JSONObject;
@ -19,37 +27,40 @@ import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author ColaMint & FongMi
*/
public class Bili extends Spider {
private static final String url = "https://www.bilibili.com";
private ScheduledExecutorService service;
private HashMap<String, String> header;
private AlertDialog dialog;
private JSONObject ext;
private String extend;
private boolean login;
private String getCookie(String cookie) {
if (TextUtils.isEmpty(cookie)) return "buvid3=84B0395D-C9F2-C490-E92E-A09AB48FE26E71636infoc";
if (cookie.startsWith("http")) return OkHttp.string(cookie).replace("\n", "");
return cookie;
String cache = Prefers.getString("BiliCookie");
if (!TextUtils.isEmpty(cache)) return cache;
if (cookie.startsWith("http")) return OkHttp.string(cookie).replace("\n", "").trim();
return cookie.isEmpty() ? "buvid3=84B0395D-C9F2-C490-E92E-A09AB48FE26E71636infoc" : cookie;
}
private void setHeader() throws Exception {
header.put("cookie", getCookie(ext.getString("cookie")));
header.put("User-Agent", Misc.CHROME);
header.put("Referer", url);
}
private void fetchExt() {
String result = OkHttp.string(extend);
if (!TextUtils.isEmpty(result)) extend = result;
private void setHeader() {
header.put("cookie", getCookie(ext.optString("cookie")));
header.put("Referer", "https://www.bilibili.com");
header.put("User-Agent", Utils.CHROME);
}
private void fetchRule() throws Exception {
if (header.containsKey("cookie") && header.get("cookie").length() > 0) return;
if (extend.startsWith("http")) fetchExt();
if (extend.startsWith("http")) extend = OkHttp.string(extend);
ext = new JSONObject(extend);
setHeader();
}
@ -100,6 +111,7 @@ public class Bili extends Spider {
@Override
public String detailContent(List<String> ids) throws Exception {
if (!login) checkLogin();
String bvid = ids.get(0);
String bvid2aidUrl = "https://api.bilibili.com/x/web-interface/archive/stat?bvid=" + bvid;
JSONObject bvid2aidResp = new JSONObject(OkHttp.string(bvid2aidUrl, header));
@ -112,7 +124,7 @@ public class Bili extends Spider {
for (int i = 0; i < pages.length(); ++i) {
JSONObject page = pages.getJSONObject(i);
String title = page.getString("part").replace("$", "_").replace("#", "_");
playlist.add(Trans.get(title) + "$" + aid + "+" + page.getLong("cid"));
playlist.add(title + "$" + aid + "+" + page.getLong("cid"));
}
Vod vod = new Vod();
vod.setVodId(bvid);
@ -141,4 +153,78 @@ public class Bili extends Spider {
url = resp.getJSONObject("data").getJSONArray("durl").getJSONObject(0).getString("url");
return Result.get().url(url).header(header).string();
}
private void checkLogin() throws Exception {
login = new JSONObject(OkHttp.string("https://api.bilibili.com/x/web-interface/nav", header)).getJSONObject("data").getBoolean("isLogin");
boolean qrCode = Prefers.getBoolean("BiliQRCode", true);
if (!login && qrCode) getQRCode();
}
private void getQRCode() {
try {
String json = OkHttp.string("https://passport.bilibili.com/x/passport-login/web/qrcode/generate?source=main-mini", null);
JSONObject data = new JSONObject(json).getJSONObject("data");
Init.run(() -> showQRCode(data));
} catch (Exception ignored) {
}
}
private void showQRCode(JSONObject data) {
try {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(Utils.dp2px(240), Utils.dp2px(240));
ImageView image = new ImageView(Init.context());
image.setScaleType(ImageView.ScaleType.CENTER_CROP);
image.setImageBitmap(QRCode.getBitmap(data.getString("url"), 240, 2));
FrameLayout frame = new FrameLayout(Init.context());
params.gravity = Gravity.CENTER;
frame.addView(image, params);
dialog = new AlertDialog.Builder(Init.getActivity()).setView(frame).setOnDismissListener(this::dismiss).show();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Init.execute(() -> startService(data));
Init.show("請使用 BiliBili App 掃描二維碼");
} catch (Exception ignored) {
}
}
private void startService(JSONObject data) {
service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(() -> {
try {
String qr = data.getString("qrcode_key");
String url = "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + qr + "&source=main_mini";
String json = OkHttp.string(url, header);
url = new JSONObject(json).getJSONObject("data").getString("url");
if (!TextUtils.isEmpty(url)) setCookie(url);
} catch (Exception ignored) {
}
}, 1, 1, TimeUnit.SECONDS);
}
private void setCookie(String url) {
Map<String, List<String>> respHeader = new HashMap<>();
OkHttp.stringNoRedirect(url, header, respHeader);
StringBuilder sb = new StringBuilder();
for (String value : Objects.requireNonNull(respHeader.get("set-cookie"))) sb.append(value.split(";")[0]).append(";");
Init.run(() -> Prefers.put("BiliQRCode", true), 5000);
Prefers.put("BiliCookie", sb.toString());
Init.show("請重新進入播放頁");
stopService();
}
private void stopService() {
if (service != null) service.shutdownNow();
Init.run(this::dismiss);
}
private void dismiss(DialogInterface dialog) {
Prefers.put("BiliQRCode", false);
stopService();
}
private void dismiss() {
try {
if (dialog != null) dialog.dismiss();
} catch (Exception ignored) {
}
}
}

View File

@ -8,8 +8,7 @@ import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Trans;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@ -32,7 +31,7 @@ public class Dm84 extends Spider {
private HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
return headers;
}
@ -141,7 +140,7 @@ public class Dm84 extends Spider {
List<String> vodItems = new ArrayList<>();
for (int j = 0; j < playList.size(); j++) {
Element e = playList.get(j);
vodItems.add(Trans.get(e.text()) + "$" + e.attr("href"));
vodItems.add(e.text() + "$" + e.attr("href"));
}
if (vodItems.size() > 0) {
sites.put(sourceName, TextUtils.join("#", vodItems));

View File

@ -1,20 +1,19 @@
package com.github.catvod.spider;
import android.os.SystemClock;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.util.Base64;
import com.github.catvod.bean.Class;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -60,35 +59,26 @@ public class Doll extends Spider {
@Override
public String detailContent(List<String> ids) throws Exception {
Document doc = Jsoup.parse(OkHttp.string(url + ids.get(0)));
String name = doc.select("meta[property=og:title]").attr("content");
String html = OkHttp.string(url + ids.get(0));
Document doc = Jsoup.parse(html);
StringBuilder sb = new StringBuilder();
String videoId = ids.get(0).split("/")[1].split("\\.")[0];
String pic = doc.select("meta[property=og:image]").attr("content");
String name = doc.select("meta[property=og:title]").attr("content");
String voteTag = new String(Base64.decode(Utils.getVar(html, "voteTag").getBytes(), 0));
for (int i = 0; i < voteTag.length(); i++) sb.append(Character.toChars(voteTag.charAt(i) ^ videoId.charAt(i % videoId.length())));
String playUrl = URLDecoder.decode(new String(Base64.decode(sb.toString().getBytes(), 0)));
Vod vod = new Vod();
vod.setVodId(ids.get(0));
vod.setVodPic(pic);
vod.setVodName(name);
vod.setVodPlayFrom("玩偶姐姐");
vod.setVodPlayUrl("播放$" + ids.get(0));
vod.setVodPlayUrl("播放$" + playUrl);
return Result.string(vod);
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
HashMap<String, String> result = new HashMap<>();
Misc.loadWebView(url + id, getClient(result));
while (result.isEmpty()) SystemClock.sleep(10);
return Result.get().url(result.get("url")).string();
}
private WebViewClient getClient(HashMap<String, String> result) {
return new WebViewClient() {
@Override
public void onLoadResource(WebView view, String url) {
if (url.endsWith(".m3u8")) {
result.put("url", url);
view.destroy();
}
}
};
return Result.get().url(id).string();
}
}

View File

@ -0,0 +1,24 @@
package com.github.catvod.spider;
import android.content.Context;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.net.OkHttp;
import java.net.URLEncoder;
public class Dovx extends Ali {
@Override
public void init(Context context, String extend) {
super.init(context, extend);
}
@Override
public String searchContent(String key, boolean quick) {
Result result = Result.objectFrom(OkHttp.string("https://api.dovx.tk/ali/search?wd=" + URLEncoder.encode(key)));
for (Vod vod : result.getList()) vod.setVodId(vod.getVodContent());
return result.string();
}
}

View File

@ -9,7 +9,7 @@ import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@ -97,7 +97,7 @@ public class Eighteen extends Spider {
@Override
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
HashMap<String, String> result = new HashMap<>();
Misc.loadWebView(url + id, getClient(result));
Utils.loadWebView(url + id, getClient(result));
while (result.isEmpty()) SystemClock.sleep(10);
return Result.get().url(result.get("url")).string();
}

View File

@ -6,7 +6,7 @@ import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@ -23,7 +23,7 @@ public class Hanime extends Spider {
private HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
return headers;
}

View File

@ -8,13 +8,15 @@ import android.os.Looper;
import android.widget.Toast;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.utils.Trans;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Init {
private final ExecutorService executor;
private final Handler handler;
private Application app;
@ -28,6 +30,7 @@ public class Init {
public Init() {
this.handler = new Handler(Looper.getMainLooper());
this.executor = Executors.newFixedThreadPool(5);
}
public static Application context() {
@ -37,7 +40,10 @@ public class Init {
public static void init(Context context) {
SpiderDebug.log("自定義爬蟲代碼載入成功!");
get().app = ((Application) context);
Trans.init();
}
public static void execute(Runnable runnable) {
get().executor.execute(runnable);
}
public static void run(Runnable runnable) {

View File

@ -5,7 +5,7 @@ import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@ -26,7 +26,7 @@ public class Jable extends Spider {
private HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
return headers;
}
@ -79,7 +79,7 @@ public class Jable extends Spider {
vod.setVodYear(year.replace("上市於 ", ""));
vod.setVodName(name);
vod.setVodPlayFrom("Jable");
vod.setVodPlayUrl("播放$" + Misc.getVar(doc.html(), "hlsUrl"));
vod.setVodPlayUrl("播放$" + Utils.getVar(doc.html(), "hlsUrl"));
return Result.string(vod);
}

View File

@ -1,42 +0,0 @@
package com.github.catvod.spider;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import com.github.catvod.crawler.Spider;
public class Live extends Spider {
private int delay;
@Override
public void init(Context context, String extend) {
super.init(context, extend);
this.delay = delay(extend);
}
@Override
public String homeVideoContent() {
Init.run(this::openLive, delay);
return "";
}
private int delay(String extend) {
try {
return TextUtils.isEmpty(extend) ? 0 : Integer.parseInt(extend);
} catch (Throwable ignored) {
return 0;
}
}
private void openLive() {
try {
Activity activity = Init.getActivity();
activity.startActivity(new Intent().setComponent(new ComponentName(activity, "com.fongmi.android.tv.ui.activity.LiveActivity")));
} catch (Throwable ignored) {
}
}
}

View File

@ -4,9 +4,8 @@ import android.content.Context;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
@ -22,13 +21,13 @@ import java.util.Map;
/**
* @author ColaMint & FongMi
*/
public class PanSou extends Spider {
public class PanSou extends Ali {
private final String siteUrl = "https://www.alipansou.com";
private Map<String, String> getHeaders(String id) {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
headers.put("Referer", siteUrl + id);
headers.put("_bid", "6d14a5dd6c07980d9dc089a693805ad8");
return headers;
@ -36,16 +35,17 @@ public class PanSou extends Spider {
@Override
public void init(Context context, String extend) {
Ali.get().init(extend);
super.init(context, extend);
}
@Override
public String detailContent(List<String> ids) throws Exception {
if (pattern.matcher(ids.get(0)).find()) return super.detailContent(ids);
String url = siteUrl + ids.get(0).replace("/s/", "/cv/");
Map<String, List<String>> respHeaders = new HashMap<>();
OkHttp.stringNoRedirect(url, getHeaders(ids.get(0)), respHeaders);
url = OkHttp.getRedirectLocation(respHeaders);
return Ali.get().detailContent(Arrays.asList(url));
return super.detailContent(Arrays.asList(url));
}
@Override
@ -71,9 +71,4 @@ public class PanSou extends Spider {
}
return Result.string(list);
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) {
return Ali.get().playerContent(flag, id);
}
}

View File

@ -7,9 +7,8 @@ import com.github.catvod.bean.Filter;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.bean.paper.Data;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import org.json.JSONObject;
import org.jsoup.Jsoup;
@ -27,7 +26,7 @@ import java.util.Map;
/**
* @author ColaMint & FongMi
*/
public class Paper extends Spider {
public class Paper extends Ali {
private final String url = "https://gitcafe.net/alipaper/";
private final String api = "https://gitcafe.net/tool/alipaper/";
@ -35,14 +34,14 @@ public class Paper extends Spider {
private HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
return headers;
}
@Override
public void init(Context context, String extend) {
super.init(context, extend);
types = Arrays.asList("hyds", "rhds", "omds", "qtds", "hydy", "rhdy", "omdy", "qtdy", "hydm", "rhdm", "omdm", "jlp", "zyp", "jypx", "qtsp");
Ali.get().init(extend);
}
@Override
@ -90,11 +89,6 @@ public class Paper extends Spider {
return Result.string(list);
}
@Override
public String detailContent(List<String> ids) throws Exception {
return Ali.get().detailContent(ids);
}
@Override
public String searchContent(String key, boolean quick) {
List<Vod> list = new ArrayList<>();
@ -105,9 +99,4 @@ public class Paper extends Spider {
for (Data item : Data.arrayFrom(result)) if (types.contains(item.getCat()) && item.getTitle().contains(key)) list.add(item.getVod());
return Result.string(list);
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
return Ali.get().playerContent(flag, id);
}
}

View File

@ -5,7 +5,6 @@ import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.net.OkHttp;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Objects;
@ -13,12 +12,14 @@ public class Proxy extends Spider {
private static int port = -1;
public static Object[] proxy(Map<String, String> params) throws UnsupportedEncodingException {
public static Object[] proxy(Map<String, String> params) throws Exception {
switch (Objects.requireNonNull(params.get("do"))) {
case "ck":
return new Object[]{200, "text/plain; charset=utf-8", new ByteArrayInputStream("ok".getBytes("UTF-8"))};
case "ali":
return Ali.get().vod(params);
return Ali.vod(params);
case "webdav":
return WebDAV.vod(params);
default:
return null;
}

View File

@ -1,46 +1,45 @@
package com.github.catvod.spider;
import android.content.Context;
import android.text.TextUtils;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.utils.Misc;
import java.io.File;
import java.util.Arrays;
import java.util.List;
public class Push extends Spider {
public class Push extends Ali {
@Override
public void init(Context context, String extend) {
Ali.get().init(extend);
super.init(context, extend);
}
@Override
public String detailContent(List<String> ids) throws Exception {
String url = ids.get(0).trim();
if (url.contains("aliyundrive")) return Ali.get().detailContent(ids);
if (Misc.isVip(url)) return Result.string(vod(url, "官源"));
if (Misc.isVideoFormat(url)) return Result.string(vod(url, "直連"));
return Result.string(vod(url, "網頁"));
if (url.contains("aliyundrive")) return super.detailContent(ids);
return Result.string(vod(url));
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) {
if (flag.contains("")) return Ali.get().playerContent(flag, id);
if (flag.equals("官源")) return Result.get().parse().jx().url(id).string();
if (flag.equals("網頁")) return Result.get().parse().url(id).string();
return Result.get().url(id).string();
if (flag.equals("直連")) return Result.get().url(id).string();
if (flag.equals("嗅探")) return Result.get().parse().url(id).string();
if (flag.equals("解析")) return Result.get().parse().jx().url(id).string();
return super.playerContent(flag, id, vipFlags);
}
private Vod vod(String url, String type) {
private Vod vod(String url) {
Vod vod = new Vod();
vod.setTypeName(type);
vod.setVodId(url);
vod.setVodName(url);
vod.setVodPlayFrom(type);
vod.setVodPlayUrl("播放$" + url);
vod.setTypeName("FongMi");
vod.setVodName(url.startsWith("file://") ? new File(url).getName() : url);
vod.setVodPic("https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg");
vod.setVodPlayFrom(TextUtils.join("$$$", Arrays.asList("直連", "嗅探", "解析")));
vod.setVodPlayUrl(TextUtils.join("$$$", Arrays.asList("播放$" + url, "播放$" + url, "播放$" + url)));
return vod;
}
}

View File

@ -8,7 +8,7 @@ import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@ -33,7 +33,7 @@ public class Supjav extends Spider {
private HashMap<String, String> getHeaders(String referer) {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
headers.put("Referer", referer);
return headers;
}
@ -149,7 +149,7 @@ public class Supjav extends Spider {
private String parseTV(String redirect) {
String data = OkHttp.string(redirect, getHeaders(playUrl));
return Result.get().url(Misc.getVar(data, "urlPlay")).header(getHeaders(redirect)).string();
return Result.get().url(Utils.getVar(data, "urlPlay")).header(getHeaders(redirect)).string();
}
private String parseST(String redirect) {

View File

@ -1,56 +1,48 @@
package com.github.catvod.spider;
import android.content.Context;
import android.util.Base64;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.bean.upyun.Data;
import com.github.catvod.bean.upyun.Item;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.google.common.io.BaseEncoding;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UpYun extends Spider {
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
private final String siteUrl = "https://www.upyunso.com/";
private final String apiUrl = "https://api.upyunso2.com/";
private Map<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("Referer", siteUrl);
return headers;
}
public class UpYun extends Ali {
@Override
public void init(Context context, String extend) {
Ali.get().init(extend);
super.init(context, extend);
}
@Override
public String detailContent(List<String> ids) throws Exception {
return Ali.get().detailContent(Arrays.asList(ids.get(0)));
}
@Override
public String searchContent(String key, boolean quick) {
String url = apiUrl + "search?keyword=" + URLEncoder.encode(key) + "&page=1&s_type=2";
String res = new String(Base64.decode(OkHttp.string(url, getHeaders()), Base64.DEFAULT));
public String searchContent(String key, boolean quick) throws Exception {
String res = decode(OkHttp.string("https://zyb.upyunso.com/v15/search?keyword=" + URLEncoder.encode(key) + "&page=1&s_type=2"));
List<Vod> list = new ArrayList<>();
for (Item item : Data.objectFrom(res).getResult().getItems()) if (item.isAli() && item.getTitle().contains(key)) list.add(item.getVod());
for (Item item : Data.objectFrom(res).getResult().getItems()) {
String url = decode(item.getPageUrl());
if (!url.contains("www.aliyundrive.com")) continue;
if (item.getTitle().contains(key)) list.add(item.url(url).getVod());
}
return Result.string(list);
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) {
return Ali.get().playerContent(flag, id);
private String decode(String data) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec("qq1920520460qqzz".getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec("qq1920520460qqzz".getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] encryptDataBytes = BaseEncoding.base16().decode(data.toUpperCase());
byte[] decryptData = cipher.doFinal(encryptDataBytes);
return new String(decryptData, "UTF-8");
}
}

View File

@ -0,0 +1,195 @@
package com.github.catvod.spider;
import android.content.Context;
import android.text.TextUtils;
import com.github.catvod.bean.Class;
import com.github.catvod.bean.Filter;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Sub;
import com.github.catvod.bean.Vod;
import com.github.catvod.bean.webdav.Drive;
import com.github.catvod.bean.webdav.Sorter;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Utils;
import com.thegrizzlylabs.sardineandroid.DavResource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class WebDAV extends Spider {
private static List<Drive> drives;
private List<String> playExt;
private List<String> allExt;
private String vodPic;
private String ext;
private List<Filter> getFilter() {
List<Filter> items = new ArrayList<>();
items.add(new Filter("type", "排序類型", Arrays.asList(new Filter.Value("預設", ""), new Filter.Value("名稱", "name"), new Filter.Value("大小", "size"), new Filter.Value("修改時間", "date"))));
items.add(new Filter("order", "排序方式", Arrays.asList(new Filter.Value("預設", ""), new Filter.Value("", "asc"), new Filter.Value("", "desc"))));
return items;
}
private void fetchRule() {
if (drives != null && !drives.isEmpty()) return;
if (ext.startsWith("http")) ext = OkHttp.string(ext);
Drive drive = Drive.objectFrom(ext);
drives = drive.getDrives();
vodPic = drive.getVodPic();
}
private String getExt(DavResource item) {
return item.getName().substring(item.getName().lastIndexOf(".") + 1);
}
private String removeExt(DavResource item) {
return Utils.removeExt(item.getName());
}
private static Drive getDrive(String name) {
return drives.get(drives.indexOf(new Drive(name)));
}
@Override
public void init(Context context, String extend) {
playExt = Arrays.asList("mp4", "mkv", "wmv", "flv", "avi", "mp3", "aac", "flac", "m4a");
allExt = new ArrayList<>(Arrays.asList("ass", "ssa", "srt"));
allExt.addAll(playExt);
ext = extend;
fetchRule();
}
@Override
public String homeContent(boolean filter) throws Exception {
fetchRule();
List<Class> classes = new ArrayList<>();
LinkedHashMap<String, List<Filter>> filters = new LinkedHashMap<>();
for (Drive drive : drives) classes.add(drive.toType());
for (Class item : classes) filters.put(item.getTypeId(), getFilter());
return Result.string(classes, filters);
}
@Override
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) throws Exception {
String key = tid.contains("/") ? tid.substring(0, tid.indexOf("/")) : tid;
String path = tid.contains("/") ? tid.substring(tid.indexOf("/")) : "";
String order = extend.containsKey("order") ? extend.get("order") : "";
String type = extend.containsKey("type") ? extend.get("type") : "";
List<DavResource> folders = new ArrayList<>();
List<DavResource> files = new ArrayList<>();
List<Vod> list = new ArrayList<>();
Drive drive = getDrive(key);
for (DavResource item : getList(drive, path, playExt)) {
if (item.isDirectory()) folders.add(item);
else files.add(item);
}
if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(order)) {
Sorter.sort(type, order, folders);
Sorter.sort(type, order, files);
}
for (DavResource item : folders) list.add(drive.vod(item, vodPic));
for (DavResource item : files) list.add(drive.vod(item, vodPic));
return Result.get().vod(list).page().string();
}
@Override
public String detailContent(List<String> ids) throws Exception {
String id = ids.get(0);
String key = id.contains("/") ? id.substring(0, id.indexOf("/")) : id;
String parent = id.substring(0, id.lastIndexOf("/"));
String path = parent.contains("/") ? parent.substring(parent.indexOf("/")) + "/" : "";
String name = parent.substring(parent.lastIndexOf("/") + 1);
Drive drive = getDrive(key);
List<DavResource> parents = getList(drive, path, allExt);
List<DavResource> subs = getSubs(parents);
Sorter.sort("name", "asc", parents);
List<String> playUrls = new ArrayList<>();
for (DavResource item : parents) {
if (playExt.contains(getExt(item))) {
playUrls.add(item.getName() + "$" + drive.getName() + item.getPath() + findSubs(drive, item, subs));
}
}
Vod vod = new Vod();
vod.setVodId(name);
vod.setVodName(name);
vod.setVodPic(vodPic);
vod.setVodPlayFrom(key);
vod.setVodPlayUrl(TextUtils.join("#", playUrls));
return Result.string(vod);
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
String[] ids = id.split("~~~");
return Result.get().url(getProxyUrl(ids[0])).subs(getSub(ids)).string();
}
private List<DavResource> getList(Drive drive, String path, List<String> ext) throws Exception {
path = drive.getHost() + (path.startsWith(drive.getPath()) ? path : drive.getPath() + path);
List<DavResource> items = drive.getWebdav().list(path);
items.remove(0); //Remove parent
Iterator<DavResource> iterator = items.iterator();
while (iterator.hasNext()) {
DavResource item = iterator.next();
if (!item.isDirectory() && !item.getName().contains(".")) iterator.remove();
if (!item.isDirectory() && !ext.contains(getExt(item))) iterator.remove();
}
return items;
}
private List<DavResource> getSubs(List<DavResource> items) {
List<DavResource> subs = new ArrayList<>();
for (DavResource item : items) if (Utils.isSub(getExt(item))) subs.add(item);
return subs;
}
private String findSubs(Drive drive, DavResource res, List<DavResource> items) {
StringBuilder sb = new StringBuilder();
for (DavResource item : items) if (removeExt(item).equals(removeExt(res))) sb.append("~~~").append(item.getName()).append("@@@").append(getExt(item)).append("@@@").append(drive.getName() + item.getPath());
return sb.length() > 0 ? sb.toString() : findSubs(drive, items);
}
private String findSubs(Drive drive, List<DavResource> items) {
StringBuilder sb = new StringBuilder();
for (DavResource item : items) sb.append("~~~").append(item.getName()).append("@@@").append(getExt(item)).append("@@@").append(drive.getName() + item.getPath());
return sb.toString();
}
private List<Sub> getSub(String[] ids) {
List<Sub> sub = new ArrayList<>();
for (String text : ids) {
if (!text.contains("@@@")) continue;
String[] split = text.split("@@@");
String name = split[0];
String ext = split[1];
String url = getProxyUrl(split[2]);
sub.add(Sub.create().name(name).ext(ext).url(url));
}
return sub;
}
private String getProxyUrl(String url) {
return Proxy.getUrl() + "?do=webdav&url=" + url;
}
public static Object[] vod(Map<String, String> params) throws IOException {
String url = params.get("url");
String key = url.contains("/") ? url.substring(0, url.indexOf("/")) : url;
url = url.substring(key.length());
Drive drive = getDrive(key);
Object[] result = new Object[3];
result[0] = 200;
result[1] = "application/octet-stream";
result[2] = drive.getWebdav().get(drive.getHost() + url);
return result;
}
}

View File

@ -6,15 +6,13 @@ import android.text.TextUtils;
import com.github.catvod.bean.Class;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.bean.xpath.Rule;
import com.github.catvod.crawler.Spider;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Trans;
import com.github.catvod.xpath.XPathRule;
import com.github.catvod.utils.Utils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.seimicrawler.xpath.JXDocument;
import org.seimicrawler.xpath.JXNode;
@ -27,38 +25,32 @@ import java.util.Set;
public class XPath extends Spider {
protected XPathRule rule = null;
private HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", rule.getUa().isEmpty() ? Misc.CHROME : rule.getUa());
headers.put("User-Agent", rule.getUa().isEmpty() ? Utils.CHROME : rule.getUa());
return headers;
}
private void fetchRule(String ext) {
if (ext.startsWith("http")) {
String json = OkHttp.string(ext);
rule = XPathRule.fromJson(json);
loadRuleExt(json);
} else {
rule = XPathRule.fromJson(ext);
loadRuleExt(ext);
}
@Override
public void init(Context context) {
super.init(context);
}
@Override
public void init(Context context, String extend) {
super.init(context, extend);
fetchRule(extend);
this.ext = extend;
}
@Override
public String homeContent(boolean filter) throws JSONException {
public String homeContent(boolean filter) {
fetchRule();
List<Vod> list = new ArrayList<>();
List<Class> classes = new ArrayList<>();
if (rule.getCateManual().size() > 0) {
Set<String> keys = rule.getCateManual().keySet();
for (String k : keys) classes.add(new Class(rule.getCateManual().get(k), k));
for (String k : keys) {
classes.add(new Class(rule.getCateManual().get(k), k));
}
}
String webUrl = rule.getHomeUrl();
JXDocument doc = JXDocument.create(fetch(webUrl));
@ -81,7 +73,7 @@ public class XPath extends Spider {
id = rule.getHomeVodIdR(id);
String pic = vodNodes.get(i).selOne(rule.getHomeVodImg()).asString().trim();
pic = rule.getHomeVodImgR(pic);
pic = Misc.fixUrl(webUrl, pic);
pic = Utils.fixUrl(webUrl, pic);
String mark = "";
if (!rule.getHomeVodMark().isEmpty()) {
try {
@ -103,8 +95,9 @@ public class XPath extends Spider {
@Override
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) {
String webUrl = categoryUrl(tid, pg, filter, extend);
fetchRule();
List<Vod> list = new ArrayList<>();
String webUrl = categoryUrl(tid, pg, filter, extend);
JXDocument doc = JXDocument.create(fetch(webUrl));
List<JXNode> vodNodes = doc.selN(rule.getCateVodNode());
for (int i = 0; i < vodNodes.size(); i++) {
@ -114,7 +107,7 @@ public class XPath extends Spider {
id = rule.getCateVodIdR(id);
String pic = vodNodes.get(i).selOne(rule.getCateVodImg()).asString().trim();
pic = rule.getCateVodImgR(pic);
pic = Misc.fixUrl(webUrl, pic);
pic = Utils.fixUrl(webUrl, pic);
String mark = "";
if (!rule.getCateVodMark().isEmpty()) {
try {
@ -130,7 +123,8 @@ public class XPath extends Spider {
}
@Override
public String detailContent(List<String> ids) throws JSONException {
public String detailContent(List<String> ids) {
fetchRule();
String webUrl = rule.getDetailUrl().replace("{vid}", ids.get(0));
String webContent = fetch(webUrl);
JXDocument doc = JXDocument.create(webContent);
@ -138,15 +132,9 @@ public class XPath extends Spider {
String cover = "", title = "", desc = "", category = "", area = "", year = "", remark = "", director = "", actor = "";
title = vodNode.selOne(rule.getDetailName()).asString().trim();
title = rule.getDetailNameR(title);
if (!rule.getDetailImg().isEmpty()) {
try {
cover = vodNode.selOne(rule.getDetailImg()).asString().trim();
cover = rule.getDetailImgR(cover);
cover = Misc.fixUrl(webUrl, cover);
} catch (Exception e) {
SpiderDebug.log(e);
}
}
cover = Utils.fixUrl(webUrl, cover);
if (!rule.getDetailCate().isEmpty()) {
try {
category = vodNode.selOne(rule.getDetailCate()).asString().trim();
@ -234,13 +222,15 @@ public class XPath extends Spider {
name = rule.getDetailUrlNameR(name);
String id = urlNodes.get(j).selOne(rule.getDetailUrlId()).asString().trim();
id = rule.getDetailUrlIdR(id);
vodItems.add(Trans.get(name) + "$" + id);
vodItems.add(name + "$" + id);
}
// 排除播放列表為空的播放源
if (vodItems.size() == 0 && playFrom.size() > i) {
playFrom.set(i, "");
}
playList.add(TextUtils.join("#", vodItems));
}
// 排除播放列表為空的播放源
for (int i = playFrom.size() - 1; i >= 0; i--) {
if (playFrom.get(i).isEmpty()) playFrom.remove(i);
}
@ -257,6 +247,7 @@ public class XPath extends Spider {
@Override
public String playerContent(String flag, String id, List<String> vipFlags) {
fetchRule();
String webUrl = rule.getPlayUrl().isEmpty() ? id : rule.getPlayUrl().replace("{playUrl}", id);
SpiderDebug.log(webUrl);
HashMap<String, String> headers = new HashMap<>();
@ -266,7 +257,8 @@ public class XPath extends Spider {
}
@Override
public String searchContent(String key, boolean quick) throws JSONException {
public String searchContent(String key, boolean quick) throws Exception {
fetchRule();
if (rule.getSearchUrl().isEmpty()) return "";
String webUrl = rule.getSearchUrl().replace("{wd}", URLEncoder.encode(key));
String webContent = fetch(webUrl);
@ -285,7 +277,7 @@ public class XPath extends Spider {
id = rule.getSearchVodIdR(id);
String pic = vod.optString(rule.getSearchVodImg()).trim();
pic = rule.getSearchVodImgR(pic);
pic = Misc.fixUrl(webUrl, pic);
pic = Utils.fixUrl(webUrl, pic);
String mark = vod.optString(rule.getSearchVodMark()).trim();
mark = rule.getSearchVodMarkR(mark);
list.add(new Vod(id, name, pic, mark));
@ -304,7 +296,7 @@ public class XPath extends Spider {
id = rule.getSearchVodIdR(id);
String pic = vodNodes.get(i).selOne(rule.getSearchVodImg()).asString().trim();
pic = rule.getSearchVodImgR(pic);
pic = Misc.fixUrl(webUrl, pic);
pic = Utils.fixUrl(webUrl, pic);
String mark = "";
if (!rule.getCateVodMark().isEmpty()) {
try {
@ -320,6 +312,34 @@ public class XPath extends Spider {
return Result.string(list);
}
@Override
public boolean manualVideoCheck() {
return false;
}
@Override
public boolean isVideoFormat(String url) {
return Utils.isVideoFormat(url);
}
protected String ext = null;
protected Rule rule = null;
protected void fetchRule() {
if (rule == null) {
if (ext != null) {
if (ext.startsWith("http")) {
String json = OkHttp.string(ext, null);
rule = Rule.fromJson(json);
loadRuleExt(json);
} else {
rule = Rule.fromJson(ext);
loadRuleExt(ext);
}
}
}
}
protected void loadRuleExt(String json) {
}

View File

@ -1,7 +1,5 @@
package com.github.catvod.spider;
import android.text.TextUtils;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.regex.Matcher;
@ -9,16 +7,22 @@ import java.util.regex.Pattern;
public class XPathFilter extends XPath {
@Override
protected void loadRuleExt(String json) {
super.loadRuleExt(json);
}
@Override
protected String categoryUrl(String tid, String pg, boolean filter, HashMap<String, String> extend) {
String cateUrl = rule.getCateUrl();
if (filter && extend != null && extend.size() > 0) {
for (String key : extend.keySet()) {
String value = extend.get(key);
if (TextUtils.isEmpty(value)) continue;
if (value.length() > 0) {
cateUrl = cateUrl.replace("{" + key + "}", URLEncoder.encode(value));
}
}
}
cateUrl = cateUrl.replace("{cateId}", tid).replace("{catePg}", pg);
Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(cateUrl);
while (m.find()) {

View File

@ -1,10 +1,12 @@
package com.github.catvod.spider;
import android.content.Context;
import android.text.TextUtils;
import android.util.Base64;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import com.google.gson.Gson;
import org.json.JSONException;
import org.json.JSONObject;
@ -30,7 +32,17 @@ public class XPathMac extends XPath {
// 播放器配置js取值正則
private String playerConfigJsRegex = "[\\W|\\S|.]*?MacPlayerConfig.player_list[\\W|\\S|.]*?=([\\W|\\S|.]*?),MacPlayerConfig.downer_list";
// 站點里播放源對應的真實官源
private HashMap<String, String> show2VipFlag = new HashMap<>();
private final HashMap<String, String> show2VipFlag = new HashMap<>();
/**
* mac cms 直連和官源調用應用內播放列表支持
*
* @param context
* @param extend
*/
public void init(Context context, String extend) {
super.init(context, extend);
}
@Override
protected void loadRuleExt(String json) {
@ -48,19 +60,19 @@ public class XPathMac extends XPath {
}
playerConfigJs = jsonObj.optString("pCfgJs").trim();
playerConfigJsRegex = jsonObj.optString("pCfgJsR", playerConfigJsRegex).trim();
} catch (Exception e) {
} catch (JSONException e) {
SpiderDebug.log(e);
}
}
@Override
public String homeContent(boolean filter) throws JSONException {
public String homeContent(boolean filter) {
String result = super.homeContent(filter);
if (result.isEmpty() || playerConfigJs.isEmpty()) return result;
//嘗試通過playerConfigJs獲取展示和flag匹配關系
if (result.length() > 0 && playerConfigJs.length() > 0) { // 嘗試通過playerConfigJs獲取展示和flag匹配關系
String webContent = fetch(playerConfigJs);
Matcher matcher = Pattern.compile(playerConfigJsRegex).matcher(webContent);
if (!matcher.find()) return result;
if (matcher.find()) {
try {
JSONObject jsonObject = new JSONObject(matcher.group(1));
Iterator<String> keys = jsonObject.keys();
while (keys.hasNext()) {
@ -71,23 +83,40 @@ public class XPathMac extends XPath {
if (show.isEmpty()) continue;
show2VipFlag.put(show, key);
}
} catch (Exception e) {
SpiderDebug.log(e);
}
}
}
return result;
}
@Override
public String detailContent(List<String> ids) throws JSONException {
public String detailContent(List<String> ids) {
String result = super.detailContent(ids);
if (!decodeVipFlag || result.isEmpty()) return result;
if (decodeVipFlag && result.length() > 0) {
try {
JSONObject jsonObject = new JSONObject(result);
String[] playFrom = jsonObject.optJSONArray("list").getJSONObject(0).optString("vod_play_from").split("\\$\\$\\$");
if (playFrom.length == 0) return result;
for (int i = 0; i < playFrom.length; i++) if (show2VipFlag.containsKey(playFrom[i])) playFrom[i] = show2VipFlag.get(playFrom[i]);
if (playFrom.length > 0) {
for (int i = 0; i < playFrom.length; i++) {
if (show2VipFlag.containsKey(playFrom[i])) {
playFrom[i] = show2VipFlag.get(playFrom[i]);
}
}
jsonObject.optJSONArray("list").getJSONObject(0).put("vod_play_from", TextUtils.join("$$$", playFrom));
return jsonObject.toString();
result = jsonObject.toString();
}
} catch (Throwable th) {
SpiderDebug.log(th);
}
}
return result;
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) {
fetchRule();
String webUrl = rule.getPlayUrl().isEmpty() ? id : rule.getPlayUrl().replace("{playUrl}", id);
String videoUrl = null;
// 嘗試分析直連
@ -122,7 +151,7 @@ public class XPathMac extends XPath {
}
if (videoUrl != null) {
// 適配2.0.6的調用應用內解析列表的支持, 需要配合直連分析和匹配官源解析一起使用參考cjt影視和極品直連
if (decodeVipFlag && Misc.isVip(videoUrl)) { // 使用jx:1
if (decodeVipFlag && Utils.isVip(videoUrl)) { // 使用jx:1
try {
JSONObject result = new JSONObject();
result.put("parse", 1);
@ -145,13 +174,16 @@ public class XPathMac extends XPath {
}
}
// 如果是視頻直連 直接返回免解
else if (Misc.isVideoFormat(videoUrl)) {
else if (isVideoFormat(videoUrl)) {
try {
JSONObject result = new JSONObject();
result.put("parse", 0);
result.put("playUrl", "");
result.put("url", videoUrl);
result.put("header", "");
HashMap<String, String> headers = new HashMap<>();
if (rule.getPlayUa().length() > 0) headers.put("User-Agent", rule.getPlayUa());
if (rule.getPlayReferer().length() > 0) headers.put("Referer", rule.getPlayReferer());
result.put("header", new Gson().toJson(headers));
return result.toString();
} catch (Exception e) {
SpiderDebug.log(e);

View File

@ -1,7 +1,5 @@
package com.github.catvod.spider;
import android.text.TextUtils;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.regex.Matcher;
@ -15,10 +13,11 @@ public class XPathMacFilter extends XPathMac {
if (filter && extend != null && extend.size() > 0) {
for (String key : extend.keySet()) {
String value = extend.get(key);
if (TextUtils.isEmpty(value)) continue;
if (value.length() > 0) {
cateUrl = cateUrl.replace("{" + key + "}", URLEncoder.encode(value));
}
}
}
cateUrl = cateUrl.replace("{cateId}", tid).replace("{catePg}", pg);
Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(cateUrl);
while (m.find()) {

View File

@ -8,31 +8,19 @@ import android.webkit.WebViewClient;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.yiso.Item;
import com.github.catvod.crawler.Spider;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import com.google.gson.JsonParser;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class YiSo extends Spider {
public class YiSo extends Ali {
@Override
public void init(Context context, String extend) {
Ali.get().init(extend);
}
@Override
public String detailContent(List<String> ids) throws Exception {
return Ali.get().detailContent(ids);
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
return Ali.get().playerContent(flag, id);
super.init(context, extend);
}
@Override
@ -40,7 +28,7 @@ public class YiSo extends Spider {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return "";
String url = "https://yiso.fun/api/search?name=" + URLEncoder.encode(key) + "&from=ali";
Map<String, String> result = new HashMap<>();
Misc.loadWebView(url, getWebViewClient(result));
Utils.loadWebView(url, getWebViewClient(result));
while (!result.containsKey("json")) SystemClock.sleep(50);
String json = JsonParser.parseString(Objects.requireNonNull(result.get("json"))).getAsJsonPrimitive().getAsString();
return Result.string(Item.objectFrom(json).getData().getList(key));

View File

@ -8,8 +8,7 @@ import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Trans;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@ -25,14 +24,14 @@ import java.util.Map;
public class Ying extends Spider {
private static final String siteUrl = "https://www.yhdmp.cc";
private static final String siteUrl = "https://www.yhpdm.com";
private static final String listUrl = siteUrl + "/list/";
private static final String showUrl = siteUrl + "/showp/";
private static final String filterUrl = "https://www.xmfans.me/yxsf/js/yx_catalog.js";
private static final String filterUrl = siteUrl + "/yxsf/js/yx_catalog.js";
private HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
return headers;
}
@ -75,7 +74,7 @@ public class Ying extends Spider {
for (Element element : doc2.select("div.lpic > ul > li")) {
String id = element.select("a").attr("href").split("/")[2];
String name = element.select("h2").text();
String pic = "https:".concat(element.select("a > img").attr("src"));
String pic = element.select("a > img").attr("src");
String remarks = element.select("span > font").text();
remarks = remarks.contains(":") ? remarks.split(" ")[1] : remarks;
list.add(new Vod(id, name, pic, remarks));
@ -101,7 +100,7 @@ public class Ying extends Spider {
for (Element element : doc.select("div.lpic > ul > li")) {
String id = element.select("a").attr("href").split("/")[2];
String name = element.select("h2").text();
String pic = "https:".concat(element.select("a > img").attr("src"));
String pic = element.select("a > img").attr("src");
String remarks = element.select("span > font").text();
remarks = remarks.contains(":") ? remarks.split(" ")[1] : remarks;
list.add(new Vod(id, name, pic, remarks));
@ -113,7 +112,7 @@ public class Ying extends Spider {
public String detailContent(List<String> ids) {
Document doc = Jsoup.parse(OkHttp.string(showUrl.concat(ids.get(0)), getHeaders()));
String name = doc.select("div.rate > h1").text();
String pic = "https:".concat(doc.select("div.thumb > img").attr("src"));
String pic = doc.select("div.thumb > img").attr("src");
String content = doc.select("div.info").text();
Elements element = doc.select("div.sinfo > span > a");
@ -136,7 +135,7 @@ public class Ying extends Spider {
List<String> vodItems = new ArrayList<>();
for (int j = 0; j < playList.size(); j++) {
Element e = playList.get(j);
vodItems.add(Trans.get(e.text()) + "$" + e.attr("href"));
vodItems.add(e.text() + "$" + e.attr("href"));
}
if (vodItems.size() > 0) {
sites.put(sourceName, TextUtils.join("#", vodItems));
@ -157,7 +156,7 @@ public class Ying extends Spider {
for (Element element : doc.select("div.lpic > ul > li")) {
String id = element.select("a").attr("href").split("/")[2];
String name = element.select("h2").text();
String pic = "https:".concat(element.select("a > img").attr("src"));
String pic = element.select("a > img").attr("src");
String remarks = element.select("span > font").text();
remarks = remarks.contains(":") ? remarks.split(" ")[1] : remarks;
list.add(new Vod(id, name, pic, remarks));

View File

@ -8,8 +8,7 @@ import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Trans;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@ -33,7 +32,7 @@ public class Ysj extends Spider {
private HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
return headers;
}
@ -131,7 +130,7 @@ public class Ysj extends Spider {
for (int j = 0; j < playList.size(); j++) {
Element e = playList.get(j);
String href = e.attr("href").replace(playUrl, "");
vodItems.add(Trans.get(e.text()) + "$" + href);
vodItems.add(e.text() + "$" + href);
}
if (vodItems.size() > 0) {
sites.put(sourceName, TextUtils.join("#", vodItems));

View File

@ -4,9 +4,8 @@ import android.content.Context;
import com.github.catvod.bean.Result;
import com.github.catvod.bean.Vod;
import com.github.catvod.crawler.Spider;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Misc;
import com.github.catvod.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@ -14,21 +13,24 @@ import org.jsoup.nodes.Element;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Zhaozy extends Spider {
public class Zhaozy extends Ali {
private final Pattern regexAli = Pattern.compile("(https://www.aliyundrive.com/s/[^\"]+)");
private final Pattern regexVid = Pattern.compile("(\\S+)");
private final String siteUrl = "https://zhaoziyuan.la/";
private String username;
private String password;
private Map<String, String> getHeader() {
Map<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
headers.put("Referer", siteUrl);
headers.put("Cookie", getCookie());
return headers;
@ -36,10 +38,10 @@ public class Zhaozy extends Spider {
private String getCookie() {
Map<String, String> params = new HashMap<>();
params.put("username", "nikalo8893@bitvoo.com");
params.put("password", "P@ssw0rd");
params.put("username", username);
params.put("password", password);
Map<String, String> headers = new HashMap<>();
headers.put("User-Agent", Misc.CHROME);
headers.put("User-Agent", Utils.CHROME);
headers.put("Referer", siteUrl + "login.html");
headers.put("Origin", siteUrl);
Map<String, List<String>> resp = new HashMap<>();
@ -51,25 +53,23 @@ public class Zhaozy extends Spider {
@Override
public void init(Context context, String extend) {
Ali.get().init(extend);
String[] split = extend.split("\\$\\$\\$");
super.init(context, split[0]);
username = split[1];
password = split[2];
}
@Override
public String detailContent(List<String> ids) throws Exception {
if (pattern.matcher(ids.get(0)).find()) return super.detailContent(ids);
Matcher matcher = regexAli.matcher(OkHttp.string(siteUrl + ids.get(0), getHeader()));
if (!matcher.find()) return "";
ids.set(0, matcher.group(1));
return Ali.get().detailContent(ids);
}
@Override
public String playerContent(String flag, String id, List<String> vipFlags) throws Exception {
return Ali.get().playerContent(flag, id);
if (matcher.find()) return super.detailContent(Arrays.asList(matcher.group(1)));
return "";
}
@Override
public String searchContent(String key, boolean quick) throws Exception {
String url = siteUrl + "so?filename=" + URLEncoder.encode(key);
String url = siteUrl + "sos?filename=" + URLEncoder.encode(key);
Document doc = Jsoup.parse(OkHttp.string(url, getHeader()));
List<Vod> list = new ArrayList<>();
for (Element element : doc.select("div.li_con div.news_text")) {

View File

@ -1,22 +0,0 @@
package com.github.catvod.utils;
import com.google.gson.JsonParser;
public class Json {
public static String getString(String result, String column) {
return JsonParser.parseString(result).getAsJsonObject().get(column).getAsString();
}
public static int getInt(String result, String column) {
return JsonParser.parseString(result).getAsJsonObject().get(column).getAsInt();
}
public static long getLong(String result, String column) {
return JsonParser.parseString(result).getAsJsonObject().get(column).getAsLong();
}
public static boolean getBoolean(String result, String column) {
return JsonParser.parseString(result).getAsJsonObject().get(column).getAsBoolean();
}
}

View File

@ -35,7 +35,7 @@ public class QRCode {
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, margin);
return createBitmap(new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, Misc.dp2px(size), Misc.dp2px(size), hints));
return createBitmap(new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, Utils.dp2px(size), Utils.dp2px(size), hints));
} catch (Exception e) {
e.printStackTrace();
return null;

View File

@ -5,7 +5,8 @@ import java.util.regex.Pattern;
public class Sniffer {
public static final Pattern RULE = Pattern.compile(
"http((?!http).){12,}?\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a)\\?.*|" +
"http((?!http).){12,}\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a)"
"http((?!http).){12,}?\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)\\?.*|" +
"http((?!http).){12,}\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)|" +
"http((?!http).)*?video/tos*"
);
}

File diff suppressed because one or more lines are too long

View File

@ -10,21 +10,17 @@ import android.webkit.ValueCallback;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.github.catvod.crawler.SpiderDebug;
import com.github.catvod.spider.Init;
import org.json.JSONException;
import org.json.JSONObject;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
public class Misc {
public class Utils {
public static final String CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36";
public static final String CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36";
public static boolean isVip(String url) {
List<String> hosts = Arrays.asList("iqiyi.com", "v.qq.com", "youku.com", "le.com", "tudou.com", "mgtv.com", "sohu.com", "acfun.cn", "bilibili.com", "baofeng.com", "pptv.com");
@ -33,6 +29,7 @@ public class Misc {
}
public static boolean isVideoFormat(String url) {
if (url.contains("url=http") || url.contains(".js") || url.contains(".css") || url.contains(".html")) return false;
return Sniffer.RULE.matcher(url).find();
}
@ -41,7 +38,7 @@ public class Misc {
}
public static String getSize(double size) {
if (size == 0) return "";
if (size <= 0) return "";
if (size > 1024 * 1024 * 1024 * 1024.0) {
size /= (1024 * 1024 * 1024 * 1024.0);
return String.format(Locale.getDefault(), "%.2f%s", size, "TB");
@ -58,51 +55,19 @@ public class Misc {
}
public static String fixUrl(String base, String src) {
try {
if (src.startsWith("//")) {
Uri parse = Uri.parse(base);
src = parse.getScheme() + ":" + src;
return parse.getScheme() + ":" + src;
} else if (!src.contains("://")) {
Uri parse = Uri.parse(base);
src = parse.getScheme() + "://" + parse.getHost() + src;
}
} catch (Exception e) {
SpiderDebug.log(e);
}
return parse.getScheme() + "://" + parse.getHost() + src;
} else {
return src;
}
public static JSONObject fixJsonVodHeader(JSONObject headers, String input, String url) throws JSONException {
if (headers == null) headers = new JSONObject();
if (input.contains("www.mgtv.com")) {
headers.put("Referer", "");
headers.put("User-Agent", "Mozilla/5.0");
} else if (url.contains("titan.mgtv")) {
headers.put("Referer", "");
headers.put("User-Agent", "Mozilla/5.0");
} else if (input.contains("bilibili")) {
headers.put("Referer", "https://www.bilibili.com/");
headers.put("User-Agent", Misc.CHROME);
}
return headers;
}
public static JSONObject jsonParse(String input, String json) throws JSONException {
JSONObject jsonPlayData = new JSONObject(json);
String url = jsonPlayData.getString("url");
if (url.startsWith("//")) url = "https:" + url;
if (!url.startsWith("http")) return null;
if (url.equals(input)) if (isVip(url) || !isVideoFormat(url)) return null;
JSONObject headers = new JSONObject();
String ua = jsonPlayData.optString("user-agent", "");
if (ua.trim().length() > 0) headers.put("User-Agent", ua);
String referer = jsonPlayData.optString("referer", "");
if (referer.trim().length() > 0) headers.put("Referer", referer);
headers = Misc.fixJsonVodHeader(headers, input, url);
JSONObject taskResult = new JSONObject();
taskResult.put("header", headers);
taskResult.put("url", url);
return taskResult;
public static String removeExt(String text) {
return text.contains(".") ? text.substring(0, text.lastIndexOf(".")) : text;
}
public static String substring(String text) {
@ -118,7 +83,13 @@ public class Misc {
}
public static String getVar(String data, String param) {
for (String var : data.split("var")) if (var.contains(param)) return var.split("'")[1];
for (String var : data.split("var")) if (var.contains(param)) return checkVar(var);
return "";
}
private static String checkVar(String var) {
if (var.contains("'")) return var.split("'")[1];
if (var.contains("\"")) return var.split("\"")[1];
return "";
}

View File

@ -6,7 +6,7 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
@ -15,7 +15,9 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
android.enableJetifier=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
clientId=76917ccccd4441c39457a04f6084fb2f

Binary file not shown.

View File

@ -1 +1 @@
a84fef826cb82da525469e8acf1e7d9a
9eb909e7a180e28b617c5fd15bda5b22

View File

@ -1,31 +1,7 @@
{
"spider": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;a84fef826cb82da525469e8acf1e7d9a",
"spider": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;9eb909e7a180e28b617c5fd15bda5b22",
"wallpaper": "https://gao.chuqiuyu.tk",
"lives": [
{
"name": "直播",
"type": 0,
"url": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/txt/adult.txt"
}
],
"sites": [
{
"key": "AList",
"name": "AList",
"type": 3,
"api": "csp_AList",
"searchable": 1,
"filterable": 1,
"switchable": 0,
"ext": {
"drives": [
{
"name": "木偶",
"server": "https://www.kugutsu.ml"
}
]
}
},
{
"key": "泥巴",
"name": "泥巴",
@ -610,8 +586,7 @@
"api": "csp_Push",
"searchable": 1,
"filterable": 1,
"switchable": 0,
"ext": "http://我不是.肥猫.love:63/token.php"
"changeable": 0
}
]
}

70
json/ali.json Normal file
View File

@ -0,0 +1,70 @@
{
"sites": [
{
"key": "紙條",
"name": "紙條",
"type": 3,
"api": "csp_Paper",
"searchable": 1,
"filterable": 1,
"changeable": 0,
"ext": "影視天下第一",
"jar": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar"
},
{
"key": "易搜",
"name": "易搜",
"type": 3,
"api": "csp_YiSo",
"searchable": 1,
"filterable": 0,
"changeable": 0,
"ext": "影視天下第一",
"jar": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar"
},
{
"key": "盤搜",
"name": "盤搜",
"type": 3,
"api": "csp_PanSou",
"searchable": 1,
"filterable": 0,
"changeable": 0,
"ext": "影視天下第一",
"jar": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar"
},
{
"key": "UP雲搜",
"name": "UP雲搜",
"type": 3,
"api": "csp_UpYun",
"searchable": 1,
"filterable": 0,
"changeable": 0,
"ext": "影視天下第一",
"jar": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar"
},
{
"key": "找資源",
"name": "找資源",
"type": 3,
"api": "csp_Zhaozy",
"searchable": 1,
"filterable": 0,
"changeable": 0,
"ext": "影視天下第一$$$test2$$$test2",
"jar": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar"
},
{
"key": "push_agent",
"name": "推送",
"type": 3,
"api": "csp_Push",
"searchable": 1,
"filterable": 0,
"changeable": 0,
"ext": "影視天下第一",
"jar": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar"
}
]
}

View File

@ -1,29 +1,10 @@
{
"vodPic": "https://s1.ax1x.com/2023/04/04/pp5M5Jx.png",
"drives": [
{
"name": "小雅",
"server": "http://alist.xiaoya.pro"
},
{
"name": "杜比",
"server": "https://dubi.tk"
},
{
"name": "帥鵬",
"server": "https://hi.shuaipeng.wang"
},
{
"name": "星夢",
"server": "https://pan.bashroot.top"
},
{
"name": "梓澪",
"server": "https://zi0.cc"
},
{
"name": "米奇",
"server": "https://anime.mqmmw.ga"
},
{
"name": "觸光",
"server": "https://pan.ichuguang.com"
@ -37,20 +18,16 @@
"server": "https://al.chirmyram.com"
},
{
"name": "雲播放",
"server": "https://quanzi.laoxianghuijia.cn"
},
{
"name": "姬路白雪",
"server": "https://pan.jlbx.xyz"
"name": "米奇",
"server": "https://anime.mqmmw.ga"
},
{
"name": "神族九帝",
"server": "https://alist.shenzjd.com"
},
{
"name": "資源小站",
"server": "https://960303.xyz"
"name": "梓澪",
"server": "https://zi0.cc"
}
]
}

View File

@ -1,5 +1,5 @@
{
"cookie": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/txt/cookie.txt",
"cookie": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/txt/cookie.txt",
"classes": [
{
"type_name": "帕梅拉",

View File

@ -1,15 +1,6 @@
{
"spider": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;a84fef826cb82da525469e8acf1e7d9a",
"wallpaper": "http://www.kf666888.cn/api/tvbox/img",
"lives": [
{
"name": "直播",
"type": 1,
"url": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/live.json",
"epg": "http://epg.51zmt.top:8000/api/diyp/?ch={epg}&date={date}",
"logo": "http://epg.51zmt.top:8000/{logo}"
}
],
"spider": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;9eb909e7a180e28b617c5fd15bda5b22",
"wallpaper": "http://饭太硬.ga/深色壁纸/api.php",
"sites": [
{
"key": "AList",
@ -18,8 +9,18 @@
"api": "csp_AList",
"searchable": 1,
"filterable": 1,
"switchable": 0,
"ext": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/alist.json"
"changeable": 0,
"ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/alist.json"
},
{
"key": "WebDAV",
"name": "WebDAV",
"type": 3,
"api": "csp_WebDAV",
"searchable": 1,
"filterable": 1,
"changeable": 0,
"ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/webdav.json"
},
{
"key": "哔哩",
@ -28,8 +29,8 @@
"api": "csp_Bili",
"searchable": 1,
"filterable": 1,
"switchable": 0,
"ext": "https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/bili.json"
"changeable": 0,
"ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/bili.json"
},
{
"key": "泥巴",
@ -38,57 +39,17 @@
"api": "csp_NiNi",
"searchable": 1,
"filterable": 1,
"switchable": 1
"changeable": 1
},
{
"key": "播",
"name": "播",
"type": 1,
"api": "https://www.kuaibozy.com/api.php/provide/vod/",
"key": "播",
"name": "播",
"type": 3,
"api": "csp_XPathMacFilter",
"searchable": 1,
"filterable": 0,
"switchable": 1,
"categories": [
"动漫",
"国产剧",
"日韩剧",
"港台剧",
"欧美剧",
"泰剧",
"动作片",
"喜剧片",
"爱情片",
"科幻片",
"恐怖片",
"剧情片",
"战争片",
"纪录片",
"综艺"
]
},
{
"key": "百度",
"name": "百度",
"type": 1,
"api": "https://api.apibdzy.com/api.php/provide/vod/",
"searchable": 1,
"filterable": 0,
"switchable": 1,
"categories": [
"国产动漫",
"日韩动漫",
"大陆剧",
"欧美剧",
"韩剧",
"日剧",
"动作片",
"喜剧片",
"爱情片",
"科幻片",
"恐怖片",
"剧情片",
"战争片"
]
"filterable": 1,
"changeable": 1,
"ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/duboku.json"
},
{
"key": "櫻花",
@ -97,7 +58,7 @@
"api": "csp_Ying",
"searchable": 1,
"filterable": 1,
"switchable": 1
"changeable": 1
},
{
"key": "巴士",
@ -106,7 +67,7 @@
"api": "csp_Dm84",
"searchable": 1,
"filterable": 1,
"switchable": 1
"changeable": 1
},
{
"key": "異界",
@ -115,7 +76,7 @@
"api": "csp_Ysj",
"searchable": 1,
"filterable": 1,
"switchable": 1
"changeable": 1
},
{
"key": "紙條",
@ -124,8 +85,16 @@
"api": "csp_Paper",
"searchable": 1,
"filterable": 1,
"switchable": 0,
"ext": "http://我不是.肥猫.love:63/token.php"
"changeable": 0
},
{
"key": "七夜",
"name": "七夜",
"type": 3,
"api": "csp_Dovx",
"searchable": 1,
"filterable": 0,
"changeable": 0
},
{
"key": "易搜",
@ -134,8 +103,7 @@
"api": "csp_YiSo",
"searchable": 1,
"filterable": 0,
"switchable": 0,
"ext": "http://我不是.肥猫.love:63/token.php"
"changeable": 0
},
{
"key": "盤搜",
@ -144,8 +112,7 @@
"api": "csp_PanSou",
"searchable": 1,
"filterable": 0,
"switchable": 0,
"ext": "http://我不是.肥猫.love:63/token.php"
"changeable": 0
},
{
"key": "UP雲搜",
@ -154,8 +121,7 @@
"api": "csp_UpYun",
"searchable": 1,
"filterable": 0,
"switchable": 0,
"ext": "http://我不是.肥猫.love:63/token.php"
"changeable": 0
},
{
"key": "找資源",
@ -164,18 +130,8 @@
"api": "csp_Zhaozy",
"searchable": 1,
"filterable": 0,
"switchable": 0,
"ext": "http://我不是.肥猫.love:63/token.php"
},
{
"key": "Live",
"name": "直播",
"type": 3,
"api": "csp_Live",
"searchable": 0,
"filterable": 0,
"switchable": 0,
"ext": "2000"
"changeable": 0,
"ext": "影視天下第一$$$test2$$$test2"
},
{
"key": "push_agent",
@ -184,8 +140,7 @@
"api": "csp_Push",
"searchable": 1,
"filterable": 0,
"switchable": 0,
"ext": "http://我不是.肥猫.love:63/token.php"
"changeable": 0
}
]
}

772
json/duboku.json Normal file
View File

@ -0,0 +1,772 @@
{
"author": "takagen99",
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"homeUrl": "https://www.duboku.tv/",
"dcVipFlag": "true",
"dcPlayUrl": "true",
"cateNode": "//ul[contains(@class,'nav-menu')]/li/a[contains(@href, 'vodtype')]",
"cateName": "/text()",
"cateId": "/@href",
"cateIdR": "/vodtype/(\\w+).html",
"cateManual": {
"陆剧": "13",
"日韩剧": "15",
"短剧": "21",
"英美剧": "16",
"台泰剧": "14",
"港剧": "20",
"综艺": "3",
"动漫": "4"
},
"homeVodNode": "//ul[contains(@class,'myui-vodlist')]/li/div/a",
"homeVodName": "/@title",
"homeVodId": "/@href",
"homeVodIdR": "/voddetail/(\\w+).html",
"homeVodImg": "/@data-original",
"homeVodImgR": "\\S+(http\\S+)",
"homeVodMark": "//span[contains(@class,'pic-text')]/text()",
"cateUrl": "https://www.duboku.tv/vodshow/{cateId}-{area}-{by}------{catePg}---{year}.html",
"cateVodNode": "//ul[contains(@class,'myui-vodlist')]/li/div/a",
"cateVodName": "/@title",
"cateVodId": "/@href",
"cateVodIdR": "/voddetail/(\\w+).html",
"cateVodImg": "/@data-original",
"cateVodImgR": "\\S+(http\\S+)",
"cateVodMark": "//span[contains(@class,'pic-text')]/text()",
"dtUrl": "https://my.duboku.vip/voddetail/{vid}.html",
"dtNode": "//body",
"dtName": "//div[contains(@class,'myui-content__thumb')]/a/@title",
"dtNameR": "",
"dtImg": "//div[contains(@class,'myui-content__thumb')]/a/img/@data-original",
"dtImgR": "",
"dtCate": "//div[contains(@class,'myui-content__detail')]/p/span[contains(text(), '分类')]/following-sibling::a/text()",
"dtYear": "//div[contains(@class,'myui-content__detail')]/p/span[contains(text(), '年份')]/following-sibling::a/text()",
"dtArea": "//div[contains(@class,'myui-content__detail')]/p/span[contains(text(), '地区')]/following-sibling::a/text()",
"dtMark": "//div[contains(@class,'myui-content__detail')]/p/span[contains(text(), '更新')]/following-sibling::a/text()",
"dtDirector": "//div[contains(@class,'myui-content__detail')]/p/span[contains(text(), '导演')]/following-sibling::a/text()",
"dtActor": "//div[contains(@class,'myui-content__detail')]/p/span[contains(text(), '主演')]/following-sibling::a/text()",
"dtDesc": "//div[contains(@class,'myui-content__detail')]/p/span[contains(text(), '简介')]/following-sibling::a/text()",
"dtFromNode": "//ul[contains(@class,'nav-tabs')]/li/a",
"dtFromName": "/text()",
"dtFromNameR": "",
"dtUrlNode": "//ul[contains(@class,'myui-content__list')]",
"dtUrlSubNode": "/li/a",
"dtUrlId": "/@href",
"dtUrlIdR": "/vodplay/(\\S+).html",
"dtUrlName": "/text()",
"dtUrlNameR": "",
"playUrl": "https://my.duboku.vip/vodplay/{playUrl}.html",
"playUa": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"playReferer": "https://www.duboku.tv/",
"searchUrl": "https://www.duboku.tv/index.php/ajax/suggest?mid=1&wd={wd}&limit=10",
"scVodNode": "json:list",
"scVodName": "name",
"scVodId": "id",
"scVodIdR": "",
"scVodImg": "pic",
"scVodMark": "",
"filter": {
"13": [
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
},
{
"n": "2018",
"v": "2018"
},
{
"n": "2017",
"v": "2017"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
],
"14": [
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
},
{
"n": "2018",
"v": "2018"
},
{
"n": "2017",
"v": "2017"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
],
"16": [
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
},
{
"n": "2018",
"v": "2018"
},
{
"n": "2017",
"v": "2017"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
],
"15": [
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
},
{
"n": "2018",
"v": "2018"
},
{
"n": "2017",
"v": "2017"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
],
"2": [
{
"key": "cateId",
"name": "类型",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "陆剧",
"v": "13"
},
{
"n": "日韩剧",
"v": "15"
},
{
"n": "英美剧",
"v": "16"
},
{
"n": "台泰剧",
"v": "14"
},
{
"n": "港剧",
"v": "20"
}
]
},
{
"key": "area",
"name": "地区",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "内地",
"v": "内地"
},
{
"n": "韩国",
"v": "韩国"
},
{
"n": "香港",
"v": "香港"
},
{
"n": "台湾",
"v": "台湾"
},
{
"n": "美国",
"v": "美国"
},
{
"n": "英国",
"v": "英国"
},
{
"n": "巴西",
"v": "巴西"
},
{
"n": "西班牙",
"v": "西班牙"
},
{
"n": "泰国",
"v": "泰国"
},
{
"n": "德国",
"v": "德国"
},
{
"n": "法国",
"v": "法国"
},
{
"n": "日本",
"v": "日本"
},
{
"n": "荷兰",
"v": "荷兰"
}
]
},
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
},
{
"n": "2018",
"v": "2018"
},
{
"n": "2017",
"v": "2017"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
],
"3": [
{
"key": "area",
"name": "地区",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "内地",
"v": "内地"
},
{
"n": "香港",
"v": "香港"
},
{
"n": "台湾",
"v": "台湾"
},
{
"n": "韩国",
"v": "韩国"
},
{
"n": "美国",
"v": "美国"
}
]
},
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
],
"4": [
{
"key": "area",
"name": "地区",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "国产",
"v": "国产"
},
{
"n": "日本",
"v": "日本"
},
{
"n": "美国",
"v": "美国"
},
{
"n": "法国",
"v": "法国"
},
{
"n": "其他",
"v": "其他"
}
]
},
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
},
{
"n": "2018",
"v": "2018"
},
{
"n": "2017",
"v": "2017"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
],
"20": [
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
},
{
"n": "2018",
"v": "2018"
},
{
"n": "2017",
"v": "2017"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
],
"21": [
{
"key": "year",
"name": "年份",
"value": [
{
"n": "全部",
"v": ""
},
{
"n": "2023",
"v": "2023"
},
{
"n": "2022",
"v": "2022"
},
{
"n": "2021",
"v": "2021"
},
{
"n": "2020",
"v": "2020"
},
{
"n": "2019",
"v": "2019"
},
{
"n": "2018",
"v": "2018"
},
{
"n": "2017",
"v": "2017"
}
]
},
{
"key": "by",
"name": "排序",
"value": [
{
"n": "排序",
"v": ""
},
{
"n": "时间",
"v": "time"
},
{
"n": "人气",
"v": "hits"
},
{
"n": "评分",
"v": "score"
}
]
}
]
}
}

File diff suppressed because it is too large Load Diff

17
json/webdav.json Normal file
View File

@ -0,0 +1,17 @@
{
"vodPic": "https://avatars.githubusercontent.com/u/3471963?v=4",
"drives": [
{
"name": "七米藍",
"server": "https://al.chirmyram.com/dav",
"user": "alist",
"pass": "alist"
},
{
"name": "影視庫",
"server": "https://esir.eu.org/dav",
"user": "alist",
"pass": "alist"
}
]
}

View File

@ -11,6 +11,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
rootProject.name = "CatVodSpider"

View File

@ -44,6 +44,7 @@ public class Run {
Group group = groups.get(groups.size() - 1);
String name = split[0];
String url = split[1].trim();
if (url.startsWith("http://txtest")) url = url.replace("http://txtest", "http://121.51.249.6/txtest");
group.find(Channel.create().name(name).epg(name)).addUrls(url.split("#"));
}
}
@ -51,7 +52,7 @@ public class Run {
for (Group group : groups) {
for (Channel channel : group.getChannel()) {
channel.number(String.format(Locale.getDefault(), "%03d", ++number));
channel.logo("https://gh-proxy.com/https://raw.githubusercontent.com/FongMi/TV/release/app/src/leanback/res/drawable-xxhdpi/ic_live.png");
channel.logo("https://ghproxy.com/https://raw.githubusercontent.com/FongMi/TV/release/app/src/main/res/drawable-xxhdpi/ic_img_empty.png");
combine(channel);
}
}

View File

@ -1,8 +1,6 @@
香港,#genre#
001,凤凰中文,tb1/gt/fenghuangzhongwen.png,鳳凰中文,http://play-live.ifeng.com/live/06OLEGEGM4G.m3u8
002,凤凰资讯,tb1/gt/fenghuangzixun.png,鳳凰資訊,http://play-live.ifeng.com/live/06OLEEWQKN4.m3u8
台灣,#genre#
003,星卫HD电影,tb1/gt/starmov.png,星衛電影,http://198.16.64.10:8278/xingwei_movie/playlist.m3u8?tid=MBDB4578128345781283&ct=19225&tsum=f2041ec954c95b4a5fe29d7ccbfe5b60
歐美_1234,#genre#
1001,,,Three,http://live.redtraffic.xyz/threesome.m3u8
1002,,,BlowJob,http://live.redtraffic.xyz/blowjob.m3u8

View File

@ -1 +1 @@
DedeUserID=3493076028885079;DedeUserID__ckMd5=60a8757a1f4d6ae9;SESSDATA=42b8ada6,1683277266,4bd05*b2;bili_jct=2dbe39aea02b41324395630a24d4775f;
DedeUserID=690781341;DedeUserID__ckMd5=cabc96906269c5b6;SESSDATA=2245ba24%2C1684212125%2C466fd%2Ab2;bili_jct=de6fdb60c10f8a83910aa55d79407b4e;