diff --git a/app/src/main/java/com/github/catvod/api/AliYun.java b/app/src/main/java/com/github/catvod/api/AliYun.java index 4274ef73..6fdd9850 100644 --- a/app/src/main/java/com/github/catvod/api/AliYun.java +++ b/app/src/main/java/com/github/catvod/api/AliYun.java @@ -19,9 +19,13 @@ 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.Download; import com.github.catvod.bean.ali.Drive; import com.github.catvod.bean.ali.Item; import com.github.catvod.bean.ali.OAuth; +import com.github.catvod.bean.ali.Preview; +import com.github.catvod.bean.ali.Res; +import com.github.catvod.bean.ali.Share; import com.github.catvod.bean.ali.User; import com.github.catvod.crawler.SpiderDebug; import com.github.catvod.net.OkHttp; @@ -31,9 +35,7 @@ import com.github.catvod.spider.Proxy; import com.github.catvod.utils.FileUtil; import com.github.catvod.utils.QRCode; import com.github.catvod.utils.Utils; - -import org.json.JSONArray; -import org.json.JSONObject; +import com.google.gson.JsonObject; import java.io.ByteArrayInputStream; import java.io.File; @@ -131,21 +133,18 @@ public class AliYun { return headers; } - private boolean alist(String url, JSONObject body) { - //https://api-cf.nn.ci/alist/ali_open/ - //https://api.xhofe.top/alist/ali_open/ - //https://sni_api_nn_ci.cooluc.com/alist/ali_open/ + private boolean alist(String url, JsonObject param) { String api = "https://aliapi.ewwe.gq/alist/ali_open/" + url; - OkResult result = OkHttp.postJson(api, body.toString(), getHeader()); + OkResult result = OkHttp.postJson(api, param.toString(), getHeader()); SpiderDebug.log(result.getCode() + "," + api + "," + result.getBody()); if (isManyRequest(result.getBody())) return false; oauth = OAuth.objectFrom(result.getBody()).save(); return true; } - private String post(String url, JSONObject body) { + private String post(String url, JsonObject param) { url = url.startsWith("https") ? url : "https://api.aliyundrive.com/" + url; - OkResult result = OkHttp.postJson(url, body.toString(), getHeader()); + OkResult result = OkHttp.postJson(url, param.toString(), getHeader()); SpiderDebug.log(result.getCode() + "," + url + "," + result.getBody()); return result.getBody(); } @@ -180,31 +179,27 @@ public class AliYun { } private void refreshShareToken() { - try { - SpiderDebug.log("refreshShareToken..."); - JSONObject body = new JSONObject(); - body.put("share_id", shareId); - body.put("share_pwd", ""); - String result = post("v2/share_link/get_share_token", body); - shareToken = new JSONObject(result).getString("share_token"); - } catch (Exception e) { - e.printStackTrace(); - Utils.notify("來晚啦,該分享已失效。"); - } + SpiderDebug.log("refreshShareToken..."); + JsonObject param = new JsonObject(); + param.addProperty("share_id", shareId); + param.addProperty("share_pwd", ""); + String json = post("v2/share_link/get_share_token", param); + shareToken = Share.objectFrom(json).getShareToken(); + if (shareToken.isEmpty()) Utils.notify("來晚啦,該分享已失效。"); } private boolean refreshAccessToken() { try { SpiderDebug.log("refreshAccessToken..."); - JSONObject body = new JSONObject(); + JsonObject param = 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(); - if (user.getAccessToken().isEmpty()) throw new Exception(result); + param.addProperty("refresh_token", token); + param.addProperty("grant_type", "refresh_token"); + String json = post("https://auth.aliyundrive.com/v2/account/token", param); + user = User.objectFrom(json).save(); + if (user.getAccessToken().isEmpty()) throw new Exception(json); return true; } catch (Exception e) { if (e instanceof TimeoutException) return onTimeout(); @@ -218,72 +213,47 @@ public class AliYun { } } - private boolean getDriveId() { - try { - SpiderDebug.log("Obtain drive id..."); - String result = auth("https://user.aliyundrive.com/v2/user/get", "{}", false); - drive = Drive.objectFrom(result).save(); - driveId = drive.getResourceDriveId().isEmpty() ? drive.getDriveId() : drive.getResourceDriveId(); - return false; - } catch (Exception e) { - e.printStackTrace(); - drive.clean().save(); - return true; - } + private void getDriveId() { + SpiderDebug.log("Obtain drive id..."); + String result = auth("https://user.aliyundrive.com/v2/user/get", "{}", false); + drive = Drive.objectFrom(result).save(); + driveId = drive.getResourceDriveId().isEmpty() ? drive.getDriveId() : drive.getResourceDriveId(); } private boolean 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); - return oauthRedirect(Code.objectFrom(result).getCode()); - } catch (Exception e) { - e.printStackTrace(); - return false; - } + SpiderDebug.log("OAuth Request..."); + JsonObject param = new JsonObject(); + param.addProperty("authorize", 1); + param.addProperty("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 json = auth(url, param.toString(), true); + return oauthRedirect(Code.objectFrom(json).getCode()); } private boolean oauthRedirect(String code) { - try { - SpiderDebug.log("OAuth Redirect..."); - JSONObject body = new JSONObject(); - body.put("code", code); - body.put("grant_type", "authorization_code"); - return alist("code", body); - } catch (Exception e) { - e.printStackTrace(); - oauth.clean().save(); - return false; - } + SpiderDebug.log("OAuth Redirect..."); + JsonObject param = new JsonObject(); + param.addProperty("code", code); + param.addProperty("grant_type", "authorization_code"); + return alist("code", param); } private boolean refreshOpenToken() { - try { - if (oauth.getRefreshToken().isEmpty()) return oauthRequest(); - SpiderDebug.log("refreshOpenToken..."); - JSONObject body = new JSONObject(); - body.put("grant_type", "refresh_token"); - body.put("refresh_token", oauth.getRefreshToken()); - return alist("token", body); - } catch (Exception e) { - e.printStackTrace(); - oauth.clean().save(); - return false; - } + if (oauth.getRefreshToken().isEmpty()) return oauthRequest(); + SpiderDebug.log("refreshOpenToken..."); + JsonObject param = new JsonObject(); + param.addProperty("grant_type", "refresh_token"); + param.addProperty("refresh_token", oauth.getRefreshToken()); + return alist("token", param); } - public Vod getVod(String url, String fileId) throws Exception { - JSONObject body = new JSONObject(); - body.put("share_id", shareId); - String result = post("adrive/v3/share_link/get_share_by_anonymous", body); - JSONObject object = new JSONObject(result); + public Vod getVod(String url, String fileId) { + JsonObject param = new JsonObject(); + param.addProperty("share_id", shareId); + Share share = Share.objectFrom(post("adrive/v3/share_link/get_share_by_anonymous", param)); List files = new ArrayList<>(); List subs = new ArrayList<>(); - listFiles(new Item(getParentFileId(fileId, object)), files, subs); + listFiles(new Item(getParentFileId(fileId, share)), files, subs); Collections.sort(files); List playFrom = Arrays.asList("原畫", "普畫"); List episode = new ArrayList<>(); @@ -293,28 +263,28 @@ public class AliYun { Vod vod = new Vod(); vod.setVodId(url); vod.setVodContent(url); - vod.setVodPic(object.getString("avatar")); - vod.setVodName(object.getString("share_name")); + vod.setVodPic(share.getAvatar()); + vod.setVodName(share.getShareName()); vod.setVodPlayUrl(TextUtils.join("$$$", playUrl)); vod.setVodPlayFrom(TextUtils.join("$$$", playFrom)); vod.setTypeName("阿里雲盤"); return vod; } - private void listFiles(Item folder, List files, List subs) throws Exception { + private void listFiles(Item folder, List files, List subs) { listFiles(folder, files, subs, ""); } - private void listFiles(Item parent, List files, List subs, String marker) throws Exception { - JSONObject body = new JSONObject(); + private void listFiles(Item parent, List files, List subs, String marker) { List 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)); + JsonObject param = new JsonObject(); + param.addProperty("limit", 200); + param.addProperty("share_id", shareId); + param.addProperty("parent_file_id", parent.getFileId()); + param.addProperty("order_by", "name"); + param.addProperty("order_direction", "ASC"); + if (marker.length() > 0) param.addProperty("marker", marker); + Item item = Item.objectFrom(auth("adrive/v3/file/list", param.toString(), true)); for (Item file : item.getItems()) { if (file.getType().equals("folder")) { folders.add(file); @@ -332,14 +302,11 @@ public class AliYun { } } - private String getParentFileId(String fileId, JSONObject shareInfo) throws Exception { - JSONArray array = shareInfo.getJSONArray("file_infos"); + private String getParentFileId(String fileId, Share share) { 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 ""; + if (share.getFileInfos().isEmpty()) return ""; + Item item = share.getFileInfos().get(0); + return item.getType().equals("folder") ? item.getFileId() : "root"; } private void pair(String name1, List items, List subs) { @@ -373,14 +340,14 @@ public class AliYun { public String getDownloadUrl(String fileId) { try { + getDriveId(); SpiderDebug.log("getDownloadUrl..." + fileId); - if (getDriveId()) throw new Exception("unable obtain drive id"); - tempIds.add(0, copy(fileId)); - JSONObject body = new JSONObject(); - body.put("file_id", tempIds.get(0)); - body.put("drive_id", driveId); - String json = oauth("openFile/getDownloadUrl", body.toString(), true); - return new JSONObject(json).getString("url"); + tempIds.add(0, copy(fileId, true)); + JsonObject param = new JsonObject(); + param.addProperty("file_id", tempIds.get(0)); + param.addProperty("drive_id", driveId); + String json = oauth("openFile/getDownloadUrl", param.toString(), true); + return Download.objectFrom(json).getUrl(); } catch (Exception e) { e.printStackTrace(); return ""; @@ -389,21 +356,21 @@ public class AliYun { } } - public JSONObject getVideoPreviewPlayInfo(String fileId) { + public Preview.Info getVideoPreviewPlayInfo(String fileId) { try { + getDriveId(); SpiderDebug.log("getVideoPreviewPlayInfo..." + fileId); - if (getDriveId()) throw new Exception("unable obtain drive id"); - tempIds.add(0, copy(fileId)); - JSONObject body = new JSONObject(); - body.put("file_id", tempIds.get(0)); - body.put("drive_id", driveId); - body.put("category", "live_transcoding"); - body.put("url_expire_sec", "14400"); - String json = oauth("openFile/getVideoPreviewPlayInfo", body.toString(), true); - return new JSONObject(json).getJSONObject("video_preview_play_info"); + tempIds.add(0, copy(fileId, true)); + JsonObject param = new JsonObject(); + param.addProperty("file_id", tempIds.get(0)); + param.addProperty("drive_id", driveId); + param.addProperty("category", "live_transcoding"); + param.addProperty("url_expire_sec", "14400"); + String json = oauth("openFile/getVideoPreviewPlayInfo", param.toString(), true); + return Preview.objectFrom(json).getVideoPreviewPlayInfo(); } catch (Exception e) { e.printStackTrace(); - return new JSONObject(); + return new Preview.Info(); } finally { Init.execute(this::deleteAll); } @@ -415,51 +382,38 @@ public class AliYun { } private String getPreviewContent(String[] ids) { - try { - JSONObject playInfo = getVideoPreviewPlayInfo(ids[0]); - List url = getPreviewUrl(playInfo); - List subs = getSubs(ids); - subs.addAll(getSubs(playInfo)); - return Result.get().url(url).m3u8().subs(subs).header(getHeader()).string(); - } catch (Exception e) { - e.printStackTrace(); - return Result.get().url("").string(); - } + Preview.Info info = getVideoPreviewPlayInfo(ids[0]); + List url = getPreviewUrl(info); + List subs = getSubs(ids); + subs.addAll(getSubs(info)); + return Result.get().url(url).m3u8().subs(subs).header(getHeader()).string(); } - private List getPreviewUrl(JSONObject playInfo) throws Exception { - if (!playInfo.has("live_transcoding_task_list")) return Collections.emptyList(); - JSONArray taskList = playInfo.getJSONArray("live_transcoding_task_list"); + private List getPreviewUrl(Preview.Info info) { + List tasks = info.getLiveTranscodingTaskList(); List url = new ArrayList<>(); - for (int i = taskList.length() - 1; i >= 0; i--) { - JSONObject task = taskList.getJSONObject(i); - if (!task.optString("status").equals("finished")) continue; - url.add(task.optString("template_id")); - url.add(task.optString("url")); + for (int i = tasks.size() - 1; i >= 0; i--) { + url.add(tasks.get(i).getTemplateId()); + url.add(tasks.get(i).getUrl()); } return url; } - private List getSubs(JSONObject playInfo) throws Exception { - if (!playInfo.has("live_transcoding_subtitle_task_list")) return Collections.emptyList(); - JSONArray taskList = playInfo.getJSONArray("live_transcoding_subtitle_task_list"); + private List getSubs(Preview.Info info) { List subs = new ArrayList<>(); - for (int i = 0; i < taskList.length(); ++i) { - JSONObject task = taskList.getJSONObject(i); - String lang = task.getString("language"); - String url = task.getString("url"); - subs.add(Sub.create().url(url).name(lang).lang(lang).ext("vtt")); - } + for (Preview.LiveTranscodingTask task : info.getLiveTranscodingSubtitleTaskList()) subs.add(task.getSub()); return subs; } - private String copy(String fileId) throws Exception { + private String copy(String fileId, boolean retry) 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, driveId); - String result = auth("adrive/v2/batch", json, true); - if (result.contains("ForbiddenNoPermission.File")) return copy(fileId); - return new JSONObject(result).getJSONArray("responses").getJSONObject(0).getJSONObject("body").getString("file_id"); + Res res = Res.objectFrom(auth("adrive/v2/batch", json, true)); + if (res.getResponse().getStatus() == 403 && retry) refreshShareToken(); + if (res.getResponse().getStatus() == 403 && retry) copy(fileId, false); + if (res.getResponse().getStatus() == 403 && !retry) throw new Exception(res.getResponse().getBody().getMessage()); + return res.getResponse().getBody().getFileId(); } private void deleteAll() { @@ -471,15 +425,11 @@ public class AliYun { } 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, driveId, fileId, fileId); - String result = auth("adrive/v2/batch", json, true); - return result.length() == 211; - } catch (Exception ignored) { - return false; - } + 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, driveId, fileId, fileId); + Res res = Res.objectFrom(auth("adrive/v2/batch", json, true)); + return res.getResponse().getStatus() == 404; } public Object[] proxySub(Map params) throws Exception { diff --git a/app/src/main/java/com/github/catvod/bean/Result.java b/app/src/main/java/com/github/catvod/bean/Result.java index 1da6c813..78009793 100644 --- a/app/src/main/java/com/github/catvod/bean/Result.java +++ b/app/src/main/java/com/github/catvod/bean/Result.java @@ -1,6 +1,7 @@ package com.github.catvod.bean; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.annotations.SerializedName; import com.google.gson.reflect.TypeToken; @@ -54,6 +55,10 @@ public class Result { return Result.get().classes(classes).vod(list).filters(filters).string(); } + public static String string(List classes, List list, JsonElement filters) { + return Result.get().classes(classes).vod(list).filters(filters).string(); + } + public static String string(List classes, LinkedHashMap> filters) { return Result.get().classes(classes).filters(filters).string(); } @@ -105,6 +110,13 @@ public class Result { return this; } + public Result filters(JsonElement element) { + if (element == null) return this; + Type listType = new TypeToken>>() {}.getType(); + this.filters = new Gson().fromJson(element.toString(), listType); + return this; + } + public Result header(Map header) { if (header.isEmpty()) return this; this.header = new Gson().toJson(header); diff --git a/app/src/main/java/com/github/catvod/bean/ali/Download.java b/app/src/main/java/com/github/catvod/bean/ali/Download.java new file mode 100644 index 00000000..c0f8c613 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/ali/Download.java @@ -0,0 +1,32 @@ +package com.github.catvod.bean.ali; + +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +public class Download { + + @SerializedName("url") + private String url; + @SerializedName("file_id") + private String fileId; + @SerializedName("expiration") + private String expiration; + + public static Download objectFrom(String str) { + return new Gson().fromJson(str, Download.class); + } + + public String getUrl() { + return TextUtils.isEmpty(url) ? "" : url; + } + + public String getFileId() { + return TextUtils.isEmpty(fileId) ? "" : fileId; + } + + public String getExpiration() { + return TextUtils.isEmpty(expiration) ? "" : expiration; + } +} diff --git a/app/src/main/java/com/github/catvod/bean/ali/Preview.java b/app/src/main/java/com/github/catvod/bean/ali/Preview.java new file mode 100644 index 00000000..0d6c6a3a --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/ali/Preview.java @@ -0,0 +1,84 @@ +package com.github.catvod.bean.ali; + +import android.text.TextUtils; + +import com.github.catvod.bean.Sub; +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.util.Collections; +import java.util.List; + +public class Preview { + + @SerializedName("video_preview_play_info") + private Info videoPreviewPlayInfo; + @SerializedName("drive_id") + private String driveId; + @SerializedName("file_id") + private String fileId; + + public static Preview objectFrom(String str) { + return new Gson().fromJson(str, Preview.class); + } + + public Info getVideoPreviewPlayInfo() { + return videoPreviewPlayInfo == null ? new Info() : videoPreviewPlayInfo; + } + + public String getDriveId() { + return TextUtils.isEmpty(driveId) ? "" : driveId; + } + + public String getFileId() { + return TextUtils.isEmpty(fileId) ? "" : fileId; + } + + public static class Info { + + @SerializedName("live_transcoding_task_list") + private List liveTranscodingTaskList; + @SerializedName("live_transcoding_subtitle_task_list") + private List liveTranscodingSubtitleTaskList; + + public List getLiveTranscodingTaskList() { + return liveTranscodingTaskList == null ? Collections.emptyList() : liveTranscodingTaskList; + } + + public List getLiveTranscodingSubtitleTaskList() { + return liveTranscodingSubtitleTaskList == null ? Collections.emptyList() : liveTranscodingSubtitleTaskList; + } + } + + public static class LiveTranscodingTask { + + @SerializedName("template_id") + private String templateId; + @SerializedName("language") + private String language; + @SerializedName("status") + private String status; + @SerializedName("url") + private String url; + + public String getTemplateId() { + return TextUtils.isEmpty(templateId) ? "" : templateId; + } + + public String getLanguage() { + return TextUtils.isEmpty(language) ? "" : language; + } + + public String getStatus() { + return TextUtils.isEmpty(status) ? "" : status; + } + + public String getUrl() { + return TextUtils.isEmpty(url) ? "" : url; + } + + public Sub getSub() { + return Sub.create().url(getUrl()).name(getLanguage()).lang(getLanguage()).ext("vtt"); + } + } +} diff --git a/app/src/main/java/com/github/catvod/bean/ali/Res.java b/app/src/main/java/com/github/catvod/bean/ali/Res.java new file mode 100644 index 00000000..95e7703b --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/ali/Res.java @@ -0,0 +1,79 @@ +package com.github.catvod.bean.ali; + +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.util.Collections; +import java.util.List; + +public class Res { + + @SerializedName("responses") + private List responses; + @SerializedName("body") + private Body body; + @SerializedName("id") + private String id; + @SerializedName("status") + private int status; + + public static Res objectFrom(String str) { + return new Gson().fromJson(str, Res.class); + } + + public List getResponses() { + return responses == null ? Collections.emptyList() : responses; + } + + public Res getResponse() { + return getResponses().isEmpty() ? new Res() : getResponses().get(0); + } + + public Body getBody() { + return body == null ? new Body() : body; + } + + public String getId() { + return TextUtils.isEmpty(id) ? "" : id; + } + + public int getStatus() { + return status; + } + + public static class Body { + + @SerializedName("domain_id") + private String domainId; + @SerializedName("drive_id") + private String driveId; + @SerializedName("file_id") + private String fileId; + @SerializedName("code") + private String code; + @SerializedName("message") + private String message; + + public String getDomainId() { + return TextUtils.isEmpty(domainId) ? "" : domainId; + } + + public String getDriveId() { + return TextUtils.isEmpty(driveId) ? "" : driveId; + } + + public String getFileId() { + return TextUtils.isEmpty(fileId) ? "" : fileId; + } + + public String getCode() { + return TextUtils.isEmpty(code) ? "" : code; + } + + public String getMessage() { + return TextUtils.isEmpty(message) ? "" : message; + } + } +} diff --git a/app/src/main/java/com/github/catvod/bean/ali/Share.java b/app/src/main/java/com/github/catvod/bean/ali/Share.java new file mode 100644 index 00000000..457123b6 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/ali/Share.java @@ -0,0 +1,108 @@ +package com.github.catvod.bean.ali; + +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.util.Collections; +import java.util.List; + +public class Share { + + @SerializedName("share_token") + private String shareToken; + @SerializedName("expire_time") + private String expireTime; + @SerializedName("expires_in") + private int expiresIn; + + @SerializedName("creator_id") + private String creatorId; + @SerializedName("creator_name") + private String creatorName; + @SerializedName("creator_phone") + private String creatorPhone; + @SerializedName("expiration") + private String expiration; + @SerializedName("updated_at") + private String updatedAt; + @SerializedName("vip") + private String vip; + @SerializedName("avatar") + private String avatar; + @SerializedName("share_name") + private String shareName; + @SerializedName("display_name") + private String displayName; + @SerializedName("share_title") + private String shareTitle; + @SerializedName("has_pwd") + private boolean hasPwd; + @SerializedName("file_infos") + private List fileInfos; + + public static Share objectFrom(String str) { + return new Gson().fromJson(str, Share.class); + } + + public String getShareToken() { + return TextUtils.isEmpty(shareToken) ? "" : shareToken; + } + + public String getExpireTime() { + return TextUtils.isEmpty(expireTime) ? "" : expireTime; + } + + public int getExpiresIn() { + return expiresIn; + } + + public String getCreatorId() { + return TextUtils.isEmpty(creatorId) ? "" : creatorId; + } + + public String getCreatorName() { + return TextUtils.isEmpty(creatorName) ? "" : creatorName; + } + + public String getCreatorPhone() { + return TextUtils.isEmpty(creatorPhone) ? "" : creatorPhone; + } + + public String getExpiration() { + return TextUtils.isEmpty(expiration) ? "" : expiration; + } + + public String getUpdatedAt() { + return TextUtils.isEmpty(updatedAt) ? "" : updatedAt; + } + + public String getVip() { + return TextUtils.isEmpty(vip) ? "" : vip; + } + + public String getAvatar() { + return TextUtils.isEmpty(avatar) ? "" : avatar; + } + + public String getShareName() { + return TextUtils.isEmpty(shareName) ? "" : shareName; + } + + public String getDisplayName() { + return TextUtils.isEmpty(displayName) ? "" : displayName; + } + + public String getShareTitle() { + return TextUtils.isEmpty(shareTitle) ? "" : shareTitle; + } + + public boolean isHasPwd() { + return hasPwd; + } + + public List getFileInfos() { + return fileInfos == null ? Collections.emptyList() : fileInfos; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/Ali.java b/app/src/main/java/com/github/catvod/spider/Ali.java index bc6dd2b6..930d98d2 100644 --- a/app/src/main/java/com/github/catvod/spider/Ali.java +++ b/app/src/main/java/com/github/catvod/spider/Ali.java @@ -1,13 +1,18 @@ package com.github.catvod.spider; import android.content.Context; +import android.text.TextUtils; import com.github.catvod.api.AliYun; -import android.text.TextUtils; import com.github.catvod.bean.Result; +import com.github.catvod.bean.Vod; import com.github.catvod.crawler.Spider; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -25,13 +30,9 @@ public class Ali extends Spider { @Override public String detailContent(List 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) : ""; - AliYun.get().setShareId(shareId); - return Result.string(AliYun.get().getVod(url, fileId)); + String id = ids.get(0).trim(); + Matcher matcher = pattern.matcher(id); + return matcher.find() ? Result.string(parseVod(matcher, id)) : ""; } @Override @@ -39,45 +40,45 @@ public class Ali extends Spider { AliYun.get().setShareId(id.split("@")[0]); return AliYun.get().playerContent(id.split("@")[1].split("\\+"), flag.split("#")[0].equals("原畫")); } - - /** - * 获取详情内容视频播放地址(多 share_link 模式) - * - * @param ids share_link 集合 - * @return 详情内容视频播放地址 - */ - public String detailContentVodPlayUrl(List ids) throws Exception { - List playUrl = new ArrayList<>(); - for (String id : ids) { - Matcher matcher = pattern.matcher(id); - if (matcher.find()) { - String shareId = matcher.group(1); - String fileId = matcher.groupCount() == 3 ? matcher.group(3) : ""; - AliYun.get().setShareId(shareId); - playUrl.add(AliYun.get().getVod(id, fileId).getVodPlayUrl()); - } - } - return TextUtils.join("$$$", playUrl); + + private Vod parseVod(Matcher matcher, String id) { + String shareId = matcher.group(1); + String fileId = matcher.groupCount() == 3 ? matcher.group(3) : ""; + AliYun.get().setShareId(shareId); + return AliYun.get().getVod(id, fileId); } - + /** - * 获取详情内容视频播放来源(多 shared_link 模式) + * 獲取詳情內容視頻播放來源(多 shared_link) * * @param ids share_link 集合 - * @return 详情内容视频播放来源 + * @return 詳情內容視頻播放來源 */ public String detailContentVodPlayFrom(List ids) { List playFrom = new ArrayList<>(); - if (ids.size() > 1) { - for (int i = 1; i <= ids.size(); i++) { - playFrom.addAll(Arrays.asList(String.format(Locale.CHINA, "原畫#%02d", i), String.format(Locale.CHINA, "普畫#%02d", i))); - } - } else { - playFrom.addAll(Arrays.asList("原畫", "普畫")); + if (ids.size() < 1) return TextUtils.join("$$$", Arrays.asList("原畫", "普畫")); + for (int i = 1; i <= ids.size(); i++) { + playFrom.add(String.format(Locale.getDefault(), "原畫#%02d", i)); + playFrom.add(String.format(Locale.getDefault(), "普畫#%02d", i)); } return TextUtils.join("$$$", playFrom); } + /** + * 獲取詳情內容視頻播放地址(多 share_link) + * + * @param ids share_link 集合 + * @return 詳情內容視頻播放地址 + */ + public String detailContentVodPlayUrl(List ids) { + List playUrl = new ArrayList<>(); + for (String id : ids) { + Matcher matcher = pattern.matcher(id); + if (matcher.find()) playUrl.add(parseVod(matcher, id).getVodPlayUrl()); + } + return TextUtils.join("$$$", playUrl); + } + public static Object[] proxy(Map params) throws Exception { String type = params.get("type"); if ("sub".equals(type)) return AliYun.get().proxySub(params); diff --git a/app/src/main/java/com/github/catvod/spider/Wogg.java b/app/src/main/java/com/github/catvod/spider/Wogg.java index e0af9ca3..a948960e 100644 --- a/app/src/main/java/com/github/catvod/spider/Wogg.java +++ b/app/src/main/java/com/github/catvod/spider/Wogg.java @@ -1,14 +1,14 @@ package com.github.catvod.spider; import android.content.Context; + import com.github.catvod.bean.Class; import com.github.catvod.bean.Result; import com.github.catvod.bean.Vod; -import com.github.catvod.crawler.SpiderDebug; import com.github.catvod.net.OkHttp; import com.github.catvod.utils.Utils; -import org.json.JSONException; -import org.json.JSONObject; +import com.google.gson.JsonParser; + import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -26,134 +26,124 @@ import java.util.regex.Pattern; * @author zhixc */ public class Wogg extends Ali { - - private final String siteURL = "http://tvfan.xxooo.cf"; - - private JSONObject filters; - private final Pattern regexCategory = Pattern.compile("/vodtype/(\\w+).html"); - private final Pattern regexPageTotal = Pattern.compile("\\$\\(\"\\.mac_total\"\\)\\.text\\('(\\d+)'\\);"); - - private Map getHeader() { - Map header = new HashMap<>(); - header.put("User-Agent", Utils.CHROME); - return header; - } - - @Override - public void init(Context context, String extend) { - super.init(context, extend); - - try { - filters = new JSONObject("{\"1\": [{\"key\": \"3\", \"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\": \"枪战\"}, {\"n\": \"恐怖\", \"v\": \"恐怖\"}, {\"n\": \"悬疑\", \"v\": \"悬疑\"}, {\"n\": \"惊悚\", \"v\": \"惊悚\"}, {\"n\": \"经典\", \"v\": \"经典\"}, {\"n\": \"青春\", \"v\": \"青春\"}, {\"n\": \"文艺\", \"v\": \"文艺\"}, {\"n\": \"古装\", \"v\": \"古装\"}, {\"n\": \"历史\", \"v\": \"历史\"}, {\"n\": \"微电影\", \"v\": \"微电影\"}]}, {\"key\": \"1\", \"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\": \"加拿大\"}, {\"n\": \"其他\", \"v\": \"其他\"}]}, {\"key\": \"11\", \"name\": \"年份\", \"value\": [{\"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\"}, {\"n\": \"2016\", \"v\": \"2016\"}, {\"n\": \"2015\", \"v\": \"2015\"}, {\"n\": \"2014\", \"v\": \"2014\"}, {\"n\": \"2013\", \"v\": \"2013\"}, {\"n\": \"2012\", \"v\": \"2012\"}, {\"n\": \"2011\", \"v\": \"2011\"}, {\"n\": \"2010\", \"v\": \"2010\"}]}, {\"key\": \"5\", \"name\": \"字母\", \"value\": [{\"n\": \"A\", \"v\": \"A\"}, {\"n\": \"B\", \"v\": \"B\"}, {\"n\": \"C\", \"v\": \"C\"}, {\"n\": \"D\", \"v\": \"D\"}, {\"n\": \"E\", \"v\": \"E\"}, {\"n\": \"F\", \"v\": \"F\"}, {\"n\": \"G\", \"v\": \"G\"}, {\"n\": \"H\", \"v\": \"H\"}, {\"n\": \"I\", \"v\": \"I\"}, {\"n\": \"J\", \"v\": \"J\"}, {\"n\": \"K\", \"v\": \"K\"}, {\"n\": \"L\", \"v\": \"L\"}, {\"n\": \"M\", \"v\": \"M\"}, {\"n\": \"N\", \"v\": \"N\"}, {\"n\": \"O\", \"v\": \"O\"}, {\"n\": \"P\", \"v\": \"P\"}, {\"n\": \"Q\", \"v\": \"Q\"}, {\"n\": \"R\", \"v\": \"R\"}, {\"n\": \"S\", \"v\": \"S\"}, {\"n\": \"T\", \"v\": \"T\"}, {\"n\": \"U\", \"v\": \"U\"}, {\"n\": \"V\", \"v\": \"V\"}, {\"n\": \"W\", \"v\": \"W\"}, {\"n\": \"X\", \"v\": \"X\"}, {\"n\": \"Y\", \"v\": \"Y\"}, {\"n\": \"Z\", \"v\": \"Z\"}, {\"n\": \"0-9\", \"v\": \"0-9\"}]}, {\"key\": \"2\", \"name\": \"排序\", \"value\": [{\"n\": \"时间\", \"v\": \"time\"}, {\"n\": \"人气\", \"v\": \"hits\"}, {\"n\": \"评分\", \"v\": \"score\"}]}], \"20\": [{\"key\": \"1\", \"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\": \"加拿大\"}, {\"n\": \"其他\", \"v\": \"其他\"}]}, {\"key\": \"4\", \"name\": \"语言\", \"value\": [{\"n\": \"国语\", \"v\": \"国语\"}, {\"n\": \"英语\", \"v\": \"英语\"}, {\"n\": \"粤语\", \"v\": \"粤语\"}, {\"n\": \"闽南语\", \"v\": \"闽南语\"}, {\"n\": \"韩语\", \"v\": \"韩语\"}, {\"n\": \"日语\", \"v\": \"日语\"}, {\"n\": \"法语\", \"v\": \"法语\"}, {\"n\": \"德语\", \"v\": \"德语\"}, {\"n\": \"其它\", \"v\": \"其它\"}]}, {\"key\": \"11\", \"name\": \"年份\", \"value\": [{\"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\"}, {\"n\": \"2016\", \"v\": \"2016\"}, {\"n\": \"2015\", \"v\": \"2015\"}, {\"n\": \"2014\", \"v\": \"2014\"}, {\"n\": \"2013\", \"v\": \"2013\"}, {\"n\": \"2012\", \"v\": \"2012\"}, {\"n\": \"2011\", \"v\": \"2011\"}, {\"n\": \"2010\", \"v\": \"2010\"}]}, {\"key\": \"5\", \"name\": \"字母\", \"value\": [{\"n\": \"A\", \"v\": \"A\"}, {\"n\": \"B\", \"v\": \"B\"}, {\"n\": \"C\", \"v\": \"C\"}, {\"n\": \"D\", \"v\": \"D\"}, {\"n\": \"E\", \"v\": \"E\"}, {\"n\": \"F\", \"v\": \"F\"}, {\"n\": \"G\", \"v\": \"G\"}, {\"n\": \"H\", \"v\": \"H\"}, {\"n\": \"I\", \"v\": \"I\"}, {\"n\": \"J\", \"v\": \"J\"}, {\"n\": \"K\", \"v\": \"K\"}, {\"n\": \"L\", \"v\": \"L\"}, {\"n\": \"M\", \"v\": \"M\"}, {\"n\": \"N\", \"v\": \"N\"}, {\"n\": \"O\", \"v\": \"O\"}, {\"n\": \"P\", \"v\": \"P\"}, {\"n\": \"Q\", \"v\": \"Q\"}, {\"n\": \"R\", \"v\": \"R\"}, {\"n\": \"S\", \"v\": \"S\"}, {\"n\": \"T\", \"v\": \"T\"}, {\"n\": \"U\", \"v\": \"U\"}, {\"n\": \"V\", \"v\": \"V\"}, {\"n\": \"W\", \"v\": \"W\"}, {\"n\": \"X\", \"v\": \"X\"}, {\"n\": \"Y\", \"v\": \"Y\"}, {\"n\": \"Z\", \"v\": \"Z\"}, {\"n\": \"0-9\", \"v\": \"0-9\"}]}, {\"key\": \"2\", \"name\": \"排序\", \"value\": [{\"n\": \"时间\", \"v\": \"time\"}, {\"n\": \"人气\", \"v\": \"hits\"}, {\"n\": \"评分\", \"v\": \"score\"}]}], \"24\": [{\"key\": \"1\", \"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\": \"加拿大\"}, {\"n\": \"其他\", \"v\": \"其他\"}]}, {\"key\": \"4\", \"name\": \"语言\", \"value\": [{\"n\": \"国语\", \"v\": \"国语\"}, {\"n\": \"英语\", \"v\": \"英语\"}, {\"n\": \"粤语\", \"v\": \"粤语\"}, {\"n\": \"闽南语\", \"v\": \"闽南语\"}, {\"n\": \"韩语\", \"v\": \"韩语\"}, {\"n\": \"日语\", \"v\": \"日语\"}, {\"n\": \"法语\", \"v\": \"法语\"}, {\"n\": \"德语\", \"v\": \"德语\"}, {\"n\": \"其它\", \"v\": \"其它\"}]}, {\"key\": \"11\", \"name\": \"年份\", \"value\": [{\"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\"}, {\"n\": \"2016\", \"v\": \"2016\"}, {\"n\": \"2015\", \"v\": \"2015\"}, {\"n\": \"2014\", \"v\": \"2014\"}, {\"n\": \"2013\", \"v\": \"2013\"}, {\"n\": \"2012\", \"v\": \"2012\"}, {\"n\": \"2011\", \"v\": \"2011\"}, {\"n\": \"2010\", \"v\": \"2010\"}]}, {\"key\": \"5\", \"name\": \"字母\", \"value\": [{\"n\": \"A\", \"v\": \"A\"}, {\"n\": \"B\", \"v\": \"B\"}, {\"n\": \"C\", \"v\": \"C\"}, {\"n\": \"D\", \"v\": \"D\"}, {\"n\": \"E\", \"v\": \"E\"}, {\"n\": \"F\", \"v\": \"F\"}, {\"n\": \"G\", \"v\": \"G\"}, {\"n\": \"H\", \"v\": \"H\"}, {\"n\": \"I\", \"v\": \"I\"}, {\"n\": \"J\", \"v\": \"J\"}, {\"n\": \"K\", \"v\": \"K\"}, {\"n\": \"L\", \"v\": \"L\"}, {\"n\": \"M\", \"v\": \"M\"}, {\"n\": \"N\", \"v\": \"N\"}, {\"n\": \"O\", \"v\": \"O\"}, {\"n\": \"P\", \"v\": \"P\"}, {\"n\": \"Q\", \"v\": \"Q\"}, {\"n\": \"R\", \"v\": \"R\"}, {\"n\": \"S\", \"v\": \"S\"}, {\"n\": \"T\", \"v\": \"T\"}, {\"n\": \"U\", \"v\": \"U\"}, {\"n\": \"V\", \"v\": \"V\"}, {\"n\": \"W\", \"v\": \"W\"}, {\"n\": \"X\", \"v\": \"X\"}, {\"n\": \"Y\", \"v\": \"Y\"}, {\"n\": \"Z\", \"v\": \"Z\"}, {\"n\": \"0-9\", \"v\": \"0-9\"}]}, {\"key\": \"2\", \"name\": \"排序\", \"value\": [{\"n\": \"时间\", \"v\": \"time\"}, {\"n\": \"人气\", \"v\": \"hits\"}, {\"n\": \"评分\", \"v\": \"score\"}]}], \"28\": [{\"key\": \"1\", \"name\": \"地区\", \"value\": [{\"n\": \"国产\", \"v\": \"国产\"}, {\"n\": \"日韩\", \"v\": \"日韩\"}, {\"n\": \"欧美\", \"v\": \"欧美\"}]}, {\"key\": \"11\", \"name\": \"年份\", \"value\": [{\"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\"}, {\"n\": \"2016\", \"v\": \"2016\"}, {\"n\": \"2015\", \"v\": \"2015\"}, {\"n\": \"2014\", \"v\": \"2014\"}, {\"n\": \"2013\", \"v\": \"2013\"}, {\"n\": \"2012\", \"v\": \"2012\"}, {\"n\": \"2011\", \"v\": \"2011\"}, {\"n\": \"2010\", \"v\": \"2010\"}]}, {\"key\": \"5\", \"name\": \"字母\", \"value\": [{\"n\": \"A\", \"v\": \"A\"}, {\"n\": \"B\", \"v\": \"B\"}, {\"n\": \"C\", \"v\": \"C\"}, {\"n\": \"D\", \"v\": \"D\"}, {\"n\": \"E\", \"v\": \"E\"}, {\"n\": \"F\", \"v\": \"F\"}, {\"n\": \"G\", \"v\": \"G\"}, {\"n\": \"H\", \"v\": \"H\"}, {\"n\": \"I\", \"v\": \"I\"}, {\"n\": \"J\", \"v\": \"J\"}, {\"n\": \"K\", \"v\": \"K\"}, {\"n\": \"L\", \"v\": \"L\"}, {\"n\": \"M\", \"v\": \"M\"}, {\"n\": \"N\", \"v\": \"N\"}, {\"n\": \"O\", \"v\": \"O\"}, {\"n\": \"P\", \"v\": \"P\"}, {\"n\": \"Q\", \"v\": \"Q\"}, {\"n\": \"R\", \"v\": \"R\"}, {\"n\": \"S\", \"v\": \"S\"}, {\"n\": \"T\", \"v\": \"T\"}, {\"n\": \"U\", \"v\": \"U\"}, {\"n\": \"V\", \"v\": \"V\"}, {\"n\": \"W\", \"v\": \"W\"}, {\"n\": \"X\", \"v\": \"X\"}, {\"n\": \"Y\", \"v\": \"Y\"}, {\"n\": \"Z\", \"v\": \"Z\"}, {\"n\": \"0-9\", \"v\": \"0-9\"}]}, {\"key\": \"2\", \"name\": \"排序\", \"value\": [{\"n\": \"时间\", \"v\": \"time\"}, {\"n\": \"人气\", \"v\": \"hits\"}, {\"n\": \"评分\", \"v\": \"score\"}]}], \"32\": [{\"key\": \"5\", \"name\": \"字母\", \"value\": [{\"n\": \"A\", \"v\": \"A\"}, {\"n\": \"B\", \"v\": \"B\"}, {\"n\": \"C\", \"v\": \"C\"}, {\"n\": \"D\", \"v\": \"D\"}, {\"n\": \"E\", \"v\": \"E\"}, {\"n\": \"F\", \"v\": \"F\"}, {\"n\": \"G\", \"v\": \"G\"}, {\"n\": \"H\", \"v\": \"H\"}, {\"n\": \"I\", \"v\": \"I\"}, {\"n\": \"J\", \"v\": \"J\"}, {\"n\": \"K\", \"v\": \"K\"}, {\"n\": \"L\", \"v\": \"L\"}, {\"n\": \"M\", \"v\": \"M\"}, {\"n\": \"N\", \"v\": \"N\"}, {\"n\": \"O\", \"v\": \"O\"}, {\"n\": \"P\", \"v\": \"P\"}, {\"n\": \"Q\", \"v\": \"Q\"}, {\"n\": \"R\", \"v\": \"R\"}, {\"n\": \"S\", \"v\": \"S\"}, {\"n\": \"T\", \"v\": \"T\"}, {\"n\": \"U\", \"v\": \"U\"}, {\"n\": \"V\", \"v\": \"V\"}, {\"n\": \"W\", \"v\": \"W\"}, {\"n\": \"X\", \"v\": \"X\"}, {\"n\": \"Y\", \"v\": \"Y\"}, {\"n\": \"Z\", \"v\": \"Z\"}, {\"n\": \"0-9\", \"v\": \"0-9\"}]}, {\"key\": \"2\", \"name\": \"排序\", \"value\": [{\"n\": \"时间\", \"v\": \"time\"}, {\"n\": \"人气\", \"v\": \"hits\"}, {\"n\": \"评分\", \"v\": \"score\"}]}]}"); - } catch (JSONException e) { - e.printStackTrace(); - SpiderDebug.log(e); - } - } - - @Override - public String homeContent(boolean filter) { - List classes = new ArrayList<>(); - Document doc = Jsoup.parse(OkHttp.string(siteURL, getHeader())); - Elements elements = doc.select(".nav-link"); - for (Element e : elements) { - Matcher mather = regexCategory.matcher(e.attr("href")); - if (mather.find()) { - classes.add(new Class(mather.group(1), e.text().trim())); - } - } - return Result.string(classes, this.parseVodListFromDoc(doc), filter ? filters : null); - } - - @Override - public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { - String[] urlParams = new String[]{tid, "", "", "", "", "", "", "", pg, "", "", ""}; - if (extend != null && extend.size() > 0) { - for (String key : extend.keySet()) { - urlParams[Integer.parseInt(key)] = extend.get(key); - } - } - - Document doc = Jsoup.parse(OkHttp.string(String.format("%s/index.php/vodshow/%s.html", siteURL, String.join("-", urlParams)), getHeader())); - int page = Integer.parseInt(pg), limit = 72, total = 0; - Matcher matcher = regexPageTotal.matcher(doc.html()); - if (matcher.find()) { - total = Integer.parseInt(matcher.group(1)); - } - int count = total <= limit ? 1 : ((int) Math.ceil(total / (double) limit)); - return Result.get().vod(this.parseVodListFromDoc(doc)).page(page, count, limit, total).string(); - } - - private List parseVodListFromDoc(Document doc) { - List list = new ArrayList<>(); - Elements elements = doc.select(".module-item"); - for (Element e : elements) { - String vodId = e.selectFirst(".video-name a").attr("href"); - String vodPic = e.selectFirst(".module-item-pic > img").attr("data-src"); - String vodName = e.selectFirst(".video-name").text(); - String vodRemarks = e.selectFirst(".module-item-text").text(); - list.add(new Vod(vodId, vodName, vodPic, vodRemarks)); - } - return list; - } - - @Override - public String detailContent(List ids) throws Exception { - String vodId = ids.get(0); - - Document doc = Jsoup.parse(OkHttp.string(siteURL + vodId, getHeader())); - - Vod item = new Vod(); - item.setVodId(vodId); - item.setVodName(doc.selectFirst(".video-info-header > .page-title").text()); - item.setVodPic(doc.selectFirst(".module-item-pic img").attr("data-src")); - item.setVodArea(doc.select(".video-info-header a.tag-link").last().text()); - item.setTypeName(String.join(",", doc.select(".video-info-header div.tag-link a").eachText())); - - List shareLinks = doc.select(".module-row-text").eachAttr("data-clipboard-text"); - item.setVodPlayUrl(super.detailContentVodPlayUrl(shareLinks)); - item.setVodPlayFrom(super.detailContentVodPlayFrom(shareLinks)); - - Elements elements = doc.select(".video-info-item"); - for (Element e : elements) { - String title = e.previousElementSibling().text(); - if (title.contains("导演")) { - item.setVodDirector(String.join(",", e.select("a").eachText())); - } else if (title.contains("主演")) { - item.setVodActor(String.join(",", e.select("a").eachText())); - } else if (title.contains("年代")) { - item.setVodYear(e.selectFirst("a").text().trim()); - } else if (title.contains("备注")) { - item.setVodRemarks(e.text().trim()); - } else if (title.contains("剧情")) { - item.setVodContent(e.selectFirst(".sqjj_a").text().replace("[收起部分]", "").trim()); - } - } - return Result.string(item); - } - - @Override - public String searchContent(String key, boolean quick) throws Exception { - return searchContent(key, "1"); - } - - @Override - public String searchContent(String key, boolean quick, String pg) throws Exception { - return searchContent(key, pg); - } - - private String searchContent(String key, String pg) { - String searchURL = siteURL + String.format("/index.php/vodsearch/%s----------%s---.html", URLEncoder.encode(key), pg); - String html = OkHttp.string(searchURL, getHeader()); - Elements items = Jsoup.parse(html).select(".module-search-item"); - List list = new ArrayList<>(); - for (Element item : items) { - String vodId = item.select(".video-serial").attr("href"); - String name = item.select(".video-serial").attr("title"); - String pic = item.select(".module-item-pic > img").attr("data-src"); - String remark = item.select(".video-tag-icon").text(); - list.add(new Vod(vodId, name, pic, remark)); - } - return Result.string(list); - } + + private final String siteUrl = "http://tvfan.xxooo.cf"; + private final Pattern regexCategory = Pattern.compile("/vodtype/(\\w+).html"); + private final Pattern regexPageTotal = Pattern.compile("\\$\\(\"\\.mac_total\"\\)\\.text\\('(\\d+)'\\);"); + + private String extend; + + private Map getHeader() { + Map header = new HashMap<>(); + header.put("User-Agent", Utils.CHROME); + return header; + } + + @Override + public void init(Context context, String extend) { + this.extend = extend; + } + + @Override + public String homeContent(boolean filter) { + List classes = new ArrayList<>(); + Document doc = Jsoup.parse(OkHttp.string(siteUrl, getHeader())); + Elements elements = doc.select(".nav-link"); + for (Element e : elements) { + Matcher mather = regexCategory.matcher(e.attr("href")); + if (mather.find()) { + classes.add(new Class(mather.group(1), e.text().trim())); + } + } + return Result.string(classes, this.parseVodListFromDoc(doc), filter ? JsonParser.parseString(OkHttp.string(extend)) : null); + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { + String[] urlParams = new String[]{tid, "", "", "", "", "", "", "", pg, "", "", ""}; + if (extend != null && extend.size() > 0) { + for (String key : extend.keySet()) { + urlParams[Integer.parseInt(key)] = extend.get(key); + } + } + Document doc = Jsoup.parse(OkHttp.string(String.format("%s/index.php/vodshow/%s.html", siteUrl, String.join("-", urlParams)), getHeader())); + int page = Integer.parseInt(pg), limit = 72, total = 0; + Matcher matcher = regexPageTotal.matcher(doc.html()); + if (matcher.find()) total = Integer.parseInt(matcher.group(1)); + int count = total <= limit ? 1 : ((int) Math.ceil(total / (double) limit)); + return Result.get().vod(this.parseVodListFromDoc(doc)).page(page, count, limit, total).string(); + } + + private List parseVodListFromDoc(Document doc) { + List list = new ArrayList<>(); + Elements elements = doc.select(".module-item"); + for (Element e : elements) { + String vodId = e.selectFirst(".video-name a").attr("href"); + String vodPic = e.selectFirst(".module-item-pic > img").attr("data-src"); + String vodName = e.selectFirst(".video-name").text(); + String vodRemarks = e.selectFirst(".module-item-text").text(); + list.add(new Vod(vodId, vodName, vodPic, vodRemarks)); + } + return list; + } + + @Override + public String detailContent(List ids) throws Exception { + String vodId = ids.get(0); + Document doc = Jsoup.parse(OkHttp.string(siteUrl + vodId, getHeader())); + + Vod item = new Vod(); + item.setVodId(vodId); + item.setVodName(doc.selectFirst(".video-info-header > .page-title").text()); + item.setVodPic(doc.selectFirst(".module-item-pic img").attr("data-src")); + item.setVodArea(doc.select(".video-info-header a.tag-link").last().text()); + item.setTypeName(String.join(",", doc.select(".video-info-header div.tag-link a").eachText())); + + List shareLinks = doc.select(".module-row-text").eachAttr("data-clipboard-text"); + item.setVodPlayFrom(super.detailContentVodPlayFrom(shareLinks)); + item.setVodPlayUrl(super.detailContentVodPlayUrl(shareLinks)); + + Elements elements = doc.select(".video-info-item"); + for (Element e : elements) { + String title = e.previousElementSibling().text(); + if (title.contains("导演")) { + item.setVodDirector(String.join(",", e.select("a").eachText())); + } else if (title.contains("主演")) { + item.setVodActor(String.join(",", e.select("a").eachText())); + } else if (title.contains("年代")) { + item.setVodYear(e.selectFirst("a").text().trim()); + } else if (title.contains("备注")) { + item.setVodRemarks(e.text().trim()); + } else if (title.contains("剧情")) { + item.setVodContent(e.selectFirst(".sqjj_a").text().replace("[收起部分]", "").trim()); + } + } + + return Result.string(item); + } + + @Override + public String searchContent(String key, boolean quick) throws Exception { + return searchContent(key, "1"); + } + + @Override + public String searchContent(String key, boolean quick, String pg) throws Exception { + return searchContent(key, pg); + } + + private String searchContent(String key, String pg) { + String searchURL = siteUrl + String.format("/index.php/vodsearch/%s----------%s---.html", URLEncoder.encode(key), pg); + String html = OkHttp.string(searchURL, getHeader()); + Elements items = Jsoup.parse(html).select(".module-search-item"); + List list = new ArrayList<>(); + for (Element item : items) { + String vodId = item.select(".video-serial").attr("href"); + String name = item.select(".video-serial").attr("title"); + String pic = item.select(".module-item-pic > img").attr("data-src"); + String remark = item.select(".video-tag-icon").text(); + list.add(new Vod(vodId, name, pic, remark)); + } + return Result.string(list); + } } \ No newline at end of file