├── tools
├── .gitignore
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── build.gradle
└── src
│ └── main
│ ├── resources
│ └── live.txt
│ └── java
│ └── com
│ └── fongmi
│ └── tools
│ ├── bean
│ ├── Data.java
│ ├── Group.java
│ └── Channel.java
│ ├── Util.java
│ └── Run.java
├── jar
├── custom_spider.jar.md5
├── 3rd
│ ├── oss.jar
│ ├── apktool_2.4.1.jar
│ └── baksmali-2.5.2.jar
├── custom_spider.jar
├── spider.jar
│ ├── original
│ │ └── META-INF
│ │ │ └── MANIFEST.MF
│ └── apktool.yml
└── genJar.bat
├── .gitignore
├── app
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ └── strings.xml
│ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.webp
│ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.webp
│ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.webp
│ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.webp
│ │ └── layout
│ │ │ └── activity_main.xml
│ │ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── catvod
│ │ │ ├── utils
│ │ │ ├── Image.java
│ │ │ ├── ReflectUtil.java
│ │ │ ├── QRCode.java
│ │ │ ├── Prefers.java
│ │ │ ├── FileUtil.java
│ │ │ └── Utils.java
│ │ │ ├── crawler
│ │ │ ├── SpiderDebug.java
│ │ │ └── Spider.java
│ │ │ ├── demo
│ │ │ └── MainActivity.java
│ │ │ ├── net
│ │ │ ├── OkResult.java
│ │ │ ├── OkRequest.java
│ │ │ ├── Cronet.java
│ │ │ ├── OkHttp.java
│ │ │ └── SSLSocketFactoryCompat.java
│ │ │ ├── bean
│ │ │ ├── ali
│ │ │ │ ├── Code.java
│ │ │ │ ├── OAuth.java
│ │ │ │ ├── User.java
│ │ │ │ ├── Biz.java
│ │ │ │ ├── Item.java
│ │ │ │ └── Data.java
│ │ │ ├── upyun
│ │ │ │ ├── Data.java
│ │ │ │ └── Item.java
│ │ │ ├── Filter.java
│ │ │ ├── alist
│ │ │ │ ├── Sorter.java
│ │ │ │ ├── Drive.java
│ │ │ │ └── Item.java
│ │ │ ├── Sub.java
│ │ │ ├── paper
│ │ │ │ └── Data.java
│ │ │ ├── webdav
│ │ │ │ ├── Sorter.java
│ │ │ │ └── Drive.java
│ │ │ ├── Class.java
│ │ │ ├── yiso
│ │ │ │ └── Item.java
│ │ │ ├── Vod.java
│ │ │ └── Result.java
│ │ │ └── spider
│ │ │ ├── Dovx.java
│ │ │ ├── XPathMacFilter.java
│ │ │ ├── XPathFilter.java
│ │ │ ├── Proxy.java
│ │ │ ├── UpYun.java
│ │ │ ├── Ali.java
│ │ │ ├── TuGou.java
│ │ │ ├── Push.java
│ │ │ ├── PanSearch.java
│ │ │ ├── PanSou.java
│ │ │ ├── Init.java
│ │ │ ├── Zhaozy.java
│ │ │ ├── Doll.java
│ │ │ ├── Local.java
│ │ │ ├── Jable.java
│ │ │ ├── Eighteen.java
│ │ │ ├── Miss.java
│ │ │ ├── Hanime.java
│ │ │ ├── Ying.java
│ │ │ ├── Ysj.java
│ │ │ ├── Dm84.java
│ │ │ ├── Supjav.java
│ │ │ └── XPathMac.java
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── txt
└── cookie.txt
├── README.md
├── json
├── webdav.json
├── alist.json
├── bili.json
└── config.json
├── settings.gradle
├── .github
└── workflows
│ └── main.yml
├── gradle.properties
├── gradlew.bat
└── gradlew
/tools/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/jar/custom_spider.jar.md5:
--------------------------------------------------------------------------------
1 | 8b50403c7f94d6d04c1812adfb2957b6
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | .idea
3 | *build
4 | *.jks
5 | *i.java
6 | /local.properties
--------------------------------------------------------------------------------
/jar/3rd/oss.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/jar/3rd/oss.jar
--------------------------------------------------------------------------------
/jar/custom_spider.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/jar/custom_spider.jar
--------------------------------------------------------------------------------
/jar/3rd/apktool_2.4.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/jar/3rd/apktool_2.4.1.jar
--------------------------------------------------------------------------------
/jar/3rd/baksmali-2.5.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/jar/3rd/baksmali-2.5.2.jar
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CatVodSpider
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/jar/spider.jar/original/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Dex-Location: classes.dex
3 | Created-By: dx 1.11
4 |
5 |
--------------------------------------------------------------------------------
/tools/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/tools/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/txt/cookie.txt:
--------------------------------------------------------------------------------
1 | DedeUserID=690781341;DedeUserID__ckMd5=cabc96906269c5b6;SESSDATA=2245ba24%2C1684212125%2C466fd%2Ab2;bili_jct=de6fdb60c10f8a83910aa55d79407b4e;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CatVodSpider
2 |
3 | #仓库fokk自fongmi大佬,仅仅适配了影视仓本地配置token方法,以及增加了githubAction打包,其他与fongmi仓库一致
4 |
5 | ### Based on CatVod
6 |
7 | https://github.com/CatVodTVOfficial/CatVodTVSpider
8 |
--------------------------------------------------------------------------------
/tools/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Aug 22 15:05:50 CST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/tools/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java-library'
3 | }
4 |
5 | java {
6 | sourceCompatibility = JavaVersion.VERSION_11
7 | targetCompatibility = JavaVersion.VERSION_11
8 | }
9 |
10 | dependencies {
11 | implementation 'com.squareup.okhttp3:okhttp:3.12.13'
12 | implementation 'com.google.code.gson:gson:2.8.6'
13 | }
--------------------------------------------------------------------------------
/jar/spider.jar/apktool.yml:
--------------------------------------------------------------------------------
1 | !!brut.androlib.meta.MetaInfo
2 | apkFileName: dex.jar
3 | compressionType: false
4 | doNotCompress: null
5 | isFrameworkApk: false
6 | packageInfo: null
7 | sdkInfo: null
8 | sharedLibrary: false
9 | sparseResources: false
10 | unknownFiles:
11 | usesFramework: null
12 | version: 2.4.1_0303
13 | versionInfo: null
14 |
--------------------------------------------------------------------------------
/json/webdav.json:
--------------------------------------------------------------------------------
1 | {
2 | "drives": [
3 | {
4 | "name": "七米藍",
5 | "server": "https://al.chirmyram.com/dav",
6 | "user": "alist",
7 | "pass": "alist"
8 | },
9 | {
10 | "name": "影視庫",
11 | "server": "https://esir.eu.org/dav",
12 | "user": "alist",
13 | "pass": "alist"
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/tools/src/main/resources/live.txt:
--------------------------------------------------------------------------------
1 | 香港,#genre#
2 | 001,凤凰中文,tb1/gt/fenghuangzhongwen.png,鳳凰中文,http://play-live.ifeng.com/live/06OLEGEGM4G.m3u8
3 | 002,凤凰资讯,tb1/gt/fenghuangzixun.png,鳳凰資訊,http://play-live.ifeng.com/live/06OLEEWQKN4.m3u8
4 | 歐美_1234,#genre#
5 | 1001,,,Three,http://live.redtraffic.xyz/threesome.m3u8
6 | 1002,,,BlowJob,http://live.redtraffic.xyz/blowjob.m3u8
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/utils/Image.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.utils;
2 |
3 | public class Image {
4 |
5 | public static final String FOLDER = "https://s1.ax1x.com/2023/05/04/p9tgI81.png";
6 | public static final String VIDEO = "https://s1.ax1x.com/2023/05/04/p9tgogx.png";
7 |
8 | public static String getIcon(boolean folder) {
9 | return folder ? FOLDER : VIDEO;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/crawler/SpiderDebug.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.crawler;
2 |
3 | import android.util.Log;
4 |
5 | public class SpiderDebug {
6 |
7 | private static final String TAG = SpiderDebug.class.getSimpleName();
8 |
9 | public static void log(Throwable e) {
10 | Log.d(TAG, e.getMessage());
11 | }
12 |
13 | public static void log(String msg) {
14 | Log.d(TAG, msg);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | maven { url "https://plugins.gradle.org/m2/" }
7 | }
8 | }
9 | dependencyResolutionManagement {
10 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
11 | repositories {
12 | google()
13 | mavenCentral()
14 | maven { url 'https://jitpack.io' }
15 | }
16 | }
17 | rootProject.name = "CatVodSpider"
18 | include ':app'
19 | include ':tools'
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/demo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.demo;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 |
6 | import com.github.catvod.R;
7 | import com.github.catvod.spider.Init;
8 |
9 | public class MainActivity extends Activity {
10 |
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | setContentView(R.layout.activity_main);
15 | Init.init(getApplicationContext());
16 | new Thread(() -> {
17 |
18 | }).start();
19 | }
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/net/OkResult.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.net;
2 |
3 | import android.text.TextUtils;
4 |
5 | public class OkResult {
6 |
7 | private final int code;
8 | private final String body;
9 |
10 | public OkResult() {
11 | this.code = 500;
12 | this.body = "";
13 | }
14 |
15 | public OkResult(int code, String body) {
16 | this.code = code;
17 | this.body = body;
18 | }
19 |
20 | public int getCode() {
21 | return code;
22 | }
23 |
24 | public String getBody() {
25 | return TextUtils.isEmpty(body) ? "" : body;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/json/alist.json:
--------------------------------------------------------------------------------
1 | {
2 | "vodPic": "https://s1.ax1x.com/2023/05/04/p9tgI81.png",
3 | "drives": [
4 | {
5 | "name": "小雅",
6 | "server": "http://alist.xiaoya.pro"
7 | },
8 | {
9 | "name": "觸光",
10 | "server": "https://pan.ichuguang.com"
11 | },
12 | {
13 | "name": "一只魚",
14 | "server": "https://vtok.pp.ua/"
15 | },
16 | {
17 | "name": "七米藍",
18 | "server": "https://al.chirmyram.com"
19 | },
20 | {
21 | "name": "神族九帝",
22 | "server": "https://alist.shenzjd.com"
23 | },
24 | {
25 | "name": "梓澪",
26 | "server": "https://zi0.cc"
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/ali/Code.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.ali;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.google.gson.Gson;
6 | import com.google.gson.annotations.SerializedName;
7 |
8 | public class Code {
9 |
10 | @SerializedName("redirectUri")
11 | private String redirectUri;
12 |
13 | public static Code objectFrom(String str) {
14 | return new Gson().fromJson(str, Code.class);
15 | }
16 |
17 | public String getRedirectUri() {
18 | return TextUtils.isEmpty(redirectUri) ? "" : redirectUri;
19 | }
20 |
21 | public String getCode() {
22 | return getRedirectUri().split("code=")[1];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Spider Jar Gen CI
2 |
3 | on: workflow_dispatch
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: windows-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v2
12 | - name: set up JDK 11
13 | uses: actions/setup-java@v2
14 | with:
15 | java-version: '11'
16 | distribution: 'adopt'
17 | cache: gradle
18 |
19 | - name: Build with Gradle
20 | run: ./build.bat ec
21 |
22 | - name: Update spider jar
23 | uses: EndBug/add-and-commit@v7
24 | with:
25 | default_author: github_actions
26 | message: 'update spider jar'
27 | add: "['./jar/custom_spider.jar', './jar/custom_spider.jar.md5']"
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/upyun/Data.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.upyun;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.annotations.SerializedName;
5 |
6 | import java.util.Collections;
7 | import java.util.List;
8 |
9 | public class Data {
10 |
11 | @SerializedName("result")
12 | private Data result;
13 | @SerializedName("items")
14 | private List- items;
15 |
16 | public static Data objectFrom(String str) {
17 | return new Gson().fromJson(str, Data.class);
18 | }
19 |
20 | public Data getResult() {
21 | return result == null ? new Data() : result;
22 | }
23 |
24 | public List
- getItems() {
25 | return items == null ? Collections.emptyList() : items;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Dovx.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 |
5 | import com.github.catvod.bean.Result;
6 | import com.github.catvod.bean.Vod;
7 | import com.github.catvod.net.OkHttp;
8 |
9 | import java.net.URLEncoder;
10 |
11 | public class Dovx extends Ali {
12 |
13 | @Override
14 | public void init(Context context, String extend) {
15 | super.init(context, extend);
16 | }
17 |
18 | @Override
19 | public String searchContent(String key, boolean quick) {
20 | Result result = Result.objectFrom(OkHttp.string("https://api.dovx.tk/ali/search?wd=" + URLEncoder.encode(key)));
21 | for (Vod vod : result.getList()) vod.setVodId(vod.getVodContent());
22 | return result.string();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/utils/ReflectUtil.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.utils;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | public class ReflectUtil {
6 | /**
7 | * @Description: 判断是否包含某个方法
8 | */
9 | public static Method getMethod(Object object, String methodName, Class> ... parameterTypes){
10 | Method method = null ;
11 |
12 | for(Class> clazz = object.getClass() ; clazz != Object.class ; clazz = clazz.getSuperclass()) {
13 | try {
14 | method = clazz.getMethod(methodName,parameterTypes) ;
15 | return method ;
16 | } catch (Exception e) {
17 | //这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
18 | //如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
19 |
20 | }
21 | }
22 |
23 | return null;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/json/bili.json:
--------------------------------------------------------------------------------
1 | {
2 | "cookie": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/txt/cookie.txt",
3 | "classes": [
4 | {
5 | "type_name": "帕梅拉",
6 | "type_id": "帕梅拉"
7 | },
8 | {
9 | "type_name": "太极拳",
10 | "type_id": "太极拳"
11 | },
12 | {
13 | "type_name": "广场舞",
14 | "type_id": "广场舞"
15 | },
16 | {
17 | "type_name": "健身",
18 | "type_id": "健身"
19 | },
20 | {
21 | "type_name": "舞蹈",
22 | "type_id": "舞蹈"
23 | },
24 | {
25 | "type_name": "电影",
26 | "type_id": "电影"
27 | },
28 | {
29 | "type_name": "电视剧",
30 | "type_id": "电视剧"
31 | },
32 | {
33 | "type_name": "演唱会",
34 | "type_id": "演唱会"
35 | },
36 | {
37 | "type_name": "动物世界",
38 | "type_id": "动物世界"
39 | }
40 | ],
41 | "filter": {
42 | }
43 | }
--------------------------------------------------------------------------------
/tools/src/main/java/com/fongmi/tools/bean/Data.java:
--------------------------------------------------------------------------------
1 | package com.fongmi.tools.bean;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.annotations.SerializedName;
5 | import com.google.gson.reflect.TypeToken;
6 |
7 | import java.lang.reflect.Type;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class Data {
12 |
13 | @SerializedName("name")
14 | private String name;
15 | @SerializedName("epg")
16 | private String epg;
17 |
18 | @SerializedName("logo")
19 | private String logo;
20 |
21 | public static List arrayFrom(String str) {
22 | Type listType = new TypeToken>() {}.getType();
23 | return new Gson().fromJson(str, listType);
24 | }
25 |
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | public String getEpg() {
31 | return epg;
32 | }
33 |
34 | public String getLogo() {
35 | return logo;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/Filter.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.List;
6 |
7 | public class Filter {
8 |
9 | @SerializedName("key")
10 | private String key;
11 | @SerializedName("name")
12 | private String name;
13 | @SerializedName("value")
14 | private List value;
15 |
16 | public Filter(String key, String name, List value) {
17 | this.key = key;
18 | this.name = name;
19 | this.value = value;
20 | }
21 |
22 | public static class Value {
23 |
24 | @SerializedName("n")
25 | private String n;
26 | @SerializedName("v")
27 | private String v;
28 |
29 | public Value(String value) {
30 | this.n = value;
31 | this.v = value;
32 | }
33 |
34 | public Value(String n, String v) {
35 | this.n = n;
36 | this.v = v;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/upyun/Item.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.upyun;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.bean.Vod;
6 | import com.google.gson.annotations.SerializedName;
7 |
8 | public class Item {
9 |
10 | @SerializedName("title")
11 | private String title;
12 | @SerializedName("page_url")
13 | private String pageUrl;
14 | @SerializedName("insert_time")
15 | private String insertTime;
16 |
17 | public String getTitle() {
18 | return TextUtils.isEmpty(title) ? "" : title.replaceAll("", "").replaceAll("", "");
19 | }
20 |
21 | public String getPageUrl() {
22 | return TextUtils.isEmpty(pageUrl) ? "" : pageUrl;
23 | }
24 |
25 | public String getInsertTime() {
26 | return TextUtils.isEmpty(insertTime) ? "" : insertTime;
27 | }
28 |
29 | public Item url(String pageUrl) {
30 | this.pageUrl = pageUrl;
31 | return this;
32 | }
33 |
34 | public Vod getVod() {
35 | return new Vod(getPageUrl(), getTitle(), "https://inews.gtimg.com/newsapp_bt/0/13263837859/1000", getInsertTime());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tools/src/main/java/com/fongmi/tools/Util.java:
--------------------------------------------------------------------------------
1 | package com.fongmi.tools;
2 |
3 | import java.io.IOException;
4 | import java.net.URI;
5 | import java.nio.charset.StandardCharsets;
6 | import java.nio.file.Files;
7 | import java.nio.file.Path;
8 | import java.nio.file.Paths;
9 | import java.util.stream.Stream;
10 |
11 | import okhttp3.OkHttpClient;
12 | import okhttp3.Request;
13 |
14 | public class Util {
15 |
16 | public static String call(String url) throws IOException {
17 | return new OkHttpClient().newCall(new Request.Builder().url(url).build()).execute().body().string();
18 | }
19 |
20 | public static String getFile(Class> clz, String fileName) {
21 | try {
22 | StringBuilder sb = new StringBuilder();
23 | URI uri = clz.getClassLoader().getResource(fileName).toURI();
24 | Stream stream = Files.lines(Paths.get(uri), StandardCharsets.UTF_8);
25 | stream.forEach(s -> sb.append(s).append("\n"));
26 | return sb.toString();
27 | } catch (Exception e) {
28 | return "";
29 | }
30 | }
31 |
32 | public static String getFile(String fileName) {
33 | try {
34 | return Files.readString(Path.of(fileName));
35 | } catch (Exception e) {
36 | return "";
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/XPathMacFilter.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import java.net.URLEncoder;
4 | import java.util.HashMap;
5 | import java.util.regex.Matcher;
6 | import java.util.regex.Pattern;
7 |
8 | public class XPathMacFilter extends XPathMac {
9 |
10 | @Override
11 | protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) {
12 | String cateUrl = rule.getCateUrl();
13 | if (filter && extend != null && extend.size() > 0) {
14 | for (String key : extend.keySet()) {
15 | String value = extend.get(key);
16 | if (value.length() > 0) {
17 | cateUrl = cateUrl.replace("{" + key + "}", URLEncoder.encode(value));
18 | }
19 | }
20 | }
21 | cateUrl = cateUrl.replace("{cateId}", tid).replace("{catePg}", pg);
22 | Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(cateUrl);
23 | while (m.find()) {
24 | String n = m.group(0).replace("{", "").replace("}", "");
25 | cateUrl = cateUrl.replace(m.group(0), "").replace("/" + n + "/", "");
26 | }
27 | return cateUrl;
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/alist/Sorter.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.alist;
2 |
3 | import java.util.Collections;
4 | import java.util.Comparator;
5 | import java.util.List;
6 |
7 | public class Sorter implements Comparator
- {
8 |
9 | private final String type;
10 | private final String order;
11 |
12 | public static void sort(String type, String order, List
- items) {
13 | Collections.sort(items, new Sorter(type, order));
14 | }
15 |
16 | public Sorter(String type, String order) {
17 | this.type = type;
18 | this.order = order;
19 | }
20 |
21 | @Override
22 | public int compare(Item o1, Item o2) {
23 | boolean asc = order.equals("asc");
24 | switch (type) {
25 | case "name":
26 | return asc ? o1.getName().compareTo(o2.getName()) : o2.getName().compareTo(o1.getName());
27 | case "size":
28 | return asc ? Long.compare(o1.getSize(), o2.getSize()) : Long.compare(o2.getSize(), o1.getSize());
29 | case "date":
30 | return asc ? o1.getDate().compareTo(o2.getDate()) : o2.getDate().compareTo(o1.getDate());
31 | default:
32 | return -1;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/Sub.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class Sub {
6 |
7 | @SerializedName("url")
8 | private String url;
9 | @SerializedName("name")
10 | private String name;
11 | @SerializedName("lang")
12 | private String lang;
13 | @SerializedName("format")
14 | private String format;
15 |
16 | public static Sub create() {
17 | return new Sub();
18 | }
19 |
20 | public Sub name(String name) {
21 | this.name = name;
22 | return this;
23 | }
24 |
25 | public Sub url(String url) {
26 | this.url = url;
27 | return this;
28 | }
29 |
30 | public Sub lang(String lang) {
31 | this.lang = lang;
32 | return this;
33 | }
34 |
35 | public Sub format(String format) {
36 | this.format = format;
37 | return this;
38 | }
39 |
40 | public Sub ext(String ext) {
41 | switch (ext) {
42 | case "vtt":
43 | return format("text/vtt");
44 | case "ass":
45 | case "ssa":
46 | return format("text/x-ssa");
47 | default:
48 | return format("application/x-subrip");
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/jar/genJar.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | del "%~dp0\custom_spider.jar"
4 | rd /s/q "%~dp0\Smali_classes"
5 |
6 | java -jar "%~dp0\3rd\baksmali-2.5.2.jar" d "%~dp0\..\app\build\intermediates\dex\release\minifyReleaseWithR8\classes.dex" -o "%~dp0\Smali_classes"
7 |
8 | rd /s/q "%~dp0\spider.jar\smali\com\github\catvod\spider"
9 | rd /s/q "%~dp0\spider.jar\smali\com\github\catvod\parser"
10 |
11 | if not exist "%~dp0\spider.jar\smali\com\github\catvod\" md "%~dp0\spider.jar\smali\com\github\catvod\"
12 |
13 | if "%1" == "ec" (
14 | java -Dfile.encoding=utf-8 -jar "%~dp0\3rd\oss.jar" "%~dp0\Smali_classes"
15 | )
16 |
17 | move "%~dp0\Smali_classes\com\github\catvod\spider" "%~dp0\spider.jar\smali\com\github\catvod\"
18 | move "%~dp0\Smali_classes\com\github\catvod\parser" "%~dp0\spider.jar\smali\com\github\catvod\"
19 |
20 | rd /s/q "%~dp0\Smali_classes"
21 |
22 | java -jar "%~dp0\3rd\apktool_2.4.1.jar" b "%~dp0\spider.jar" -c
23 |
24 | move "%~dp0\spider.jar\dist\dex.jar" "%~dp0\custom_spider.jar"
25 |
26 | certUtil -hashfile "%~dp0\custom_spider.jar" MD5 | find /i /v "md5" | find /i /v "certutil" > "%~dp0\custom_spider.jar.md5"
27 |
28 | rd /s/q "%~dp0\spider.jar\smali\com\github\catvod\spider"
29 | rd /s/q "%~dp0\spider.jar\smali\com\github\catvod\parser"
30 |
31 | rd /s/q "%~dp0\spider.jar\build"
32 | rd /s/q "%~dp0\spider.jar\dist"
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/XPathFilter.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import java.net.URLEncoder;
4 | import java.util.HashMap;
5 | import java.util.regex.Matcher;
6 | import java.util.regex.Pattern;
7 |
8 | public class XPathFilter extends XPath {
9 |
10 | @Override
11 | protected void loadRuleExt(String json) {
12 | super.loadRuleExt(json);
13 | }
14 |
15 | @Override
16 | protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) {
17 | String cateUrl = rule.getCateUrl();
18 | if (filter && extend != null && extend.size() > 0) {
19 | for (String key : extend.keySet()) {
20 | String value = extend.get(key);
21 | if (value.length() > 0) {
22 | cateUrl = cateUrl.replace("{" + key + "}", URLEncoder.encode(value));
23 | }
24 | }
25 | }
26 | cateUrl = cateUrl.replace("{cateId}", tid).replace("{catePg}", pg);
27 | Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(cateUrl);
28 | while (m.find()) {
29 | String n = m.group(0).replace("{", "").replace("}", "");
30 | cateUrl = cateUrl.replace(m.group(0), "").replace("/" + n + "/", "");
31 | }
32 | return cateUrl;
33 | }
34 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/paper/Data.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.paper;
2 |
3 | import com.github.catvod.bean.Vod;
4 | import com.google.gson.Gson;
5 | import com.google.gson.annotations.SerializedName;
6 | import com.google.gson.reflect.TypeToken;
7 |
8 | import java.lang.reflect.Type;
9 | import java.util.List;
10 |
11 | public class Data {
12 |
13 | @SerializedName("key")
14 | private String key;
15 | @SerializedName("cat")
16 | private String cat;
17 | @SerializedName("title")
18 | private String title;
19 | @SerializedName("date")
20 | private String date;
21 |
22 | public static List arrayFrom(String str) {
23 | Type listType = new TypeToken
>() {}.getType();
24 | return new Gson().fromJson(str, listType);
25 | }
26 |
27 | public String getKey() {
28 | return key;
29 | }
30 |
31 | public String getCat() {
32 | return cat;
33 | }
34 |
35 | public String getTitle() {
36 | return title;
37 | }
38 |
39 | public String getDate() {
40 | return date;
41 | }
42 |
43 | public Vod getVod() {
44 | return new Vod("https://www.aliyundrive.com/s/" + getKey(), getTitle(), "https://www.lgstatic.com/i/image2/M01/15/7E/CgoB5lysLXCADg6ZAABapAHUnQM321.jpg", getDate());
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/webdav/Sorter.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.webdav;
2 |
3 | import com.thegrizzlylabs.sardineandroid.DavResource;
4 |
5 | import java.util.Collections;
6 | import java.util.Comparator;
7 | import java.util.List;
8 |
9 | public class Sorter implements Comparator {
10 |
11 | private final String type;
12 | private final String order;
13 |
14 | public static void sort(String type, String order, List items) {
15 | Collections.sort(items, new Sorter(type, order));
16 | }
17 |
18 | public Sorter(String type, String order) {
19 | this.type = type;
20 | this.order = order;
21 | }
22 |
23 | @Override
24 | public int compare(DavResource o1, DavResource o2) {
25 | boolean asc = order.equals("asc");
26 | switch (type) {
27 | case "name":
28 | return asc ? o1.getName().compareTo(o2.getName()) : o2.getName().compareTo(o1.getName());
29 | case "size":
30 | return asc ? Long.compare(o1.getContentLength(), o2.getContentLength()) : Long.compare(o2.getContentLength(), o1.getContentLength());
31 | case "date":
32 | return asc ? o1.getModified().compareTo(o2.getModified()) : o2.getModified().compareTo(o1.getModified());
33 | default:
34 | return -1;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | android.enableJetifier=true
19 | # Enables namespacing of each library's R class so that its R class includes only the
20 | # resources declared in the library itself and none from the library's dependencies,
21 | # thereby reducing the size of the R class for that library
22 | android.nonTransitiveRClass=true
23 | clientId=76917ccccd4441c39457a04f6084fb2f
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Merge
2 | -flattenpackagehierarchy com.github.catvod.spider.merge
3 | -dontwarn org.slf4j.impl.StaticLoggerBinder
4 |
5 | # Spider
6 | -keep class com.github.catvod.crawler.* { *; }
7 | -keep class com.github.catvod.spider.* { public ; }
8 | -keep class com.github.catvod.parser.* { public ; }
9 |
10 | # Gson
11 | -keepattributes Signature
12 | -keepattributes *Annotation*
13 | -dontwarn sun.misc.**
14 | -keep class com.google.gson.** { *; }
15 | -keep class * extends com.google.gson.TypeAdapter
16 | -keep class * implements com.google.gson.TypeAdapterFactory
17 | -keep class * implements com.google.gson.JsonSerializer
18 | -keep class * implements com.google.gson.JsonDeserializer
19 | -keepclassmembers,allowobfuscation class * { @com.google.gson.annotations.SerializedName ; }
20 | -keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
21 | -keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
22 |
23 | # Cronet
24 | -keep class org.chromium.net.** { *; }
25 | -keep class com.google.net.cronet.** { *; }
26 |
27 | # OkHttp
28 | -dontwarn okhttp3.**
29 | -keep class okio.** { *; }
30 | -keep class okhttp3.** { *; }
31 |
32 | # Sardine
33 | -keep class com.thegrizzlylabs.sardineandroid.** { *; }
34 |
35 | # Zxing
36 | -keepclassmembers enum * {
37 | public static **[] values();
38 | public static ** valueOf(java.lang.String);
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/crawler/Spider.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.crawler;
2 |
3 | import android.content.Context;
4 |
5 | import java.util.HashMap;
6 | import java.util.List;
7 |
8 | public abstract class Spider {
9 |
10 | public void init(Context context) {
11 | }
12 |
13 | public void init(Context context, String extend) {
14 | init(context);
15 | }
16 |
17 | public String homeContent(boolean filter) throws Exception {
18 | return "";
19 | }
20 |
21 | public String homeVideoContent() throws Exception {
22 | return "";
23 | }
24 |
25 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception {
26 | return "";
27 | }
28 |
29 | public String detailContent(List ids) throws Exception {
30 | return "";
31 | }
32 |
33 | public String searchContent(String key, boolean quick) throws Exception {
34 | return "";
35 | }
36 |
37 | public String playerContent(String flag, String id, List vipFlags) throws Exception {
38 | return "";
39 | }
40 |
41 | public String getToken() {
42 | return "";
43 | }
44 |
45 | public void setToken(String newToken){
46 |
47 | }
48 |
49 | public boolean manualVideoCheck() {
50 | return false;
51 | }
52 |
53 | public boolean isVideoFormat(String url) {
54 | return false;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/Class.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.annotations.SerializedName;
5 | import com.google.gson.reflect.TypeToken;
6 |
7 | import java.lang.reflect.Type;
8 | import java.util.List;
9 |
10 | public class Class {
11 |
12 | @SerializedName("type_id")
13 | private String typeId;
14 | @SerializedName("type_name")
15 | private String typeName;
16 | @SerializedName("type_flag")
17 | private String typeFlag;
18 |
19 | public static List arrayFrom(String str) {
20 | Type listType = new TypeToken>() {}.getType();
21 | return new Gson().fromJson(str, listType);
22 | }
23 |
24 | public Class(String typeId) {
25 | this(typeId, typeId);
26 | }
27 |
28 | public Class(String typeId, String typeName) {
29 | this(typeId, typeName, "");
30 | }
31 |
32 | public Class(String typeId, String typeName, String typeFlag) {
33 | this.typeId = typeId;
34 | this.typeName = typeName;
35 | this.typeFlag = typeFlag;
36 | }
37 |
38 | public String getTypeId() {
39 | return typeId;
40 | }
41 |
42 | @Override
43 | public boolean equals(Object obj) {
44 | if (this == obj) return true;
45 | if (!(obj instanceof Class)) return false;
46 | Class it = (Class) obj;
47 | return getTypeId().equals(it.getTypeId());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Proxy.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import com.github.catvod.crawler.Spider;
4 | import com.github.catvod.crawler.SpiderDebug;
5 | import com.github.catvod.net.OkHttp;
6 |
7 | import java.io.ByteArrayInputStream;
8 | import java.util.Map;
9 | import java.util.Objects;
10 |
11 | public class Proxy extends Spider {
12 |
13 | private static int port = -1;
14 |
15 | public static Object[] proxy(Map params) throws Exception {
16 | switch (Objects.requireNonNull(params.get("do"))) {
17 | case "ck":
18 | return new Object[]{200, "text/plain; charset=utf-8", new ByteArrayInputStream("ok".getBytes("UTF-8"))};
19 | case "ali":
20 | return Ali.proxy(params);
21 | case "webdav":
22 | return WebDAV.vod(params);
23 | default:
24 | return null;
25 | }
26 | }
27 |
28 | static void adjustPort() {
29 | if (Proxy.port > 0) return;
30 | int port = 9978;
31 | while (port < 10000) {
32 | String resp = OkHttp.string("http://127.0.0.1:" + port + "/proxy?do=ck", null);
33 | if (resp.equals("ok")) {
34 | SpiderDebug.log("Found local server port " + port);
35 | Proxy.port = port;
36 | break;
37 | }
38 | port++;
39 | }
40 | }
41 |
42 | public static String getUrl() {
43 | adjustPort();
44 | return "http://127.0.0.1:" + port + "/proxy";
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/ali/OAuth.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.ali;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.ali.API;
6 | import com.github.catvod.utils.FileUtil;
7 | import com.google.gson.Gson;
8 | import com.google.gson.annotations.SerializedName;
9 |
10 | public class OAuth {
11 |
12 | @SerializedName("token_type")
13 | private String tokenType;
14 | @SerializedName("access_token")
15 | private String accessToken;
16 | @SerializedName("refresh_token")
17 | private String refreshToken;
18 |
19 | public static OAuth objectFrom(String str) {
20 | OAuth item = new Gson().fromJson(str, OAuth.class);
21 | return item == null ? new OAuth() : item;
22 | }
23 |
24 | public String getTokenType() {
25 | return TextUtils.isEmpty(tokenType) ? "" : tokenType;
26 | }
27 |
28 | public String getAccessToken() {
29 | return TextUtils.isEmpty(accessToken) ? "" : accessToken;
30 | }
31 |
32 | public String getRefreshToken() {
33 | return TextUtils.isEmpty(refreshToken) ? "" : refreshToken;
34 | }
35 |
36 | public String getAuthorization() {
37 | return getTokenType() + " " + getAccessToken();
38 | }
39 |
40 | public OAuth clean() {
41 | this.refreshToken = "";
42 | this.accessToken = "";
43 | return this;
44 | }
45 |
46 | public OAuth save() {
47 | FileUtil.write(API.get().getOAuthCache(), toString());
48 | return this;
49 | }
50 |
51 | @Override
52 | public String toString() {
53 | return new Gson().toJson(this);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'ru.cleverpumpkin.proguard-dictionaries-generator'
4 | }
5 |
6 | android {
7 | compileSdk 33
8 |
9 | defaultConfig {
10 | applicationId "com.github.catvod.demo"
11 | minSdk 17
12 | targetSdk 29
13 | ndk { abiFilters "armeabi-v7a" }
14 | buildConfigField("String", "CLIENT_ID", "\"${clientId}\"")
15 | }
16 |
17 | buildTypes {
18 | release {
19 | minifyEnabled true
20 | proguardFiles 'proguard-rules.pro'
21 | proguardDictionaries {
22 | dictionaryNames = ["build/class-dictionary", "build/package-dictionary", "build/obfuscation-dictionary"]
23 | minLineLength 1
24 | maxLineLength 3
25 | linesCountInDictionary 100000
26 | }
27 | }
28 | }
29 |
30 | compileOptions {
31 | sourceCompatibility JavaVersion.VERSION_1_8
32 | targetCompatibility JavaVersion.VERSION_1_8
33 | }
34 | }
35 |
36 | dependencies {
37 | //Debug For HTTP/3
38 | debugImplementation 'org.chromium.net:cronet-embedded:101.4951.41'
39 | implementation('com.github.thegrizzlylabs:sardine-android:0.8') { exclude group: 'com.squareup.okhttp3', module: 'okhttp' }
40 | implementation('com.squareup.okhttp3:okhttp:3.12.13') { force = true }
41 | implementation 'com.google.net.cronet:cronet-okhttp:0.1.0'
42 | implementation 'com.google.code.gson:gson:2.8.6'
43 | implementation 'cn.wanghaomiao:JsoupXpath:2.5.1'
44 | implementation 'com.google.zxing:core:3.3.0'
45 | implementation 'org.jsoup:jsoup:1.15.3'
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/utils/QRCode.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.utils;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | import com.google.zxing.BarcodeFormat;
6 | import com.google.zxing.EncodeHintType;
7 | import com.google.zxing.MultiFormatWriter;
8 | import com.google.zxing.common.BitMatrix;
9 |
10 | import java.util.EnumMap;
11 | import java.util.Map;
12 |
13 | public class QRCode {
14 |
15 | private static final int WHITE = 0xFFFFFFFF;
16 | private static final int BLACK = 0xFF000000;
17 |
18 | public static Bitmap createBitmap(BitMatrix matrix) {
19 | int width = matrix.getWidth();
20 | int height = matrix.getHeight();
21 | int[] pixels = new int[width * height];
22 | for (int y = 0; y < height; y++) {
23 | int offset = y * width;
24 | for (int x = 0; x < width; x++) {
25 | pixels[offset + x] = matrix.get(x, y) ? BLACK : WHITE;
26 | }
27 | }
28 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
29 | bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
30 | return bitmap;
31 | }
32 |
33 | public static Bitmap getBitmap(String contents, int size, int margin) {
34 | try {
35 | Map hints = new EnumMap<>(EncodeHintType.class);
36 | hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
37 | hints.put(EncodeHintType.MARGIN, margin);
38 | return createBitmap(new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, Utils.dp2px(size), Utils.dp2px(size), hints));
39 | } catch (Exception e) {
40 | e.printStackTrace();
41 | return null;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tools/src/main/java/com/fongmi/tools/bean/Group.java:
--------------------------------------------------------------------------------
1 | package com.fongmi.tools.bean;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class Group {
9 |
10 | @SerializedName("channel")
11 | private List channel;
12 | @SerializedName("logo")
13 | private String logo;
14 | @SerializedName("name")
15 | private String name;
16 | @SerializedName("pass")
17 | private String pass;
18 |
19 | public static Group create(String name) {
20 | return new Group(name);
21 | }
22 |
23 | public Group(String name) {
24 | this.name = name;
25 | if (!name.contains("_")) return;
26 | setName(name.split("_")[0]);
27 | setPass(name.split("_")[1]);
28 | }
29 |
30 | public List getChannel() {
31 | return channel = channel == null ? new ArrayList<>() : channel;
32 | }
33 |
34 | public void setLogo(String logo) {
35 | this.logo = logo;
36 | }
37 |
38 | public String getName() {
39 | return name == null ? "" : name;
40 | }
41 |
42 | public void setName(String name) {
43 | this.name = name;
44 | }
45 |
46 | public void setPass(String pass) {
47 | this.pass = pass;
48 | }
49 |
50 | public Channel find(Channel channel) {
51 | int index = getChannel().indexOf(channel);
52 | if (index != -1) return getChannel().get(index);
53 | getChannel().add(channel);
54 | return channel;
55 | }
56 |
57 | @Override
58 | public boolean equals(Object obj) {
59 | if (obj == null) return false;
60 | if (this == obj) return true;
61 | if (!(obj instanceof Group)) return false;
62 | Group it = (Group) obj;
63 | return getName().equals(it.getName()) && getChannel().size() == it.getChannel().size();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/utils/Prefers.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.utils;
2 |
3 | import static android.content.Context.MODE_PRIVATE;
4 |
5 | import android.content.SharedPreferences;
6 |
7 | import com.github.catvod.spider.Init;
8 |
9 | public class Prefers {
10 |
11 | private static SharedPreferences getPrefers() {
12 | return Init.context().getSharedPreferences(Init.context().getPackageName() + "_preferences", MODE_PRIVATE);
13 | }
14 |
15 | public static String getString(String key, String defaultValue) {
16 | return getPrefers().getString(key, defaultValue);
17 | }
18 |
19 | public static String getString(String key) {
20 | return getString(key, "");
21 | }
22 |
23 | public static int getInt(String key, int defaultValue) {
24 | return getPrefers().getInt(key, defaultValue);
25 | }
26 |
27 | public static int getInt(String key) {
28 | return getInt(key, 0);
29 | }
30 |
31 | public static boolean getBoolean(String key, boolean defaultValue) {
32 | return getPrefers().getBoolean(key, defaultValue);
33 | }
34 |
35 | public static boolean getBoolean(String key) {
36 | return getPrefers().getBoolean(key, false);
37 | }
38 |
39 | public static void put(String key, Object obj) {
40 | if (obj == null) return;
41 | if (obj instanceof String) {
42 | getPrefers().edit().putString(key, (String) obj).apply();
43 | } else if (obj instanceof Boolean) {
44 | getPrefers().edit().putBoolean(key, (Boolean) obj).apply();
45 | } else if (obj instanceof Float) {
46 | getPrefers().edit().putFloat(key, (Float) obj).apply();
47 | } else if (obj instanceof Integer) {
48 | getPrefers().edit().putInt(key, (Integer) obj).apply();
49 | } else if (obj instanceof Long) {
50 | getPrefers().edit().putLong(key, (Long) obj).apply();
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/utils/FileUtil.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.utils;
2 |
3 | import com.github.catvod.spider.Init;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.FileOutputStream;
9 | import java.io.InputStream;
10 | import java.io.InputStreamReader;
11 |
12 | public class FileUtil {
13 |
14 | public static File getExternalCacheDir() {
15 | return Init.context().getExternalCacheDir();
16 | }
17 |
18 | public static File getCacheDir() {
19 | return Init.context().getCacheDir();
20 | }
21 |
22 | public static File getCacheFile(String fileName) {
23 | return getExternalCacheDir().canWrite() ? new File(getExternalCacheDir(), fileName) : new File(getCacheDir(), fileName);
24 | }
25 |
26 | public static void write(File file, String data) {
27 | write(file, data.getBytes());
28 | }
29 |
30 | public static void write(File file, byte[] data) {
31 | try {
32 | FileOutputStream fos = new FileOutputStream(file);
33 | fos.write(data);
34 | fos.flush();
35 | fos.close();
36 | } catch (Exception e) {
37 | e.printStackTrace();
38 | }
39 | }
40 |
41 | public static String read(File file) {
42 | try {
43 | return read(new FileInputStream(file));
44 | } catch (Exception e) {
45 | return "";
46 | }
47 | }
48 |
49 | public static String read(InputStream is) {
50 | try {
51 | BufferedReader br = new BufferedReader(new InputStreamReader(is));
52 | StringBuilder sb = new StringBuilder();
53 | String text;
54 | while ((text = br.readLine()) != null) sb.append(text).append("\n");
55 | br.close();
56 | return Utils.substring(sb.toString());
57 | } catch (Exception e) {
58 | return "";
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/UpYun.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 |
5 | import com.github.catvod.bean.Result;
6 | import com.github.catvod.bean.Vod;
7 | import com.github.catvod.bean.upyun.Data;
8 | import com.github.catvod.bean.upyun.Item;
9 | import com.github.catvod.net.OkHttp;
10 | import com.google.common.io.BaseEncoding;
11 |
12 | import java.net.URLEncoder;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | import javax.crypto.Cipher;
17 | import javax.crypto.spec.IvParameterSpec;
18 | import javax.crypto.spec.SecretKeySpec;
19 |
20 | public class UpYun extends Ali {
21 |
22 | @Override
23 | public void init(Context context, String extend) {
24 | super.init(context, extend);
25 | }
26 |
27 | @Override
28 | public String searchContent(String key, boolean quick) throws Exception {
29 | String res = decode(OkHttp.string("https://zyb.upyunso.com/v15/search?keyword=" + URLEncoder.encode(key) + "&page=1&s_type=2"));
30 | List list = new ArrayList<>();
31 | for (Item item : Data.objectFrom(res).getResult().getItems()) {
32 | String url = decode(item.getPageUrl());
33 | if (!url.contains("www.aliyundrive.com")) continue;
34 | if (item.getTitle().contains(key)) list.add(item.url(url).getVod());
35 | }
36 | return Result.string(list);
37 | }
38 |
39 | private String decode(String data) throws Exception {
40 | SecretKeySpec keySpec = new SecretKeySpec("qq1920520460qqzz".getBytes(), "AES");
41 | IvParameterSpec ivSpec = new IvParameterSpec("qq1920520460qqzz".getBytes());
42 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
43 | cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
44 | byte[] encryptDataBytes = BaseEncoding.base16().decode(data.toUpperCase());
45 | byte[] decryptData = cipher.doFinal(encryptDataBytes);
46 | return new String(decryptData, "UTF-8");
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/ali/User.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.ali;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.ali.API;
6 | import com.github.catvod.utils.FileUtil;
7 | import com.google.gson.Gson;
8 | import com.google.gson.annotations.SerializedName;
9 |
10 | public class User {
11 |
12 | @SerializedName("default_drive_id")
13 | private String driveId;
14 | @SerializedName("user_id")
15 | private String userId;
16 | @SerializedName("token_type")
17 | private String tokenType;
18 | @SerializedName("access_token")
19 | private String accessToken;
20 | @SerializedName("refresh_token")
21 | private String refreshToken;
22 |
23 | public static User objectFrom(String str) {
24 | User item = new Gson().fromJson(str, User.class);
25 | return item == null ? new User() : item;
26 | }
27 |
28 | public String getDriveId() {
29 | return TextUtils.isEmpty(driveId) ? "" : driveId;
30 | }
31 |
32 | public String getUserId() {
33 | return TextUtils.isEmpty(userId) ? "" : userId;
34 | }
35 |
36 | public String getTokenType() {
37 | return TextUtils.isEmpty(tokenType) ? "" : tokenType;
38 | }
39 |
40 | public String getAccessToken() {
41 | return TextUtils.isEmpty(accessToken) ? "" : accessToken;
42 | }
43 |
44 | public String getRefreshToken() {
45 | return TextUtils.isEmpty(refreshToken) ? "" : refreshToken;
46 | }
47 |
48 | public void setRefreshToken(String refreshToken) {
49 | this.refreshToken = refreshToken;
50 | }
51 |
52 | public String getAuthorization() {
53 | return getTokenType() + " " + getAccessToken();
54 | }
55 |
56 | public User clean() {
57 | this.refreshToken = "";
58 | this.accessToken = "";
59 | return this;
60 | }
61 |
62 | public User save() {
63 | FileUtil.write(API.get().getUserCache(), toString());
64 | return this;
65 | }
66 |
67 | @Override
68 | public String toString() {
69 | return new Gson().toJson(this);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/ali/Biz.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.ali;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.annotations.SerializedName;
5 |
6 | import java.util.List;
7 |
8 | public class Biz {
9 |
10 | @SerializedName("pds_login_result")
11 | private Biz pdsLoginResult;
12 | @SerializedName("role")
13 | private String role;
14 | @SerializedName("isFirstLogin")
15 | private Boolean isFirstLogin;
16 | @SerializedName("needLink")
17 | private Boolean needLink;
18 | @SerializedName("loginType")
19 | private String loginType;
20 | @SerializedName("nickName")
21 | private String nickName;
22 | @SerializedName("needRpVerify")
23 | private Boolean needRpVerify;
24 | @SerializedName("avatar")
25 | private String avatar;
26 | @SerializedName("accessToken")
27 | private String accessToken;
28 | @SerializedName("userName")
29 | private String userName;
30 | @SerializedName("userId")
31 | private String userId;
32 | @SerializedName("defaultDriveId")
33 | private String defaultDriveId;
34 | @SerializedName("existLink")
35 | private List> existLink;
36 | @SerializedName("expiresIn")
37 | private Integer expiresIn;
38 | @SerializedName("expireTime")
39 | private String expireTime;
40 | @SerializedName("requestId")
41 | private String requestId;
42 | @SerializedName("dataPinSetup")
43 | private Boolean dataPinSetup;
44 | @SerializedName("state")
45 | private String state;
46 | @SerializedName("tokenType")
47 | private String tokenType;
48 | @SerializedName("dataPinSaved")
49 | private Boolean dataPinSaved;
50 | @SerializedName("refreshToken")
51 | private String refreshToken;
52 | @SerializedName("status")
53 | private String status;
54 |
55 | public static Biz objectFrom(String str) {
56 | return new Gson().fromJson(str, Biz.class);
57 | }
58 |
59 | public Biz getPdsLoginResult() {
60 | return pdsLoginResult;
61 | }
62 |
63 | public String getRefreshToken() {
64 | return refreshToken;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Ali.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 |
6 | import com.github.catvod.ali.API;
7 | import com.github.catvod.bean.Result;
8 | import com.github.catvod.crawler.Spider;
9 | import com.github.catvod.utils.ReflectUtil;
10 |
11 | import java.lang.reflect.Method;
12 | import java.util.List;
13 | import java.util.Map;
14 | import java.util.regex.Matcher;
15 | import java.util.regex.Pattern;
16 |
17 | /**
18 | * @author ColaMint & Adam & FongMi
19 | */
20 | public class Ali extends Spider {
21 |
22 | public static final Pattern pattern = Pattern.compile("www.aliyundrive.com/s/([^/]+)(/folder/([^/]+))?");
23 |
24 | @Override
25 | public void init(Context context, String extend) {
26 | //适配其他tvbox或者老版本tvbox,要先判断有没有getToken方法,调用setToken也是一样的
27 | Method method = ReflectUtil.getMethod(this, "getToken");
28 | String token = "";
29 | if (method != null) {
30 | token = getToken();
31 | }
32 | API.get().setRefreshToken(TextUtils.isEmpty(token) ? extend : token);
33 | }
34 |
35 | @Override
36 | public String detailContent(List ids) throws Exception {
37 | String url = ids.get(0).trim();
38 | Matcher matcher = pattern.matcher(url);
39 | if (!matcher.find()) return "";
40 | String shareId = matcher.group(1);
41 | String fileId = matcher.groupCount() == 3 ? matcher.group(3) : "";
42 | API.get().setShareId(shareId);
43 | return Result.string(API.get().getVod(url, fileId));
44 | }
45 |
46 | @Override
47 | public String playerContent(String flag, String id, List vipFlags) {
48 | String[] ids = id.split("\\+");
49 | return flag.equals("原畫") ? API.get().playerContent(ids) : API.get().playerContent(ids, flag);
50 | }
51 |
52 | public static Object[] proxy(Map params) {
53 | String type = params.get("type");
54 | if (type.equals("sub")) return API.get().proxySub(params);
55 | if (type.equals("token")) return API.get().getToken();
56 | return null;
57 | }
58 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/TuGou.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 |
5 | import com.github.catvod.bean.Result;
6 | import com.github.catvod.bean.Vod;
7 | import com.github.catvod.net.OkHttp;
8 | import com.github.catvod.utils.Utils;
9 |
10 | import org.jsoup.Jsoup;
11 | import org.jsoup.nodes.Element;
12 | import org.jsoup.select.Elements;
13 |
14 | import java.util.List;
15 | import java.util.ArrayList;
16 | import java.util.HashMap;
17 | import java.util.Map;
18 |
19 | /**
20 | * @author zhixc
21 | */
22 | public class TuGou extends Ali {
23 |
24 | private final String URL = "https://tugousou.com";
25 |
26 | private Map getHeader() {
27 | Map header = new HashMap<>();
28 | header.put("User-Agent", Utils.CHROME);
29 | header.put("Host", "tugousou.com");
30 | header.put("Origin", URL);
31 | header.put("Referer", URL + "/");
32 | return header;
33 | }
34 |
35 | @Override
36 | public void init(Context context, String extend) {
37 | super.init(context, extend);
38 | }
39 |
40 | @Override
41 | public String searchContent(String key, boolean quick) {
42 | Map params = new HashMap<>();
43 | params.put("keyword", key);
44 | String html = OkHttp.post(URL + "/search", params, getHeader());
45 | Element container = Jsoup.parse(html).select(".layui-container").get(1);
46 | Elements aElements = container.select("p[class=layui-font-16] > a");
47 | Elements pElements = container.select("p[class=layui-font-14 layui-font-gray text-align-right]");
48 | List list = new ArrayList<>();
49 | for (int i = 0; i < aElements.size(); i++) {
50 | Element item = aElements.get(i);
51 | String vodId = item.attr("href");
52 | String name = item.text();
53 | String pic = "https://inews.gtimg.com/newsapp_bt/0/13263837859/1000";
54 | String remark = pElements.get(i).text();
55 | list.add(new Vod(vodId, name, pic, remark));
56 | }
57 | return Result.string(list);
58 | }
59 | }
--------------------------------------------------------------------------------
/tools/src/main/java/com/fongmi/tools/bean/Channel.java:
--------------------------------------------------------------------------------
1 | package com.fongmi.tools.bean;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.Comparator;
8 | import java.util.List;
9 |
10 | public class Channel {
11 |
12 | @SerializedName("urls")
13 | private List urls;
14 | @SerializedName("number")
15 | private String number;
16 | @SerializedName("logo")
17 | private String logo;
18 | @SerializedName("epg")
19 | private String epg;
20 | @SerializedName("name")
21 | private String name;
22 | @SerializedName("ua")
23 | private String ua;
24 |
25 | public static Channel create() {
26 | return new Channel();
27 | }
28 |
29 | public List getUrls() {
30 | return urls = urls == null ? new ArrayList<>() : urls;
31 | }
32 |
33 | public String getNumber() {
34 | return number == null ? "" : number;
35 | }
36 |
37 | public String getName() {
38 | return name == null ? "" : name;
39 | }
40 |
41 | public Channel number(String number) {
42 | this.number = number;
43 | return this;
44 | }
45 |
46 | public Channel logo(String logo) {
47 | this.logo = logo;
48 | return this;
49 | }
50 |
51 | public Channel epg(String epg) {
52 | this.epg = epg;
53 | return this;
54 | }
55 |
56 | public Channel name(String name) {
57 | this.name = name;
58 | return this;
59 | }
60 |
61 | public Channel ua(String ua) {
62 | this.ua = ua;
63 | return this;
64 | }
65 |
66 | public void addUrls(String... urls) {
67 | getUrls().addAll(new ArrayList<>(Arrays.asList(urls)));
68 | }
69 |
70 | @Override
71 | public boolean equals(Object obj) {
72 | if (this == obj) return true;
73 | if (!(obj instanceof Channel)) return false;
74 | Channel it = (Channel) obj;
75 | return getName().equals(it.getName()) || (!getNumber().isEmpty() && getNumber().equals(it.getNumber()));
76 | }
77 |
78 | public static class Sorter implements Comparator {
79 |
80 | @Override
81 | public int compare(Channel c1, Channel c2) {
82 | return Integer.compare(Integer.parseInt(c1.getNumber()), Integer.parseInt(c2.getNumber()));
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Push.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 |
6 | import com.github.catvod.bean.Result;
7 | import com.github.catvod.bean.Sub;
8 | import com.github.catvod.bean.Vod;
9 | import com.github.catvod.utils.Utils;
10 |
11 | import java.io.File;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.Collections;
15 | import java.util.List;
16 | import java.util.Objects;
17 |
18 | public class Push extends Ali {
19 |
20 | @Override
21 | public void init(Context context, String extend) {
22 | super.init(context, extend);
23 | }
24 |
25 | @Override
26 | public String detailContent(List ids) throws Exception {
27 | String url = ids.get(0).trim();
28 | if (url.contains("aliyundrive")) return super.detailContent(ids);
29 | return Result.string(vod(url));
30 | }
31 |
32 | @Override
33 | public String playerContent(String flag, String id, List vipFlags) {
34 | if (flag.equals("直連")) return Result.get().url(id).subs(getSubs(id)).string();
35 | if (flag.equals("嗅探")) return Result.get().parse().url(id).string();
36 | if (flag.equals("解析")) return Result.get().parse().jx().url(id).string();
37 | return super.playerContent(flag, id, vipFlags);
38 | }
39 |
40 | private Vod vod(String url) {
41 | Vod vod = new Vod();
42 | vod.setVodId(url);
43 | vod.setTypeName("FongMi");
44 | vod.setVodName(url.startsWith("file://") ? new File(url).getName() : url);
45 | vod.setVodPic("https://pic.rmb.bdstatic.com/bjh/1d0b02d0f57f0a42201f92caba5107ed.jpeg");
46 | vod.setVodPlayFrom(TextUtils.join("$$$", Arrays.asList("直連", "嗅探", "解析")));
47 | vod.setVodPlayUrl(TextUtils.join("$$$", Arrays.asList("播放$" + url, "播放$" + url, "播放$" + url)));
48 | return vod;
49 | }
50 |
51 | private List getSubs(String url) {
52 | if (!url.startsWith("file://")) return Collections.emptyList();
53 | File file = new File(url.replace("file://", ""));
54 | if (file.getParentFile() == null) return Collections.emptyList();
55 | List subs = new ArrayList<>();
56 | for (File f : Objects.requireNonNull(file.getParentFile().listFiles())) {
57 | String ext = Utils.getExt(f.getName());
58 | if (Utils.isSub(ext)) subs.add(Sub.create().name(Utils.removeExt(f.getName())).ext(ext).url("file://" + f.getAbsolutePath()));
59 | }
60 | return subs;
61 | }
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/ali/Item.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.ali;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.utils.Utils;
6 | import com.google.gson.Gson;
7 | import com.google.gson.annotations.SerializedName;
8 |
9 | import java.util.Arrays;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | public class Item {
14 |
15 | @SerializedName("items")
16 | private List- items;
17 | @SerializedName("next_marker")
18 | private String nextMarker;
19 | @SerializedName("file_id")
20 | private String fileId;
21 | @SerializedName("share_id")
22 | private String shareId;
23 | @SerializedName("name")
24 | private String name;
25 | @SerializedName("type")
26 | private String type;
27 | @SerializedName("file_extension")
28 | private String fileExtension;
29 | @SerializedName("category")
30 | private String category;
31 | @SerializedName("size")
32 | private double size;
33 | @SerializedName("parent")
34 | private String parent;
35 |
36 | public static Item objectFrom(String str) {
37 | return new Gson().fromJson(str, Item.class);
38 | }
39 |
40 | public Item(String fileId) {
41 | this.fileId = fileId;
42 | }
43 |
44 | public List
- getItems() {
45 | return items == null ? Collections.emptyList() : items;
46 | }
47 |
48 | public String getNextMarker() {
49 | return TextUtils.isEmpty(nextMarker) ? "" : nextMarker;
50 | }
51 |
52 | public String getFileId() {
53 | return TextUtils.isEmpty(fileId) ? "" : fileId;
54 | }
55 |
56 | public String getName() {
57 | return TextUtils.isEmpty(name) ? "" : name;
58 | }
59 |
60 | public String getType() {
61 | return TextUtils.isEmpty(type) ? "" : type;
62 | }
63 |
64 | public String getExt() {
65 | return TextUtils.isEmpty(fileExtension) ? "" : fileExtension;
66 | }
67 |
68 | public String getCategory() {
69 | return TextUtils.isEmpty(category) ? "" : category;
70 | }
71 |
72 | public String getSize() {
73 | return size == 0 ? "" : "[" + Utils.getSize(size) + "]";
74 | }
75 |
76 | public String getParent() {
77 | return TextUtils.isEmpty(parent) ? "" : "[" + parent + "]";
78 | }
79 |
80 | public Item parent(String parent) {
81 | this.parent = parent;
82 | return this;
83 | }
84 |
85 | public String getDisplayName() {
86 | return TextUtils.join(" ", Arrays.asList(getParent(), getName(), getSize())).trim();
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/PanSearch.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 |
5 | import com.github.catvod.bean.Result;
6 | import com.github.catvod.bean.Vod;
7 | import com.github.catvod.net.OkHttp;
8 | import com.github.catvod.utils.Utils;
9 |
10 | import org.json.JSONArray;
11 | import org.json.JSONObject;
12 | import org.jsoup.Jsoup;
13 |
14 | import java.net.URLEncoder;
15 | import java.util.ArrayList;
16 | import java.util.HashMap;
17 | import java.util.List;
18 | import java.util.Map;
19 |
20 | /**
21 | * @author zhixc
22 | */
23 | public class PanSearch extends Ali {
24 |
25 | private final String URL = "https://www.pansearch.me/";
26 |
27 | private Map getHeader() {
28 | Map header = new HashMap<>();
29 | header.put("User-Agent", Utils.CHROME);
30 | return header;
31 | }
32 |
33 | private Map getSearchHeader() {
34 | Map header = getHeader();
35 | header.put("x-nextjs-data", "1");
36 | header.put("referer", URL);
37 | return header;
38 | }
39 |
40 | @Override
41 | public void init(Context context, String extend) {
42 | super.init(context, extend);
43 | }
44 |
45 | @Override
46 | public String searchContent(String key, boolean quick) throws Exception {
47 | String html = OkHttp.string(URL, getHeader());
48 | String data = Jsoup.parse(html).select("script[id=__NEXT_DATA__]").get(0).data();
49 | String buildId = new JSONObject(data).getString("buildId");
50 | String url = URL + "_next/data/" + buildId + "/search.json?keyword=" + URLEncoder.encode(key) + "&pan=aliyundrive";
51 | String result = OkHttp.string(url, getSearchHeader());
52 | JSONArray array = new JSONObject(result).getJSONObject("pageProps").getJSONObject("data").getJSONArray("data");
53 | List list = new ArrayList<>();
54 | for (int i = 0; i < array.length(); i++) {
55 | JSONObject item = array.getJSONObject(i);
56 | String content = item.optString("content");
57 | String[] split = content.split("\\n");
58 | if (split.length == 0) continue;
59 | String vodId = Jsoup.parse(content).select("a").attr("href");
60 | String name = split[0].replaceAll("?[^>]+>", "");
61 | String remark = item.optString("time");
62 | String pic = item.optString("image");
63 | list.add(new Vod(vodId, name, pic, remark));
64 | }
65 | return Result.string(list);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/yiso/Item.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.yiso;
2 |
3 | import com.github.catvod.bean.Vod;
4 | import com.google.gson.Gson;
5 | import com.google.gson.annotations.SerializedName;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Collections;
9 | import java.util.List;
10 |
11 | public class Item {
12 |
13 | @SerializedName("data")
14 | private DataDTO data;
15 |
16 | public static Item objectFrom(String str) {
17 | try {
18 | return new Gson().fromJson(str, Item.class);
19 | } catch (Exception e) {
20 | e.printStackTrace();
21 | return new Item();
22 | }
23 | }
24 |
25 | public DataDTO getData() {
26 | return data == null ? new DataDTO() : data;
27 | }
28 |
29 | public static class DataDTO {
30 |
31 | @SerializedName("list")
32 | private List list;
33 |
34 | public List getList(String key) {
35 | List items = new ArrayList<>();
36 | list = list == null ? Collections.emptyList() : list;
37 | for (ListDTO item : list) if (item.getName().contains(key)) items.add(item.getVod());
38 | return items;
39 | }
40 |
41 | public static class ListDTO {
42 |
43 | @SerializedName("url")
44 | private String url;
45 | @SerializedName("gmtCreate")
46 | private String gmtCreate;
47 | @SerializedName("fileInfos")
48 | private List fileInfos;
49 |
50 | public String getUrl() {
51 | return url;
52 | }
53 |
54 | public String getGmtCreate() {
55 | return gmtCreate;
56 | }
57 |
58 | public List getFileInfos() {
59 | return fileInfos;
60 | }
61 |
62 | public String getName() {
63 | return getFileInfos().get(0).getFileName();
64 | }
65 |
66 | public Vod getVod() {
67 | String id = getUrl();
68 | String name = getName();
69 | String remark = getGmtCreate();
70 | String pic = "https://inews.gtimg.com/newsapp_bt/0/13263837859/1000";
71 | return new Vod(id, name, pic, remark);
72 | }
73 |
74 | public static class FileInfoDTO {
75 |
76 | @SerializedName("fileName")
77 | private String fileName;
78 |
79 | public String getFileName() {
80 | return fileName;
81 | }
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/ali/Data.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.ali;
2 |
3 | import android.util.Base64;
4 |
5 | import com.google.gson.Gson;
6 | import com.google.gson.annotations.SerializedName;
7 |
8 | import java.util.HashMap;
9 | import java.util.Map;
10 |
11 | public class Data {
12 |
13 | @SerializedName("data")
14 | private Data data;
15 | @SerializedName("content")
16 | private Data content;
17 | @SerializedName("t")
18 | private String t;
19 | @SerializedName("ck")
20 | private String ck;
21 | @SerializedName("codeContent")
22 | private String codeContent;
23 | @SerializedName("qrCodeStatus")
24 | private String qrCodeStatus;
25 | @SerializedName("bizExt")
26 | private String bizExt;
27 |
28 | public static Data objectFrom(String str) {
29 | try {
30 | Data data = new Gson().fromJson(str, Data.class);
31 | return data == null ? new Data() : data;
32 | } catch (Exception e) {
33 | return new Data();
34 | }
35 | }
36 |
37 | public Data getData() {
38 | return data == null ? new Data() : data;
39 | }
40 |
41 | public Data getContent() {
42 | return content == null ? new Data() : content;
43 | }
44 |
45 | public String getT() {
46 | return t == null ? "" : t;
47 | }
48 |
49 | public String getCk() {
50 | return ck == null ? "" : ck;
51 | }
52 |
53 | public String getCodeContent() {
54 | return codeContent == null ? "" : codeContent;
55 | }
56 |
57 | public String getQrCodeStatus() {
58 | return qrCodeStatus == null ? "" : qrCodeStatus;
59 | }
60 |
61 | public String getBizExt() {
62 | return bizExt == null ? "" : bizExt;
63 | }
64 |
65 | public String getToken() {
66 | return Biz.objectFrom(new String(Base64.decode(getBizExt(), Base64.DEFAULT))).getPdsLoginResult().getRefreshToken();
67 | }
68 |
69 | public boolean hasToken() {
70 | return getQrCodeStatus().equals("CONFIRMED") && getBizExt().length() > 0;
71 | }
72 |
73 | public Map getParams() {
74 | Map params = new HashMap<>();
75 | params.put("t", getT());
76 | params.put("ck", getCk());
77 | params.put("appName", "aliyun_drive");
78 | params.put("appEntrance", "web");
79 | params.put("isMobile", "false");
80 | params.put("lang", "zh_CN");
81 | params.put("returnUrl", "");
82 | params.put("fromSite", "52");
83 | params.put("bizParams", "");
84 | params.put("navlanguage", "zh-CN");
85 | params.put("navPlatform", "MacIntel");
86 | return params;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/PanSou.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 |
5 | import com.github.catvod.bean.Result;
6 | import com.github.catvod.bean.Vod;
7 | import com.github.catvod.net.OkHttp;
8 | import com.github.catvod.utils.Utils;
9 |
10 | import org.jsoup.Jsoup;
11 | import org.jsoup.nodes.Element;
12 | import org.jsoup.select.Elements;
13 |
14 | import java.net.URLEncoder;
15 | import java.util.ArrayList;
16 | import java.util.Arrays;
17 | import java.util.HashMap;
18 | import java.util.List;
19 | import java.util.Map;
20 |
21 | /**
22 | * @author ColaMint & FongMi
23 | */
24 | public class PanSou extends Ali {
25 |
26 | private final String siteUrl = "https://www.alipansou.com";
27 |
28 | private Map getHeaders(String id) {
29 | HashMap headers = new HashMap<>();
30 | headers.put("User-Agent", Utils.CHROME);
31 | headers.put("Referer", siteUrl + id);
32 | headers.put("_bid", "6d14a5dd6c07980d9dc089a693805ad8");
33 | return headers;
34 | }
35 |
36 | @Override
37 | public void init(Context context, String extend) {
38 | super.init(context, extend);
39 | }
40 |
41 | @Override
42 | public String detailContent(List ids) throws Exception {
43 | if (pattern.matcher(ids.get(0)).find()) return super.detailContent(ids);
44 | String url = siteUrl + ids.get(0).replace("/s/", "/cv/");
45 | Map> respHeaders = new HashMap<>();
46 | OkHttp.stringNoRedirect(url, getHeaders(ids.get(0)), respHeaders);
47 | url = OkHttp.getRedirectLocation(respHeaders);
48 | return super.detailContent(Arrays.asList(url));
49 | }
50 |
51 | @Override
52 | public String searchContent(String key, boolean quick) {
53 | Map types = new HashMap<>();
54 | types.put("7", "資料夾");
55 | types.put("1", "影片");
56 | List list = new ArrayList<>();
57 | for (Map.Entry entry : types.entrySet()) {
58 | String typeId = entry.getKey();
59 | String typeName = entry.getValue();
60 | String url = siteUrl + "/search?k=" + URLEncoder.encode(key) + "&t=" + typeId;
61 | Elements items = Jsoup.parse(OkHttp.string(url)).select("van-row > a");
62 | for (Element item : items) {
63 | String title = item.selectFirst("template").text().trim();
64 | if (!title.contains(key)) continue;
65 | Vod vod = new Vod();
66 | vod.setVodId(item.attr("href"));
67 | vod.setVodName("[" + typeName + "] " + title);
68 | vod.setVodPic("https://inews.gtimg.com/newsapp_bt/0/13263837859/1000");
69 | list.add(vod);
70 | }
71 | }
72 | return Result.string(list);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Init.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.app.Activity;
4 | import android.app.Application;
5 | import android.content.Context;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.widget.Toast;
9 |
10 | import com.github.catvod.crawler.SpiderDebug;
11 |
12 | import java.lang.reflect.Field;
13 | import java.util.Map;
14 | import java.util.concurrent.ExecutorService;
15 | import java.util.concurrent.Executors;
16 |
17 | public class Init {
18 |
19 | private final ExecutorService executor;
20 | private final Handler handler;
21 | private Application app;
22 |
23 | private static class Loader {
24 | static volatile Init INSTANCE = new Init();
25 | }
26 |
27 | public static Init get() {
28 | return Loader.INSTANCE;
29 | }
30 |
31 | public Init() {
32 | this.handler = new Handler(Looper.getMainLooper());
33 | this.executor = Executors.newFixedThreadPool(5);
34 | }
35 |
36 | public static Application context() {
37 | return get().app;
38 | }
39 |
40 | public static void init(Context context) {
41 | SpiderDebug.log("自定義爬蟲代碼載入成功!");
42 | get().app = ((Application) context);
43 | }
44 |
45 | public static void execute(Runnable runnable) {
46 | get().executor.execute(runnable);
47 | }
48 |
49 | public static void run(Runnable runnable) {
50 | get().handler.post(runnable);
51 | }
52 |
53 | public static void run(Runnable runnable, int delay) {
54 | get().handler.postDelayed(runnable, delay);
55 | }
56 |
57 | public static void show(String msg) {
58 | get().handler.post(() -> Toast.makeText(context(), msg, Toast.LENGTH_LONG).show());
59 | }
60 |
61 | public static Activity getActivity() throws Exception {
62 | Class> activityThreadClass = Class.forName("android.app.ActivityThread");
63 | Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
64 | Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
65 | activitiesField.setAccessible(true);
66 | Map, ?> activities = (Map, ?>) activitiesField.get(activityThread);
67 | for (Object activityRecord : activities.values()) {
68 | Class> activityRecordClass = activityRecord.getClass();
69 | Field pausedField = activityRecordClass.getDeclaredField("paused");
70 | pausedField.setAccessible(true);
71 | if (!pausedField.getBoolean(activityRecord)) {
72 | Field activityField = activityRecordClass.getDeclaredField("activity");
73 | activityField.setAccessible(true);
74 | Activity activity = (Activity) activityField.get(activityRecord);
75 | SpiderDebug.log(activity.getComponentName().getClassName());
76 | return activity;
77 | }
78 | }
79 | return null;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/webdav/Drive.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.webdav;
2 |
3 | import android.net.Uri;
4 | import android.text.TextUtils;
5 |
6 | import com.github.catvod.bean.Class;
7 | import com.github.catvod.bean.Vod;
8 | import com.github.catvod.utils.Utils;
9 | import com.google.gson.Gson;
10 | import com.google.gson.annotations.SerializedName;
11 | import com.thegrizzlylabs.sardineandroid.DavResource;
12 | import com.thegrizzlylabs.sardineandroid.Sardine;
13 | import com.thegrizzlylabs.sardineandroid.impl.OkHttpSardine;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | public class Drive {
19 |
20 | @SerializedName("drives")
21 | private List drives;
22 | @SerializedName("name")
23 | private String name;
24 | @SerializedName("server")
25 | private String server;
26 | @SerializedName("user")
27 | private String user;
28 | @SerializedName("pass")
29 | private String pass;
30 | @SerializedName("path")
31 | private String path;
32 | @SerializedName("webdav")
33 | private Sardine webdav;
34 |
35 | public static Drive objectFrom(String str) {
36 | return new Gson().fromJson(str, Drive.class);
37 | }
38 |
39 | public Drive(String name) {
40 | this.name = name;
41 | }
42 |
43 | public List getDrives() {
44 | return drives == null ? new ArrayList<>() : drives;
45 | }
46 |
47 | public String getName() {
48 | return TextUtils.isEmpty(name) ? "" : name;
49 | }
50 |
51 | public String getServer() {
52 | return TextUtils.isEmpty(server) ? "" : server;
53 | }
54 |
55 | public String getUser() {
56 | return TextUtils.isEmpty(user) ? "" : user;
57 | }
58 |
59 | public String getPass() {
60 | return TextUtils.isEmpty(pass) ? "" : pass;
61 | }
62 |
63 | public String getPath() {
64 | return TextUtils.isEmpty(path) ? "" : path;
65 | }
66 |
67 | public void setPath(String path) {
68 | this.path = TextUtils.isEmpty(path) ? "" : path;
69 | }
70 |
71 | public String getHost() {
72 | return getServer().replace(getPath(), "");
73 | }
74 |
75 | public Sardine getWebdav() {
76 | if (webdav == null) init();
77 | return webdav;
78 | }
79 |
80 | public Class toType() {
81 | return new Class(getName(), getName(), "1");
82 | }
83 |
84 | private void init() {
85 | webdav = new OkHttpSardine();
86 | webdav.setCredentials(getUser(), getPass());
87 | setPath(Uri.parse(getServer()).getPath());
88 | }
89 |
90 | public Vod vod(DavResource item, String vodPic) {
91 | return new Vod(getName() + item.getPath(), item.getName(), vodPic, Utils.getSize(item.getContentLength()), item.isDirectory());
92 | }
93 |
94 | @Override
95 | public boolean equals(Object obj) {
96 | if (this == obj) return true;
97 | if (!(obj instanceof Drive)) return false;
98 | Drive it = (Drive) obj;
99 | return getName().equals(it.getName());
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/net/OkRequest.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.net;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.utils.Utils;
6 |
7 | import java.io.IOException;
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | import okhttp3.FormBody;
12 | import okhttp3.MediaType;
13 | import okhttp3.OkHttpClient;
14 | import okhttp3.Request;
15 | import okhttp3.RequestBody;
16 | import okhttp3.Response;
17 |
18 | class OkRequest {
19 |
20 | private final Map> respHeader;
21 | private final Map header;
22 | private final Map params;
23 | private final String method;
24 | private final String json;
25 | private Request request;
26 | private String url;
27 | private Object tag;
28 |
29 | OkRequest(String method, String url, Map params, Map header, Map> respHeader) {
30 | this(method, url, null, params, header, respHeader);
31 | }
32 |
33 | OkRequest(String method, String url, String json, Map header) {
34 | this(method, url, json, null, header, null);
35 | }
36 |
37 | private OkRequest(String method, String url, String json, Map params, Map header, Map> respHeader) {
38 | this.url = url;
39 | this.json = json;
40 | this.method = method;
41 | this.params = params;
42 | this.header = header;
43 | this.respHeader = respHeader;
44 | getInstance();
45 | }
46 |
47 | public OkRequest tag(Object tag) {
48 | this.tag = tag;
49 | return this;
50 | }
51 |
52 | private void getInstance() {
53 | Request.Builder builder = new Request.Builder();
54 | if (method.equals(OkHttp.GET) && params != null) setParams();
55 | if (method.equals(OkHttp.POST)) builder.post(getRequestBody());
56 | if (header != null) for (String key : header.keySet()) builder.addHeader(key, header.get(key));
57 | if (tag != null) builder.tag(tag);
58 | request = builder.url(url).build();
59 | }
60 |
61 | private RequestBody getRequestBody() {
62 | if (!TextUtils.isEmpty(json)) return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
63 | FormBody.Builder formBody = new FormBody.Builder();
64 | if (params != null) for (String key : params.keySet()) formBody.add(key, params.get(key));
65 | return formBody.build();
66 | }
67 |
68 | private void setParams() {
69 | url = url + "?";
70 | for (String key : params.keySet()) url = url.concat(key + "=" + params.get(key) + "&");
71 | url = Utils.substring(url);
72 | }
73 |
74 | public OkResult execute(OkHttpClient client) {
75 | try {
76 | Response response = client.newCall(request).execute();
77 | if (respHeader != null) respHeader.clear();
78 | if (respHeader != null) respHeader.putAll(response.headers().toMultimap());
79 | return new OkResult(response.code(), response.body().string());
80 | } catch (IOException e) {
81 | return new OkResult();
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/Vod.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class Vod {
6 |
7 | @SerializedName("type_name")
8 | private String typeName;
9 | @SerializedName("vod_id")
10 | private String vodId;
11 | @SerializedName("vod_name")
12 | private String vodName;
13 | @SerializedName("vod_pic")
14 | private String vodPic;
15 | @SerializedName("vod_remarks")
16 | private String vodRemarks;
17 | @SerializedName("vod_year")
18 | private String vodYear;
19 | @SerializedName("vod_area")
20 | private String vodArea;
21 | @SerializedName("vod_actor")
22 | private String vodActor;
23 | @SerializedName("vod_director")
24 | private String vodDirector;
25 | @SerializedName("vod_content")
26 | private String vodContent;
27 | @SerializedName("vod_play_from")
28 | private String vodPlayFrom;
29 | @SerializedName("vod_play_url")
30 | private String vodPlayUrl;
31 | @SerializedName("vod_tag")
32 | private String vodTag;
33 |
34 | public Vod() {
35 | }
36 |
37 | public Vod(String vodId, String vodName, String vodPic) {
38 | setVodId(vodId);
39 | setVodName(vodName);
40 | setVodPic(vodPic);
41 | }
42 |
43 | public Vod(String vodId, String vodName, String vodPic, String vodRemarks) {
44 | setVodId(vodId);
45 | setVodName(vodName);
46 | setVodPic(vodPic);
47 | setVodRemarks(vodRemarks);
48 | }
49 |
50 | public Vod(String vodId, String vodName, String vodPic, String vodRemarks, boolean folder) {
51 | setVodId(vodId);
52 | setVodName(vodName);
53 | setVodPic(vodPic);
54 | setVodRemarks(vodRemarks);
55 | setVodTag(folder ? "folder" : "file");
56 | }
57 |
58 | public void setTypeName(String typeName) {
59 | this.typeName = typeName;
60 | }
61 |
62 | public void setVodId(String vodId) {
63 | this.vodId = vodId;
64 | }
65 |
66 | public void setVodName(String vodName) {
67 | this.vodName = vodName;
68 | }
69 |
70 | public void setVodPic(String vodPic) {
71 | this.vodPic = vodPic;
72 | }
73 |
74 | public void setVodRemarks(String vodRemarks) {
75 | this.vodRemarks = vodRemarks;
76 | }
77 |
78 | public void setVodYear(String vodYear) {
79 | this.vodYear = vodYear;
80 | }
81 |
82 | public void setVodArea(String vodArea) {
83 | this.vodArea = vodArea;
84 | }
85 |
86 | public void setVodActor(String vodActor) {
87 | this.vodActor = vodActor;
88 | }
89 |
90 | public void setVodDirector(String vodDirector) {
91 | this.vodDirector = vodDirector;
92 | }
93 |
94 | public void setVodContent(String vodContent) {
95 | this.vodContent = vodContent;
96 | }
97 |
98 | public String getVodContent() {
99 | return vodContent;
100 | }
101 |
102 | public void setVodPlayFrom(String vodPlayFrom) {
103 | this.vodPlayFrom = vodPlayFrom;
104 | }
105 |
106 | public void setVodPlayUrl(String vodPlayUrl) {
107 | this.vodPlayUrl = vodPlayUrl;
108 | }
109 |
110 | public void setVodTag(String vodTag) {
111 | this.vodTag = vodTag;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/json/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "spider": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;630997f2d36dde4644f99300f559ff68",
3 | "wallpaper": "http://饭太硬.ga/深色壁纸/api.php",
4 | "sites": [
5 | {
6 | "key": "本地",
7 | "name": "本地",
8 | "type": 3,
9 | "api": "csp_Local",
10 | "searchable": 0,
11 | "changeable": 0
12 | },
13 | {
14 | "key": "AList",
15 | "name": "AList",
16 | "type": 3,
17 | "api": "csp_AList",
18 | "searchable": 1,
19 | "changeable": 0,
20 | "ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/alist.json"
21 | },
22 | {
23 | "key": "WebDAV",
24 | "name": "WebDAV",
25 | "type": 3,
26 | "api": "csp_WebDAV",
27 | "searchable": 1,
28 | "changeable": 0,
29 | "ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/webdav.json"
30 | },
31 | {
32 | "key": "哔哩",
33 | "name": "哔哩",
34 | "type": 3,
35 | "api": "csp_Bili",
36 | "searchable": 1,
37 | "changeable": 0,
38 | "ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/bili.json"
39 | },
40 | {
41 | "key": "泥巴",
42 | "name": "泥巴",
43 | "type": 3,
44 | "api": "csp_NiNi",
45 | "searchable": 1,
46 | "changeable": 1
47 | },
48 | {
49 | "key": "獨播",
50 | "name": "獨播",
51 | "type": 3,
52 | "api": "csp_XPathMacFilter",
53 | "searchable": 1,
54 | "changeable": 1,
55 | "ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/duboku.json"
56 | },
57 | {
58 | "key": "櫻花",
59 | "name": "櫻花",
60 | "type": 3,
61 | "api": "csp_Ying",
62 | "searchable": 1,
63 | "changeable": 1
64 | },
65 | {
66 | "key": "巴士",
67 | "name": "巴士",
68 | "type": 3,
69 | "api": "csp_Dm84",
70 | "searchable": 1,
71 | "changeable": 1
72 | },
73 | {
74 | "key": "異界",
75 | "name": "異界",
76 | "type": 3,
77 | "api": "csp_Ysj",
78 | "searchable": 1,
79 | "changeable": 1
80 | },
81 | {
82 | "key": "土狗",
83 | "name": "土狗",
84 | "type": 3,
85 | "api": "csp_TuGou",
86 | "searchable": 1,
87 | "changeable": 0
88 | },
89 | {
90 | "key": "七夜",
91 | "name": "七夜",
92 | "type": 3,
93 | "api": "csp_Dovx",
94 | "searchable": 1,
95 | "changeable": 0
96 | },
97 | {
98 | "key": "雲搜",
99 | "name": "雲搜",
100 | "type": 3,
101 | "api": "csp_UpYun",
102 | "searchable": 1,
103 | "changeable": 0
104 | },
105 | {
106 | "key": "盤搜",
107 | "name": "盤搜",
108 | "type": 3,
109 | "api": "csp_PanSou",
110 | "searchable": 1,
111 | "changeable": 0
112 | },
113 | {
114 | "key": "盤搜索",
115 | "name": "盤搜索",
116 | "type": 3,
117 | "api": "csp_PanSearch",
118 | "searchable": 1,
119 | "changeable": 0
120 | },
121 | {
122 | "key": "找資源",
123 | "name": "找資源",
124 | "type": 3,
125 | "api": "csp_Zhaozy",
126 | "searchable": 1,
127 | "changeable": 0,
128 | "ext": "影視天下第一$$$test2$$$test2"
129 | },
130 | {
131 | "key": "push_agent",
132 | "name": "推送",
133 | "type": 3,
134 | "api": "csp_Push",
135 | "searchable": 1,
136 | "changeable": 0
137 | }
138 | ]
139 | }
140 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Zhaozy.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 |
5 | import com.github.catvod.bean.Result;
6 | import com.github.catvod.bean.Vod;
7 | import com.github.catvod.net.OkHttp;
8 | import com.github.catvod.utils.Utils;
9 |
10 | import org.jsoup.Jsoup;
11 | import org.jsoup.nodes.Document;
12 | import org.jsoup.nodes.Element;
13 |
14 | import java.net.URLEncoder;
15 | import java.util.ArrayList;
16 | import java.util.Arrays;
17 | import java.util.HashMap;
18 | import java.util.List;
19 | import java.util.Map;
20 | import java.util.regex.Matcher;
21 | import java.util.regex.Pattern;
22 |
23 | public class Zhaozy extends Ali {
24 |
25 | private final Pattern regexAli = Pattern.compile("(https://www.aliyundrive.com/s/[^\"]+)");
26 | private final Pattern regexVid = Pattern.compile("(\\S+)");
27 | private final String siteUrl = "https://zhaoziyuan.la/";
28 | private String username;
29 | private String password;
30 |
31 | private Map getHeader() {
32 | Map headers = new HashMap<>();
33 | headers.put("User-Agent", Utils.CHROME);
34 | headers.put("Referer", siteUrl);
35 | headers.put("Cookie", getCookie());
36 | return headers;
37 | }
38 |
39 | private String getCookie() {
40 | Map params = new HashMap<>();
41 | params.put("username", username);
42 | params.put("password", password);
43 | Map headers = new HashMap<>();
44 | headers.put("User-Agent", Utils.CHROME);
45 | headers.put("Referer", siteUrl + "login.html");
46 | headers.put("Origin", siteUrl);
47 | Map> resp = new HashMap<>();
48 | OkHttp.post(siteUrl + "logiu.html", params, headers, resp);
49 | StringBuilder sb = new StringBuilder();
50 | for (String item : resp.get("set-cookie")) sb.append(item.split(";")[0]).append(";");
51 | return sb.toString();
52 | }
53 |
54 | @Override
55 | public void init(Context context, String extend) {
56 | String[] split = extend.split("\\$\\$\\$");
57 | super.init(context, split[0]);
58 | username = split[1];
59 | password = split[2];
60 | }
61 |
62 | @Override
63 | public String detailContent(List ids) throws Exception {
64 | if (pattern.matcher(ids.get(0)).find()) return super.detailContent(ids);
65 | Matcher matcher = regexAli.matcher(OkHttp.string(siteUrl + ids.get(0), getHeader()));
66 | if (matcher.find()) return super.detailContent(Arrays.asList(matcher.group(1)));
67 | return "";
68 | }
69 |
70 | @Override
71 | public String searchContent(String key, boolean quick) throws Exception {
72 | String url = siteUrl + "so?filename=" + URLEncoder.encode(key);
73 | Document doc = Jsoup.parse(OkHttp.string(url, getHeader()));
74 | List list = new ArrayList<>();
75 | for (Element element : doc.select("div.li_con div.news_text")) {
76 | String href = element.select("div.news_text a").attr("href");
77 | Matcher matcher = regexVid.matcher(href);
78 | if (!matcher.find()) continue;
79 | String name = element.select("div.news_text a h3").text();
80 | if (!name.contains(key)) continue;
81 | String remark = element.select("div.news_text a p").text().split("\\|")[1].split(":")[1];
82 | Vod vod = new Vod();
83 | vod.setVodPic("https://inews.gtimg.com/newsapp_bt/0/13263837859/1000");
84 | vod.setVodId(matcher.group(1));
85 | vod.setVodRemarks(remark);
86 | vod.setVodName(name);
87 | list.add(vod);
88 | }
89 | return Result.string(list);
90 | }
91 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Doll.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.util.Base64;
4 |
5 | import com.github.catvod.bean.Class;
6 | import com.github.catvod.bean.Result;
7 | import com.github.catvod.bean.Vod;
8 | import com.github.catvod.crawler.Spider;
9 | import com.github.catvod.net.OkHttp;
10 | import com.github.catvod.utils.Utils;
11 |
12 | import org.jsoup.Jsoup;
13 | import org.jsoup.nodes.Document;
14 | import org.jsoup.nodes.Element;
15 |
16 | import java.net.URLDecoder;
17 | import java.util.ArrayList;
18 | import java.util.HashMap;
19 | import java.util.List;
20 |
21 | public class Doll extends Spider {
22 |
23 | private final String url = "https://hongkongdollvideo.com/";
24 |
25 | @Override
26 | public String homeContent(boolean filter) throws Exception {
27 | List classes = new ArrayList<>();
28 | List list = new ArrayList<>();
29 | Document doc = Jsoup.parse(OkHttp.string(url));
30 | for (Element a : doc.select("ul#side-menu").get(0).select("li > a")) {
31 | String typeName = a.text();
32 | String typeId = a.attr("href").replace(url, "");
33 | classes.add(new Class(typeId, typeName));
34 | }
35 | for (Element div : doc.select("div.video-detail")) {
36 | String id = div.select("h3.video-title > a").attr("href").replace(url, "");
37 | String name = div.select("h3.video-title > a").text();
38 | String pic = url + div.select("div.thumb > a > img").attr("data-src");
39 | String remark = div.select("div.date").text();
40 | list.add(new Vod(id, name, pic, remark));
41 | }
42 | return Result.string(classes, list);
43 | }
44 |
45 | @Override
46 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception {
47 | List list = new ArrayList<>();
48 | String target = pg.equals("1") ? url + tid : url + tid + "/" + pg + ".html";
49 | Document doc = Jsoup.parse(OkHttp.string(target));
50 | for (Element div : doc.select("div.video-detail")) {
51 | String id = div.select("h3.video-title > a").attr("href").replace(url, "");
52 | String name = div.select("h3.video-title > a").text();
53 | String pic = url + div.select("div.thumb > a > img").attr("data-src");
54 | String remark = div.select("div.date").text();
55 | list.add(new Vod(id, name, pic, remark));
56 | }
57 | return Result.string(list);
58 | }
59 |
60 | @Override
61 | public String detailContent(List ids) throws Exception {
62 | String html = OkHttp.string(url + ids.get(0));
63 | Document doc = Jsoup.parse(html);
64 | StringBuilder sb = new StringBuilder();
65 | String videoId = ids.get(0).split("/")[1].split("\\.")[0];
66 | String pic = doc.select("meta[property=og:image]").attr("content");
67 | String name = doc.select("meta[property=og:title]").attr("content");
68 | String voteTag = new String(Base64.decode(Utils.getVar(html, "voteTag").getBytes(), 0));
69 | for (int i = 0; i < voteTag.length(); i++) sb.append(Character.toChars(voteTag.charAt(i) ^ videoId.charAt(i % videoId.length())));
70 | String playUrl = URLDecoder.decode(new String(Base64.decode(sb.toString().getBytes(), 0)));
71 | Vod vod = new Vod();
72 | vod.setVodId(ids.get(0));
73 | vod.setVodPic(pic);
74 | vod.setVodName(name);
75 | vod.setVodPlayFrom("玩偶姐姐");
76 | vod.setVodPlayUrl("播放$" + playUrl);
77 | return Result.string(vod);
78 | }
79 |
80 | @Override
81 | public String playerContent(String flag, String id, List vipFlags) throws Exception {
82 | return Result.get().url(id).string();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/tools/src/main/java/com/fongmi/tools/Run.java:
--------------------------------------------------------------------------------
1 | package com.fongmi.tools;
2 |
3 | import com.fongmi.tools.bean.Channel;
4 | import com.fongmi.tools.bean.Data;
5 | import com.fongmi.tools.bean.Group;
6 | import com.google.gson.Gson;
7 |
8 | import java.io.File;
9 | import java.io.IOException;
10 | import java.io.PrintWriter;
11 | import java.nio.charset.StandardCharsets;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.Locale;
15 |
16 | public class Run {
17 |
18 | private final List groups;
19 | private final List data;
20 | private final Gson gson;
21 |
22 | public static void main(String[] args) throws IOException {
23 | new Run().start("http://home.jundie.top:81/Cat/tv/live.txt");
24 | }
25 |
26 | public Run() {
27 | groups = new ArrayList<>();
28 | data = Data.arrayFrom(Util.getFile(getClass(), "data.json"));
29 | gson = new Gson().newBuilder().disableHtmlEscaping().setPrettyPrinting().create();
30 | }
31 |
32 | private void start(String text) throws IOException {
33 | //parseTxt(Util.getFile(getClass(), "live.txt"));
34 | parse(Util.call(text));
35 | writeFile();
36 | }
37 |
38 | private void parse(String text) {
39 | for (String line : text.split("\n")) {
40 | String[] split = line.split(",");
41 | if (split.length < 2) continue;
42 | if (line.contains("#genre#")) groups.add(Group.create(split[0]));
43 | if (split[1].contains("://")) {
44 | Group group = groups.get(groups.size() - 1);
45 | String name = split[0];
46 | String url = split[1].trim();
47 | if (url.startsWith("http://txtest")) url = url.replace("http://txtest", "http://121.51.249.6/txtest");
48 | group.find(Channel.create().name(name).epg(name)).addUrls(url.split("#"));
49 | }
50 | }
51 | int number = 0;
52 | for (Group group : groups) {
53 | for (Channel channel : group.getChannel()) {
54 | channel.number(String.format(Locale.getDefault(), "%03d", ++number));
55 | channel.logo("https://ghproxy.com/https://raw.githubusercontent.com/FongMi/TV/release/app/src/main/res/drawable-xxhdpi/ic_img_empty.png");
56 | combine(channel);
57 | }
58 | }
59 | }
60 |
61 | private void parseTxt(String text) {
62 | for (String line : text.split("\n")) {
63 | String[] split = line.split(",");
64 | if (split.length < 2) continue;
65 | if (line.contains("#genre#")) groups.add(Group.create(split[0]));
66 | if (!line.contains("://")) continue;
67 | Group group = groups.get(groups.size() - 1);
68 | String number = split[0];
69 | String epg = split[1];
70 | String logo = split[2];
71 | String name = split[3];
72 | String url = split[4];
73 | group.find(Channel.create().number(number).epg(epg).logo(logo).name(name).ua(getUa(url))).addUrls(url.split("#"));
74 | }
75 | }
76 |
77 | private void combine(Channel channel) {
78 | for (Data item : data) {
79 | if (item.getName().contains(channel.getName())) {
80 | channel.logo(item.getLogo());
81 | channel.epg(item.getEpg());
82 | break;
83 | }
84 | }
85 | }
86 |
87 | private String getUa(String url) {
88 | if (url.contains("play-live.ifeng")) return "okhttp/3.15";
89 | return null;
90 | }
91 |
92 | private void writeFile() {
93 | try {
94 | File file = new File("json", "live.json");
95 | PrintWriter writer = new PrintWriter(file, String.valueOf(StandardCharsets.UTF_8));
96 | writer.println(gson.toJson(groups));
97 | writer.close();
98 | } catch (Exception e) {
99 | e.printStackTrace();
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/alist/Drive.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.alist;
2 |
3 | import android.net.Uri;
4 | import android.text.TextUtils;
5 |
6 | import com.github.catvod.bean.Class;
7 | import com.github.catvod.net.OkHttp;
8 | import com.github.catvod.utils.Image;
9 | import com.google.gson.Gson;
10 | import com.google.gson.annotations.SerializedName;
11 |
12 | import java.util.ArrayList;
13 | import java.util.HashMap;
14 | import java.util.List;
15 | import java.util.Map;
16 |
17 | public class Drive {
18 |
19 | @SerializedName("drives")
20 | private List drives;
21 | @SerializedName("vodPic")
22 | private String vodPic;
23 | @SerializedName("name")
24 | private String name;
25 | @SerializedName("server")
26 | private String server;
27 | @SerializedName("password")
28 | private String password;
29 | @SerializedName("version")
30 | private int version;
31 | @SerializedName("path")
32 | private String path;
33 |
34 | public static Drive objectFrom(String str) {
35 | return new Gson().fromJson(str, Drive.class);
36 | }
37 |
38 | public List getDrives() {
39 | return drives == null ? new ArrayList<>() : drives;
40 | }
41 |
42 | public Drive(String name) {
43 | this.name = name;
44 | }
45 |
46 | public String getVodPic() {
47 | return TextUtils.isEmpty(vodPic) ? Image.FOLDER : vodPic;
48 | }
49 |
50 | public String getName() {
51 | return TextUtils.isEmpty(name) ? "" : name;
52 | }
53 |
54 | public String getServer() {
55 | return TextUtils.isEmpty(server) ? "" : server;
56 | }
57 |
58 | public String getPassword() {
59 | return TextUtils.isEmpty(password) ? "" : password;
60 | }
61 |
62 | public int getVersion() {
63 | return version;
64 | }
65 |
66 | public void setVersion(int version) {
67 | this.version = version;
68 | }
69 |
70 | public String getPath() {
71 | return TextUtils.isEmpty(path) ? "" : path;
72 | }
73 |
74 | public void setPath(String path) {
75 | this.path = TextUtils.isEmpty(path) ? "" : path;
76 | }
77 |
78 | public boolean isNew() {
79 | return getVersion() == 3;
80 | }
81 |
82 | public Class toType() {
83 | return new Class(getName(), getName(), "1");
84 | }
85 |
86 | public String getHost() {
87 | return getServer().replace(getPath(), "");
88 | }
89 |
90 | public String settingsApi() {
91 | return getHost() + "/api/public/settings";
92 | }
93 |
94 | public String listApi() {
95 | return getHost() + (isNew() ? "/api/fs/list" : "/api/public/path");
96 | }
97 |
98 | public String getApi() {
99 | return getHost() + (isNew() ? "/api/fs/get" : "/api/public/path");
100 | }
101 |
102 | public String searchApi() {
103 | return getHost() + (isNew() ? "/api/fs/search" : "/api/public/search");
104 | }
105 |
106 | public Drive check() {
107 | if (path == null) setPath(Uri.parse(getServer()).getPath());
108 | if (version == 0) setVersion(OkHttp.string(settingsApi()).contains("v2.") ? 2 : 3);
109 | return this;
110 | }
111 |
112 | public String params(String keyword) {
113 | if (isNew()) {
114 | Map params = new HashMap<>();
115 | params.put("keywords", keyword);
116 | params.put("page", 1);
117 | params.put("parent", "/");
118 | params.put("per_page", 100);
119 | return new Gson().toJson(params);
120 | } else {
121 | Map params = new HashMap<>();
122 | params.put("keyword", keyword);
123 | params.put("path", "/");
124 | return new Gson().toJson(params);
125 | }
126 | }
127 |
128 | @Override
129 | public boolean equals(Object obj) {
130 | if (this == obj) return true;
131 | if (!(obj instanceof Drive)) return false;
132 | Drive it = (Drive) obj;
133 | return getName().equals(it.getName());
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/alist/Item.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean.alist;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.bean.Vod;
6 | import com.github.catvod.utils.Utils;
7 | import com.google.gson.Gson;
8 | import com.google.gson.annotations.SerializedName;
9 | import com.google.gson.reflect.TypeToken;
10 |
11 | import java.lang.reflect.Type;
12 | import java.text.SimpleDateFormat;
13 | import java.util.Date;
14 | import java.util.List;
15 | import java.util.Locale;
16 |
17 | public class Item {
18 |
19 | @SerializedName("name")
20 | private String name;
21 | @SerializedName(value = "path", alternate = "parent")
22 | private String path;
23 | @SerializedName("type")
24 | private int type;
25 | @SerializedName("size")
26 | private long size;
27 | @SerializedName(value = "thumb", alternate = "thumbnail")
28 | private String thumb;
29 | @SerializedName(value = "url", alternate = "raw_url")
30 | private String url;
31 | @SerializedName(value = "modified", alternate = "updated_at")
32 | private String modified;
33 |
34 | public static Item objectFrom(String str) {
35 | return new Gson().fromJson(str, Item.class);
36 | }
37 |
38 | public static List
- arrayFrom(String str) {
39 | Type listType = new TypeToken
>() {}.getType();
40 | return new Gson().fromJson(str, listType);
41 | }
42 |
43 | public String getName() {
44 | return TextUtils.isEmpty(name) ? "" : name;
45 | }
46 |
47 | public void setName(String name) {
48 | this.name = name;
49 | }
50 |
51 | public String getPath() {
52 | return TextUtils.isEmpty(path) ? "" : path;
53 | }
54 |
55 | public void setPath(String path) {
56 | this.path = path;
57 | }
58 |
59 | public int getType() {
60 | return type;
61 | }
62 |
63 | public void setType(int type) {
64 | this.type = type;
65 | }
66 |
67 | public long getSize() {
68 | return size;
69 | }
70 |
71 | public String getThumb() {
72 | return TextUtils.isEmpty(thumb) ? "" : thumb;
73 | }
74 |
75 | public String getUrl() {
76 | return TextUtils.isEmpty(url) ? "" : url.startsWith("//") ? "http:" + url : url;
77 | }
78 |
79 | public String getModified() {
80 | return modified;
81 | }
82 |
83 | public Date getDate() {
84 | try {
85 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());
86 | return format.parse(getModified());
87 | } catch (Exception e) {
88 | return new Date();
89 | }
90 | }
91 |
92 | public boolean isFolder() {
93 | return getType() == 1;
94 | }
95 |
96 | public boolean isMedia(boolean isNew) {
97 | if (getName().endsWith(".ts") || getName().endsWith(".mpg")) return true;
98 | if (isNew) return getType() == 2 || getType() == 3;
99 | return getType() == 3 || getType() == 4;
100 | }
101 |
102 | public boolean ignore(boolean isNew) {
103 | if (getName().endsWith(".ts") || getName().endsWith(".mpg")) return false;
104 | if (isNew) return getType() == 0 || getType() == 4;
105 | return getType() == 0 || getType() == 2 || getType() == 5;
106 | }
107 |
108 | public String getExt() {
109 | return Utils.getExt(getName());
110 | }
111 |
112 | public String getVodId(String id) {
113 | return id + getPath() + "/" + getName();
114 | }
115 |
116 | public String getPic(String pic) {
117 | return getThumb().isEmpty() && isFolder() ? pic : getThumb();
118 | }
119 |
120 | public String getRemark() {
121 | return Utils.getSize(getSize());
122 | }
123 |
124 | public Vod getVod(String id, String pic) {
125 | return new Vod(getVodId(id), getName(), getPic(pic), getRemark(), isFolder());
126 | }
127 |
128 | public Vod getVod(Drive drive, String pic) {
129 | return new Vod(getVodId(drive.getName()), getName(), getPic(pic), drive.getName(), isFolder());
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Local.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.content.Context;
4 | import android.os.Environment;
5 |
6 | import com.github.catvod.bean.Class;
7 | import com.github.catvod.bean.Result;
8 | import com.github.catvod.bean.Sub;
9 | import com.github.catvod.bean.Vod;
10 | import com.github.catvod.crawler.Spider;
11 | import com.github.catvod.utils.Image;
12 | import com.github.catvod.utils.Utils;
13 |
14 | import java.io.File;
15 | import java.text.SimpleDateFormat;
16 | import java.util.ArrayList;
17 | import java.util.Arrays;
18 | import java.util.Collections;
19 | import java.util.HashMap;
20 | import java.util.List;
21 | import java.util.Locale;
22 | import java.util.Objects;
23 |
24 | public class Local extends Spider {
25 |
26 | private SimpleDateFormat format;
27 |
28 | @Override
29 | public void init(Context context, String extend) {
30 | format = new SimpleDateFormat("yyyyy/MM/dd HH:mm:ss", Locale.getDefault());
31 | }
32 |
33 | @Override
34 | public String homeContent(boolean filter) throws Exception {
35 | List classes = new ArrayList<>();
36 | classes.add(new Class(Environment.getExternalStorageDirectory().getAbsolutePath(), "本地文件", "1"));
37 | File[] files = new File("/storage").listFiles();
38 | if (files == null) return Result.string(classes, new ArrayList<>());
39 | List exclude = Arrays.asList("emulated", "sdcard", "self");
40 | for (File file : files) {
41 | if (exclude.contains(file.getName())) continue;
42 | classes.add(new Class(file.getAbsolutePath(), file.getName(), "1"));
43 | }
44 | return Result.string(classes, new ArrayList<>());
45 | }
46 |
47 | @Override
48 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception {
49 | List items = new ArrayList<>();
50 | List media = new ArrayList<>();
51 | List folders = new ArrayList<>();
52 | File[] files = new File(tid).listFiles();
53 | if (files == null) return Result.string(items);
54 | Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName()));
55 | for (File file : files) {
56 | if (file.getName().startsWith(".")) continue;
57 | if (file.isDirectory()) folders.add(create(file));
58 | else if (Utils.MEDIA.contains(Utils.getExt(file.getName()))) media.add(create(file));
59 | }
60 | items.addAll(folders);
61 | items.addAll(media);
62 | return Result.string(items);
63 | }
64 |
65 | @Override
66 | public String detailContent(List ids) {
67 | File file = new File(ids.get(0));
68 | Vod vod = new Vod();
69 | vod.setTypeName("FongMi");
70 | vod.setVodId(file.getAbsolutePath());
71 | vod.setVodName(file.getName());
72 | vod.setVodPic(Image.VIDEO);
73 | vod.setVodPlayFrom("播放");
74 | vod.setVodPlayUrl(file.getName() + "$" + file.getAbsolutePath());
75 | return Result.string(vod);
76 | }
77 |
78 | @Override
79 | public String playerContent(String flag, String id, List vipFlags) throws Exception {
80 | return Result.get().url(id).subs(getSubs(id)).string();
81 | }
82 |
83 | private Vod create(File file) {
84 | Vod vod = new Vod();
85 | vod.setVodId(file.getAbsolutePath());
86 | vod.setVodName(file.getName());
87 | vod.setVodPic(Image.getIcon(file.isDirectory()));
88 | vod.setVodRemarks(format.format(file.lastModified()));
89 | vod.setVodTag(file.isDirectory() ? "folder" : "file");
90 | return vod;
91 | }
92 |
93 | private List getSubs(String path) {
94 | File file = new File(path);
95 | if (file.getParentFile() == null) return Collections.emptyList();
96 | List subs = new ArrayList<>();
97 | for (File f : Objects.requireNonNull(file.getParentFile().listFiles())) {
98 | String ext = Utils.getExt(f.getName());
99 | if (Utils.isSub(ext)) subs.add(Sub.create().name(Utils.removeExt(f.getName())).ext(ext).url("file://" + f.getAbsolutePath()));
100 | }
101 | return subs;
102 | }
103 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/net/Cronet.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.net;
2 |
3 | import com.github.catvod.crawler.Spider;
4 | import com.github.catvod.spider.Init;
5 | import com.google.net.cronet.okhttptransport.CronetInterceptor;
6 |
7 | import org.chromium.net.CronetEngine;
8 |
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | import okhttp3.Dns;
13 | import okhttp3.OkHttpClient;
14 |
15 | public class Cronet {
16 |
17 | public static final String POST = "POST";
18 | public static final String GET = "GET";
19 |
20 | private final OkHttpClient noRedirect;
21 | private final OkHttpClient client;
22 |
23 | private static class Loader {
24 | static volatile Cronet INSTANCE = new Cronet();
25 | }
26 |
27 | public static Cronet get() {
28 | return Loader.INSTANCE;
29 | }
30 |
31 | public Cronet() {
32 | client = getBuilder().build();
33 | noRedirect = client.newBuilder().followRedirects(false).followSslRedirects(false).build();
34 | }
35 |
36 | private OkHttpClient.Builder getBuilder() {
37 | OkHttpClient.Builder builder = OkHttp.getBuilder();
38 | addInterceptor(builder);
39 | return builder;
40 | }
41 |
42 | private void addInterceptor(OkHttpClient.Builder builder) {
43 | try {
44 | builder.addInterceptor(CronetInterceptor.newBuilder(new CronetEngine.Builder(Init.context()).build()).build());
45 | } catch (Exception e) {
46 | e.printStackTrace();
47 | }
48 | }
49 |
50 | private static OkHttpClient client() {
51 | return get().client;
52 | }
53 |
54 | private static OkHttpClient noRedirect() {
55 | return get().noRedirect;
56 | }
57 |
58 | public static Dns safeDns() {
59 | try {
60 | return (Dns) Spider.class.getMethod("safeDns").invoke(null);
61 | } catch (Exception e) {
62 | return Dns.SYSTEM;
63 | }
64 | }
65 |
66 | public static void stringNoRedirect(String url, Map header, Map> respHeader) {
67 | string(noRedirect(), GET, url, null, null, header, respHeader);
68 | }
69 |
70 | public static String string(OkHttpClient client, String method, String url, String tag, Map params, Map header, Map> respHeader) {
71 | return new OkRequest(method, url, params, header, respHeader).tag(tag).execute(client).getBody();
72 | }
73 |
74 | public static String string(String url) {
75 | return string(url, null);
76 | }
77 |
78 | public static String string(String url, Map header) {
79 | return string(url, header, null);
80 | }
81 |
82 | public static String string(String url, Map header, Map> respHeader) {
83 | return string(url, null, header, respHeader);
84 | }
85 |
86 | public static String string(String url, Map params, Map header, Map> respHeader) {
87 | return string(url, null, params, header, respHeader);
88 | }
89 |
90 | public static String string(String url, String tag, Map header) {
91 | return string(url, tag, null, header, null);
92 | }
93 |
94 | public static String string(String url, String tag, Map params, Map header, Map> respHeader) {
95 | return string(client(), GET, url, tag, params, header, respHeader);
96 | }
97 |
98 | public static String post(String url, Map params) {
99 | return post(url, params, null);
100 | }
101 |
102 | public static String post(String url, Map params, Map header) {
103 | return post(url, params, header, null);
104 | }
105 |
106 | public static String post(String url, Map params, Map header, Map> respHeader) {
107 | return string(client(), POST, url, null, params, header, respHeader);
108 | }
109 |
110 | public static OkResult postJson(String url, String json) {
111 | return postJson(url, json, null);
112 | }
113 |
114 | public static OkResult postJson(String url, String json, Map header) {
115 | return new OkRequest(POST, url, json, header).execute(client());
116 | }
117 |
118 | public static String getRedirectLocation(Map> headers) {
119 | if (headers == null) return null;
120 | if (headers.containsKey("location")) return headers.get("location").get(0);
121 | if (headers.containsKey("Location")) return headers.get("Location").get(0);
122 | return null;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Jable.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import com.github.catvod.bean.Class;
4 | import com.github.catvod.bean.Result;
5 | import com.github.catvod.bean.Vod;
6 | import com.github.catvod.crawler.Spider;
7 | import com.github.catvod.net.OkHttp;
8 | import com.github.catvod.utils.Utils;
9 |
10 | import org.jsoup.Jsoup;
11 | import org.jsoup.nodes.Document;
12 | import org.jsoup.nodes.Element;
13 |
14 | import java.net.URLEncoder;
15 | import java.util.ArrayList;
16 | import java.util.HashMap;
17 | import java.util.List;
18 | import java.util.Locale;
19 |
20 | public class Jable extends Spider {
21 |
22 | private static final String siteUrl = "https://jable.tv";
23 | private static final String cateUrl = siteUrl + "/categories/";
24 | private static final String detailUrl = siteUrl + "/videos/";
25 | private static final String searchUrl = siteUrl + "/search/";
26 |
27 | private HashMap getHeaders() {
28 | HashMap headers = new HashMap<>();
29 | headers.put("User-Agent", Utils.CHROME);
30 | return headers;
31 | }
32 |
33 | @Override
34 | public String homeContent(boolean filter) throws Exception {
35 | List list = new ArrayList<>();
36 | List classes = new ArrayList<>();
37 | Document doc = Jsoup.parse(OkHttp.string(cateUrl, getHeaders()));
38 | for (Element element : doc.select("div.img-box > a")) {
39 | String typeId = element.attr("href").split("/")[4];
40 | String typeName = element.select("div.absolute-center > h4").text();
41 | classes.add(new Class(typeId, typeName));
42 | }
43 | doc = Jsoup.parse(OkHttp.string(siteUrl, getHeaders()));
44 | for (Element element : doc.select("div.video-img-box")) {
45 | String pic = element.select("img").attr("data-src");
46 | String url = element.select("a").attr("href");
47 | String name = element.select("div.detail > h6").text();
48 | if (pic.endsWith(".gif") || name.isEmpty()) continue;
49 | String id = url.split("/")[4];
50 | list.add(new Vod(id, name, pic));
51 | }
52 | return Result.string(classes, list);
53 | }
54 |
55 | @Override
56 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception {
57 | List list = new ArrayList<>();
58 | String target = cateUrl + tid + "/?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=post_date&from=" + String.format(Locale.getDefault(), "%02d", Integer.parseInt(pg)) + "&_=" + System.currentTimeMillis();
59 | Document doc = Jsoup.parse(OkHttp.string(target, getHeaders()));
60 | for (Element element : doc.select("div.video-img-box")) {
61 | String pic = element.select("img").attr("data-src");
62 | String url = element.select("a").attr("href");
63 | String name = element.select("div.detail > h6").text();
64 | String id = url.split("/")[4];
65 | list.add(new Vod(id, name, pic));
66 | }
67 | return Result.string(list);
68 | }
69 |
70 | @Override
71 | public String detailContent(List ids) throws Exception {
72 | Document doc = Jsoup.parse(OkHttp.string(detailUrl.concat(ids.get(0)).concat("/"), getHeaders()));
73 | String name = doc.select("meta[property=og:title]").attr("content");
74 | String pic = doc.select("meta[property=og:image]").attr("content");
75 | String year = doc.select("span.inactive-color").get(0).text();
76 | Vod vod = new Vod();
77 | vod.setVodId(ids.get(0));
78 | vod.setVodPic(pic);
79 | vod.setVodYear(year.replace("上市於 ", ""));
80 | vod.setVodName(name);
81 | vod.setVodPlayFrom("Jable");
82 | vod.setVodPlayUrl("播放$" + Utils.getVar(doc.html(), "hlsUrl"));
83 | return Result.string(vod);
84 | }
85 |
86 | @Override
87 | public String searchContent(String key, boolean quick) throws Exception {
88 | List list = new ArrayList<>();
89 | Document doc = Jsoup.parse(OkHttp.string(searchUrl.concat(URLEncoder.encode(key)).concat("/"), getHeaders()));
90 | for (Element element : doc.select("div.video-img-box")) {
91 | String pic = element.select("img").attr("data-src");
92 | String url = element.select("a").attr("href");
93 | String name = element.select("div.detail > h6").text();
94 | String id = url.split("/")[4];
95 | list.add(new Vod(id, name, pic));
96 | }
97 | return Result.string(list);
98 | }
99 |
100 | @Override
101 | public String playerContent(String flag, String id, List vipFlags) throws Exception {
102 | return Result.get().url(id).header(getHeaders()).string();
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Eighteen.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.os.SystemClock;
4 | import android.webkit.WebView;
5 | import android.webkit.WebViewClient;
6 |
7 | import com.github.catvod.bean.Class;
8 | import com.github.catvod.bean.Result;
9 | import com.github.catvod.bean.Vod;
10 | import com.github.catvod.crawler.Spider;
11 | import com.github.catvod.net.OkHttp;
12 | import com.github.catvod.utils.Utils;
13 |
14 | import org.jsoup.Jsoup;
15 | import org.jsoup.nodes.Document;
16 | import org.jsoup.nodes.Element;
17 |
18 | import java.util.ArrayList;
19 | import java.util.HashMap;
20 | import java.util.List;
21 |
22 | public class Eighteen extends Spider {
23 |
24 | private final String url = "https://maa1812.com/zh/";
25 |
26 | @Override
27 | public String homeContent(boolean filter) throws Exception {
28 | List classes = new ArrayList<>();
29 | List list = new ArrayList<>();
30 | Document doc = Jsoup.parse(OkHttp.string(url));
31 | for (Element a : doc.select("ul.animenu__nav > li > a")) {
32 | String typeName = a.text();
33 | String typeId = a.attr("href").replace(url, "");
34 | if (!typeId.contains("random/all/")) continue;
35 | if (typeName.contains("18H")) break;
36 | classes.add(new Class(typeId, typeName));
37 | }
38 | for (Element div : doc.select("div.post")) {
39 | String id = div.select("a").attr("href").replace(url, "");
40 | String name = div.select("h3").text();
41 | String pic = div.select("a > img").attr("src");
42 | String remark = div.select("div.meta").text();
43 | list.add(new Vod(id, name, pic, remark));
44 | }
45 | return Result.string(classes, list);
46 | }
47 |
48 | @Override
49 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception {
50 | List list = new ArrayList<>();
51 | tid = tid.replace("random", "list");
52 | tid = tid.replace("index", pg);
53 | Document doc = Jsoup.parse(OkHttp.string(url + tid));
54 | for (Element div : doc.select("div.post")) {
55 | String id = div.select("a").attr("href").replace(url, "");
56 | String name = div.select("h3").text();
57 | String pic = div.select("a > img").attr("src");
58 | String remark = div.select("div.meta").text();
59 | list.add(new Vod(id, name, pic, remark));
60 | }
61 | return Result.string(list);
62 | }
63 |
64 | @Override
65 | public String detailContent(List ids) throws Exception {
66 | Document doc = Jsoup.parse(OkHttp.string(url + ids.get(0)));
67 | Element wrap = doc.select("div.video-wrap").get(0);
68 | String name = wrap.select("div.archive-title > h1").text();
69 | String pic = wrap.select("div.player-wrap > img").attr("src");
70 | Vod vod = new Vod();
71 | vod.setVodId(ids.get(0));
72 | vod.setVodPic(pic);
73 | vod.setVodName(name);
74 | vod.setVodPlayFrom("18AV");
75 | vod.setVodPlayUrl("播放$" + ids.get(0));
76 | return Result.string(vod);
77 | }
78 |
79 | @Override
80 | public String searchContent(String key, boolean quick) throws Exception {
81 | HashMap params = new HashMap<>();
82 | params.put("search_keyword", key);
83 | params.put("search_type", "fc");
84 | params.put("op", "search");
85 | String res = OkHttp.post(url + "searchform_search/all/index.html", params);
86 | List list = new ArrayList<>();
87 | for (Element div : Jsoup.parse(res).select("div.post")) {
88 | String id = div.select("a").attr("href").replace(url, "");
89 | String name = div.select("h3").text();
90 | String pic = div.select("a > img").attr("src");
91 | String remark = div.select("div.meta").text();
92 | list.add(new Vod(id, name, pic, remark));
93 | }
94 | return Result.string(list);
95 | }
96 |
97 | @Override
98 | public String playerContent(String flag, String id, List vipFlags) throws Exception {
99 | HashMap result = new HashMap<>();
100 | Utils.loadWebView(url + id, getClient(result));
101 | while (result.isEmpty()) SystemClock.sleep(10);
102 | return Result.get().url(result.get("url")).string();
103 | }
104 |
105 | private WebViewClient getClient(HashMap result) {
106 | return new WebViewClient() {
107 | @Override
108 | public void onLoadResource(WebView view, String url) {
109 | if (url.endsWith(".m3u8")) {
110 | result.put("url", url);
111 | view.destroy();
112 | }
113 | }
114 | };
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/bean/Result.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.bean;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.annotations.SerializedName;
5 | import com.google.gson.reflect.TypeToken;
6 |
7 | import org.json.JSONObject;
8 |
9 | import java.lang.reflect.Type;
10 | import java.util.Arrays;
11 | import java.util.Collections;
12 | import java.util.LinkedHashMap;
13 | import java.util.List;
14 | import java.util.Map;
15 |
16 | public class Result {
17 |
18 | @SerializedName("class")
19 | private List classes;
20 | @SerializedName("list")
21 | private List list;
22 | @SerializedName("filters")
23 | private LinkedHashMap> filters;
24 | @SerializedName("header")
25 | private String header;
26 | @SerializedName("url")
27 | private String url;
28 | @SerializedName("subs")
29 | private List subs;
30 | @SerializedName("parse")
31 | private int parse;
32 | @SerializedName("jx")
33 | private int jx;
34 | @SerializedName("page")
35 | private int page;
36 | @SerializedName("pagecount")
37 | private int pagecount;
38 | @SerializedName("limit")
39 | private int limit;
40 | @SerializedName("total")
41 | private int total;
42 |
43 | public static Result objectFrom(String str) {
44 | return new Gson().fromJson(str, Result.class);
45 | }
46 |
47 | public static String string(List classes, List list, LinkedHashMap> filters) {
48 | return Result.get().classes(classes).vod(list).filters(filters).string();
49 | }
50 |
51 | public static String string(List classes, List list, JSONObject filters) {
52 | return Result.get().classes(classes).vod(list).filters(filters).string();
53 | }
54 |
55 | public static String string(List classes, LinkedHashMap> filters) {
56 | return Result.get().classes(classes).filters(filters).string();
57 | }
58 |
59 | public static String string(List classes, JSONObject filters) {
60 | return Result.get().classes(classes).filters(filters).string();
61 | }
62 |
63 | public static String string(List classes, List list) {
64 | return Result.get().classes(classes).vod(list).string();
65 | }
66 |
67 | public static String string(List list) {
68 | return Result.get().vod(list).string();
69 | }
70 |
71 | public static String string(Vod item) {
72 | return Result.get().vod(item).string();
73 | }
74 |
75 | public static Result get() {
76 | return new Result();
77 | }
78 |
79 | public Result classes(List classes) {
80 | this.classes = classes;
81 | return this;
82 | }
83 |
84 | public Result vod(List list) {
85 | this.list = list;
86 | return this;
87 | }
88 |
89 | public Result vod(Vod item) {
90 | this.list = Arrays.asList(item);
91 | return this;
92 | }
93 |
94 | public Result filters(LinkedHashMap> filters) {
95 | this.filters = filters;
96 | return this;
97 | }
98 |
99 | public Result filters(JSONObject object) {
100 | if (object == null) return this;
101 | Type listType = new TypeToken>>() {}.getType();
102 | this.filters = new Gson().fromJson(object.toString(), listType);
103 | return this;
104 | }
105 |
106 | public Result header(Map header) {
107 | if (header.isEmpty()) return this;
108 | this.header = new Gson().toJson(header);
109 | return this;
110 | }
111 |
112 | public Result parse() {
113 | this.parse = 1;
114 | return this;
115 | }
116 |
117 | public Result parse(int parse) {
118 | this.parse = parse;
119 | return this;
120 | }
121 |
122 | public Result jx() {
123 | this.jx = 1;
124 | return this;
125 | }
126 |
127 | public Result url(String url) {
128 | this.url = url;
129 | return this;
130 | }
131 |
132 | public Result subs(List subs) {
133 | this.subs = subs;
134 | return this;
135 | }
136 |
137 | public Result page() {
138 | return page(1, 1, 0, 1);
139 | }
140 |
141 | public Result page(int page, int count, int limit, int total) {
142 | this.page = page > 0 ? page : Integer.MAX_VALUE;
143 | this.limit = limit > 0 ? limit : Integer.MAX_VALUE;
144 | this.total = total > 0 ? total : Integer.MAX_VALUE;
145 | this.pagecount = count > 0 ? count : Integer.MAX_VALUE;
146 | return this;
147 | }
148 |
149 | public List getList() {
150 | return list == null ? Collections.emptyList() : list;
151 | }
152 |
153 | public String string() {
154 | return toString();
155 | }
156 |
157 | @Override
158 | public String toString() {
159 | return new Gson().toJson(this);
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Miss.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.bean.Class;
6 | import com.github.catvod.bean.Filter;
7 | import com.github.catvod.bean.Result;
8 | import com.github.catvod.bean.Vod;
9 | import com.github.catvod.crawler.Spider;
10 | import com.github.catvod.net.OkHttp;
11 |
12 | import org.jsoup.Jsoup;
13 | import org.jsoup.nodes.Document;
14 | import org.jsoup.nodes.Element;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Arrays;
18 | import java.util.HashMap;
19 | import java.util.LinkedHashMap;
20 | import java.util.List;
21 |
22 | public class Miss extends Spider {
23 |
24 | private final String url = "https://missav.com/";
25 |
26 | @Override
27 | public String homeContent(boolean filter) throws Exception {
28 | List list = new ArrayList<>();
29 | List classes = new ArrayList<>();
30 | LinkedHashMap> filters = new LinkedHashMap<>();
31 | List typeIds = Arrays.asList("chinese-subtitle", "new", "release", "uncensored-leak", "siro", "luxu", "gana", "maan", "scute", "ara", "uncensored-leak", "fc2", "heyzo", "tokyohot", "1pondo", "caribbeancom", "caribbeancompr", "10musume", "pacopacomama", "gachinco", "xxxav", "marriedslash", "naughty4610", "naughty0930", "madou", "twav");
32 | Document doc = Jsoup.parse(OkHttp.string(url));
33 | for (Element a : doc.select("nav").select("a")) {
34 | String typeName = a.text();
35 | String typeId = a.attr("href").replace(url, "");
36 | if (!typeIds.contains(typeId)) continue;
37 | classes.add(new Class(typeId, typeName));
38 | filters.put(typeId, Arrays.asList(new Filter("filters", "過濾", Arrays.asList(new Filter.Value("全部", ""), new Filter.Value("單人作品", "individual"), new Filter.Value("中文字幕", "chinese-subtitle")))));
39 | }
40 | for (Element div : doc.select("div.thumbnail")) {
41 | String id = div.select("a.text-secondary").attr("href").replace(url, "");
42 | String name = div.select("a.text-secondary").text();
43 | String pic = div.select("img").attr("data-src");
44 | if (pic.isEmpty()) pic = div.select("img").attr("src");
45 | String remark = div.select("span").text();
46 | list.add(new Vod(id, name, pic, remark));
47 | }
48 | return Result.string(classes, list, filters);
49 | }
50 |
51 | @Override
52 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception {
53 | List list = new ArrayList<>();
54 | String target = url + tid;
55 | String filters = extend.get("filters");
56 | if (TextUtils.isEmpty(filters)) target += "?page=" + pg;
57 | else target += "?filters=" + extend.get("filters") + "&page=" + pg;
58 | Document doc = Jsoup.parse(OkHttp.string(target));
59 | for (Element div : doc.select("div.thumbnail")) {
60 | String id = div.select("a.text-secondary").attr("href").replace(url, "");
61 | String name = div.select("a.text-secondary").text();
62 | String pic = div.select("img").attr("data-src");
63 | if (pic.isEmpty()) pic = div.select("img").attr("src");
64 | if (TextUtils.isEmpty(name)) continue;
65 | String remark = div.select("span").text();
66 | list.add(new Vod(id, name, pic, remark));
67 | }
68 | return Result.string(list);
69 | }
70 |
71 | @Override
72 | public String detailContent(List ids) throws Exception {
73 | Document doc = Jsoup.parse(OkHttp.string(url + ids.get(0)));
74 | String name = doc.select("meta[property=og:title]").attr("content");
75 | String pic = doc.select("meta[property=og:image]").attr("content");
76 | Vod vod = new Vod();
77 | vod.setVodId(ids.get(0));
78 | vod.setVodPic(pic);
79 | vod.setVodName(name);
80 | vod.setVodPlayFrom("MissAV");
81 | vod.setVodPlayUrl("播放$" + ids.get(0));
82 | return Result.string(vod);
83 | }
84 |
85 | @Override
86 | public String searchContent(String key, boolean quick) throws Exception {
87 | List list = new ArrayList<>();
88 | Document doc = Jsoup.parse(OkHttp.string(url + "search/" + key));
89 | for (Element div : doc.select("div.thumbnail")) {
90 | String id = div.select("a.text-secondary").attr("href").replace(url, "");
91 | String name = div.select("a.text-secondary").text();
92 | String pic = div.select("img").attr("data-src");
93 | if (pic.isEmpty()) pic = div.select("img").attr("src");
94 | String remark = div.select("span").text();
95 | list.add(new Vod(id, name, pic, remark));
96 | }
97 | return Result.string(list);
98 | }
99 |
100 | @Override
101 | public String playerContent(String flag, String id, List vipFlags) throws Exception {
102 | return Result.get().parse().url(url + id).string();
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/net/OkHttp.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.net;
2 |
3 | import com.github.catvod.crawler.Spider;
4 |
5 | import java.io.IOException;
6 | import java.util.List;
7 | import java.util.Map;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | import okhttp3.Call;
11 | import okhttp3.Dns;
12 | import okhttp3.Headers;
13 | import okhttp3.OkHttpClient;
14 | import okhttp3.Request;
15 | import okhttp3.Response;
16 |
17 | public class OkHttp {
18 |
19 | public static final String POST = "POST";
20 | public static final String GET = "GET";
21 |
22 | private final OkHttpClient noRedirect;
23 | private final OkHttpClient client;
24 |
25 | private static class Loader {
26 | static volatile OkHttp INSTANCE = new OkHttp();
27 | }
28 |
29 | public static OkHttp get() {
30 | return Loader.INSTANCE;
31 | }
32 |
33 | public OkHttp() {
34 | client = getBuilder().build();
35 | noRedirect = client.newBuilder().followRedirects(false).followSslRedirects(false).build();
36 | }
37 |
38 | public static OkHttpClient.Builder getBuilder() {
39 | 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);
40 | }
41 |
42 | public static OkHttpClient client() {
43 | return get().client;
44 | }
45 |
46 | private static OkHttpClient noRedirect() {
47 | return get().noRedirect;
48 | }
49 |
50 | public static Dns safeDns() {
51 | try {
52 | return (Dns) Spider.class.getMethod("safeDns").invoke(null);
53 | } catch (Exception e) {
54 | return Dns.SYSTEM;
55 | }
56 | }
57 |
58 | public static Response newCall(String url, Map header) throws IOException {
59 | return client().newCall(new Request.Builder().url(url).headers(Headers.of(header)).build()).execute();
60 | }
61 |
62 | public static void stringNoRedirect(String url, Map header, Map> respHeader) {
63 | string(noRedirect(), GET, url, null, null, header, respHeader);
64 | }
65 |
66 | public static String string(OkHttpClient client, String method, String url, String tag, Map params, Map header, Map> respHeader) {
67 | return new OkRequest(method, url, params, header, respHeader).tag(tag).execute(client).getBody();
68 | }
69 |
70 | public static String string(String url) {
71 | return string(url, null);
72 | }
73 |
74 | public static String string(String url, Map header) {
75 | return string(url, header, null);
76 | }
77 |
78 | public static String string(String url, Map header, Map> respHeader) {
79 | return string(url, null, header, respHeader);
80 | }
81 |
82 | public static String string(String url, Map params, Map header, Map> respHeader) {
83 | return string(url, null, params, header, respHeader);
84 | }
85 |
86 | public static String string(String url, String tag, Map header) {
87 | return string(url, tag, null, header, null);
88 | }
89 |
90 | public static String string(String url, String tag, Map params, Map header, Map> respHeader) {
91 | return string(client(), GET, url, tag, params, header, respHeader);
92 | }
93 |
94 | public static String post(String url, Map params) {
95 | return post(url, params, null);
96 | }
97 |
98 | public static String post(String url, Map params, Map header) {
99 | return post(url, params, header, null);
100 | }
101 |
102 | public static String post(String url, Map params, Map header, Map> respHeader) {
103 | return string(client(), POST, url, null, params, header, respHeader);
104 | }
105 |
106 | public static OkResult postJson(String url, String json) {
107 | return postJson(url, json, null);
108 | }
109 |
110 | public static OkResult postJson(String url, String json, Map header) {
111 | return new OkRequest(POST, url, json, header).execute(client());
112 | }
113 |
114 | public static void cancel(Object tag) {
115 | for (Call call : client().dispatcher().queuedCalls()) {
116 | if (tag.equals(call.request().tag())) {
117 | call.cancel();
118 | }
119 | }
120 | for (Call call : client().dispatcher().runningCalls()) {
121 | if (tag.equals(call.request().tag())) {
122 | call.cancel();
123 | }
124 | }
125 | }
126 |
127 | public static String getRedirectLocation(Map> headers) {
128 | if (headers == null) return null;
129 | if (headers.containsKey("location")) return headers.get("location").get(0);
130 | if (headers.containsKey("Location")) return headers.get("Location").get(0);
131 | return null;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/net/SSLSocketFactoryCompat.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.net;
2 |
3 | import java.io.IOException;
4 | import java.net.InetAddress;
5 | import java.net.Socket;
6 | import java.security.GeneralSecurityException;
7 | import java.security.cert.X509Certificate;
8 | import java.util.Arrays;
9 | import java.util.HashSet;
10 | import java.util.LinkedList;
11 | import java.util.List;
12 |
13 | import javax.net.ssl.HostnameVerifier;
14 | import javax.net.ssl.HttpsURLConnection;
15 | import javax.net.ssl.SSLContext;
16 | import javax.net.ssl.SSLSocket;
17 | import javax.net.ssl.SSLSocketFactory;
18 | import javax.net.ssl.X509TrustManager;
19 |
20 | public class SSLSocketFactoryCompat extends SSLSocketFactory {
21 |
22 | public static final HostnameVerifier hostnameVerifier = (hostname, session) -> true;
23 |
24 | public static final X509TrustManager trustAllCert = new X509TrustManager() {
25 |
26 | @Override
27 | public void checkClientTrusted(X509Certificate[] chain, String authType) {
28 | }
29 |
30 | @Override
31 | public void checkServerTrusted(X509Certificate[] chain, String authType) {
32 | }
33 |
34 | @Override
35 | public X509Certificate[] getAcceptedIssuers() {
36 | return new X509Certificate[]{};
37 | }
38 | };
39 |
40 | static String[] protocols = null;
41 | static String[] cipherSuites = null;
42 |
43 | static {
44 | try {
45 | SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
46 | if (socket != null) {
47 | List protocols = new LinkedList<>();
48 | for (String protocol : socket.getSupportedProtocols()) if (!protocol.toUpperCase().contains("SSL")) protocols.add(protocol);
49 | SSLSocketFactoryCompat.protocols = protocols.toArray(new String[protocols.size()]);
50 | List allowedCiphers = Arrays.asList("TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
51 | List availableCiphers = Arrays.asList(socket.getSupportedCipherSuites());
52 | HashSet preferredCiphers = new HashSet<>(allowedCiphers);
53 | preferredCiphers.retainAll(availableCiphers);
54 | preferredCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites())));
55 | SSLSocketFactoryCompat.cipherSuites = preferredCiphers.toArray(new String[preferredCiphers.size()]);
56 | }
57 | } catch (IOException e) {
58 | throw new RuntimeException(e);
59 | }
60 | }
61 |
62 | private final SSLSocketFactory defaultFactory;
63 |
64 | public SSLSocketFactoryCompat() {
65 | try {
66 | SSLContext sslContext = SSLContext.getInstance("TLS");
67 | sslContext.init(null, new X509TrustManager[]{SSLSocketFactoryCompat.trustAllCert}, null);
68 | defaultFactory = sslContext.getSocketFactory();
69 | HttpsURLConnection.setDefaultSSLSocketFactory(defaultFactory);
70 | } catch (GeneralSecurityException e) {
71 | throw new AssertionError();
72 | }
73 | }
74 |
75 | private void upgradeTLS(SSLSocket ssl) {
76 | if (protocols != null) {
77 | ssl.setEnabledProtocols(protocols);
78 | }
79 | if (cipherSuites != null) {
80 | ssl.setEnabledCipherSuites(cipherSuites);
81 | }
82 | }
83 |
84 | @Override
85 | public String[] getDefaultCipherSuites() {
86 | return cipherSuites;
87 | }
88 |
89 | @Override
90 | public String[] getSupportedCipherSuites() {
91 | return cipherSuites;
92 | }
93 |
94 | @Override
95 | public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
96 | Socket ssl = defaultFactory.createSocket(s, host, port, autoClose);
97 | if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
98 | return ssl;
99 | }
100 |
101 | @Override
102 | public Socket createSocket(String host, int port) throws IOException {
103 | Socket ssl = defaultFactory.createSocket(host, port);
104 | if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
105 | return ssl;
106 | }
107 |
108 | @Override
109 | public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
110 | Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort);
111 | if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
112 | return ssl;
113 | }
114 |
115 | @Override
116 | public Socket createSocket(InetAddress host, int port) throws IOException {
117 | Socket ssl = defaultFactory.createSocket(host, port);
118 | if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
119 | return ssl;
120 | }
121 |
122 | @Override
123 | public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
124 | Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort);
125 | if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
126 | return ssl;
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Hanime.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import com.github.catvod.bean.Class;
4 | import com.github.catvod.bean.Filter;
5 | import com.github.catvod.bean.Result;
6 | import com.github.catvod.bean.Vod;
7 | import com.github.catvod.crawler.Spider;
8 | import com.github.catvod.net.OkHttp;
9 | import com.github.catvod.utils.Utils;
10 |
11 | import org.jsoup.Jsoup;
12 | import org.jsoup.nodes.Document;
13 | import org.jsoup.nodes.Element;
14 |
15 | import java.util.ArrayList;
16 | import java.util.HashMap;
17 | import java.util.LinkedHashMap;
18 | import java.util.List;
19 |
20 | public class Hanime extends Spider {
21 |
22 | private static final String siteUrl = "https://hanime1.me";
23 |
24 | private HashMap getHeaders() {
25 | HashMap headers = new HashMap<>();
26 | headers.put("User-Agent", Utils.CHROME);
27 | return headers;
28 | }
29 |
30 | private Filter getFilter(String name, String key, List texts) {
31 | List values = new ArrayList<>();
32 | if (!key.equals("by")) values.add(new Filter.Value("全部", ""));
33 | for (String text : texts) {
34 | if (text.isEmpty()) continue;
35 | values.add(new Filter.Value(text));
36 | }
37 | return new Filter(key, name, values);
38 | }
39 |
40 | @Override
41 | public String homeContent(boolean filter) throws Exception {
42 | List list = new ArrayList<>();
43 | List classes = new ArrayList<>();
44 | LinkedHashMap> filters = new LinkedHashMap<>();
45 | Document doc1 = Jsoup.parse(OkHttp.string(siteUrl.concat("/search?genre=裏番"), getHeaders()));
46 | List sorts = doc1.select("div.hentai-sort-options-wrapper").eachText();
47 | List years = doc1.getElementById("year").select("option").eachAttr("value");
48 | Document doc2 = Jsoup.parse(OkHttp.string(siteUrl, getHeaders()));
49 | for (Element element : doc2.select("a.nav-item")) {
50 | String text = element.text();
51 | if (text.equals("新番預告") || text.equals("H漫畫")) continue;
52 | classes.add(new Class(text));
53 | List array = new ArrayList<>();
54 | array.add(getFilter("排序", "by", sorts));
55 | array.add(getFilter("年份", "year", years));
56 | filters.put(text, array);
57 | }
58 | for (Element element : doc2.select("a")) {
59 | if (element.attr("href").contains("watch")) {
60 | String pic = element.select("div > img").attr("src");
61 | String url = element.attr("href");
62 | String name = element.select("div > div").text();
63 | String id = url.split("=")[1];
64 | if (name.contains("smart_display") || name.isEmpty()) continue;
65 | list.add(new Vod(id, name, pic));
66 | }
67 | }
68 | return Result.string(classes, list, filters);
69 | }
70 |
71 | @Override
72 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception {
73 | List list = new ArrayList<>();
74 | if (extend.get("by") == null) extend.put("by", "最新上市");
75 | if (extend.get("year") == null) extend.put("year", "");
76 | String target = siteUrl.concat("/search?genre=").concat(tid).concat("&page=").concat(pg).concat("&sort=").concat(extend.get("by")).concat("&year=").concat(extend.get("year"));
77 | Document doc = Jsoup.parse(OkHttp.string(target, getHeaders()));
78 | for (Element element : doc.select("div.col-xs-6")) {
79 | String pic = element.select("img").get(1).attr("src");
80 | String url = element.select("a.overlay").attr("href");
81 | String name = element.select("div.card-mobile-title").text();
82 | String id = url.split("=")[1];
83 | list.add(new Vod(id, name, pic));
84 | }
85 | if (list.isEmpty()) {
86 | for (Element element : doc.select("a")) {
87 | if (element.attr("href").contains("watch")) {
88 | String pic = element.select("div > img").attr("src");
89 | String url = element.attr("href");
90 | String name = element.select("div > div").text();
91 | String id = url.split("=")[1];
92 | if (name.contains("smart_display")) continue;
93 | list.add(new Vod(id, name, pic));
94 | }
95 | }
96 | }
97 | return Result.string(list);
98 | }
99 |
100 | @Override
101 | public String detailContent(List ids) throws Exception {
102 | Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat("/watch?v=").concat(ids.get(0)), getHeaders()));
103 | String name = doc.getElementById("shareBtn-title").text();
104 | String content = doc.select("div.video-caption-text").text();
105 | String pic = doc.select("meta[property=og:image]").attr("content");
106 | String url = doc.getElementById("video-sd").attr("value");
107 | Vod vod = new Vod();
108 | vod.setVodId(ids.get(0));
109 | vod.setVodPic(pic);
110 | vod.setVodName(name);
111 | vod.setVodContent(content);
112 | vod.setVodPlayFrom("Hanime1");
113 | vod.setVodPlayUrl("播放$" + url);
114 | return Result.string(vod);
115 | }
116 |
117 | @Override
118 | public String searchContent(String key, boolean quick) throws Exception {
119 | List list = new ArrayList<>();
120 | String target = siteUrl.concat("/search?query=").concat(key).concat("&genre=&sort=&year=&month=&duration=");
121 | Document doc = Jsoup.parse(OkHttp.string(target, getHeaders()));
122 | for (Element element : doc.select("div.col-xs-6")) {
123 | String pic = element.select("img").get(1).attr("src");
124 | String url = element.select("a.overlay").attr("href");
125 | String name = element.select("div.card-mobile-title").text();
126 | String id = url.split("=")[1];
127 | list.add(new Vod(id, name, pic));
128 | }
129 | return Result.string(list);
130 | }
131 |
132 | @Override
133 | public String playerContent(String flag, String id, List vipFlags) throws Exception {
134 | return Result.get().url(id).header(getHeaders()).string();
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.utils;
2 |
3 | import android.content.pm.PackageManager;
4 | import android.net.Uri;
5 | import android.os.Build;
6 | import android.util.DisplayMetrics;
7 | import android.util.TypedValue;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.webkit.ValueCallback;
11 | import android.webkit.WebView;
12 | import android.webkit.WebViewClient;
13 |
14 | import com.github.catvod.spider.Init;
15 |
16 | import java.math.BigInteger;
17 | import java.security.MessageDigest;
18 | import java.util.Arrays;
19 | import java.util.List;
20 | import java.util.Locale;
21 | import java.util.regex.Pattern;
22 |
23 | public class Utils {
24 |
25 | 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";
26 | public static final List MEDIA = Arrays.asList("mp4", "mkv", "wmv", "flv", "avi", "mp3", "aac", "flac", "m4a");
27 | public static final Pattern RULE = Pattern.compile(
28 | "http((?!http).){12,}?\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)\\?.*|" +
29 | "http((?!http).){12,}\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)|" +
30 | "http((?!http).)*?video/tos*"
31 | );
32 |
33 | public static boolean isVip(String url) {
34 | List 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");
35 | for (String host : hosts) if (url.contains(host)) return true;
36 | return false;
37 | }
38 |
39 | public static boolean isVideoFormat(String url) {
40 | if (url.contains("url=http") || url.contains(".js") || url.contains(".css") || url.contains(".html")) return false;
41 | return RULE.matcher(url).find();
42 | }
43 |
44 | public static boolean isMobile() {
45 | boolean hasCamera = Init.context().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
46 | boolean hasPhone = Init.context().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
47 | boolean hasBT = Init.context().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
48 | return hasCamera && hasPhone && hasBT;
49 | }
50 |
51 | public static boolean isSub(String ext) {
52 | return ext.equals("srt") || ext.equals("ass") || ext.equals("ssa");
53 | }
54 |
55 | public static String getExt(String name) {
56 | return name.substring(name.lastIndexOf(".") + 1);
57 | }
58 |
59 | public static String getSize(double size) {
60 | if (size <= 0) return "";
61 | if (size > 1024 * 1024 * 1024 * 1024.0) {
62 | size /= (1024 * 1024 * 1024 * 1024.0);
63 | return String.format(Locale.getDefault(), "%.2f%s", size, "TB");
64 | } else if (size > 1024 * 1024 * 1024.0) {
65 | size /= (1024 * 1024 * 1024.0);
66 | return String.format(Locale.getDefault(), "%.2f%s", size, "GB");
67 | } else if (size > 1024 * 1024.0) {
68 | size /= (1024 * 1024.0);
69 | return String.format(Locale.getDefault(), "%.2f%s", size, "MB");
70 | } else {
71 | size /= 1024.0;
72 | return String.format(Locale.getDefault(), "%.2f%s", size, "KB");
73 | }
74 | }
75 |
76 | public static String fixUrl(String base, String src) {
77 | if (src.startsWith("//")) {
78 | Uri parse = Uri.parse(base);
79 | return parse.getScheme() + ":" + src;
80 | } else if (!src.contains("://")) {
81 | Uri parse = Uri.parse(base);
82 | return parse.getScheme() + "://" + parse.getHost() + src;
83 | } else {
84 | return src;
85 | }
86 | }
87 |
88 | public static String removeExt(String text) {
89 | return text.contains(".") ? text.substring(0, text.lastIndexOf(".")) : text;
90 | }
91 |
92 | public static String substring(String text) {
93 | return substring(text, 1);
94 | }
95 |
96 | public static String substring(String text, int num) {
97 | if (text != null && text.length() > num) {
98 | return text.substring(0, text.length() - num);
99 | } else {
100 | return text;
101 | }
102 | }
103 |
104 | public static String getVar(String data, String param) {
105 | for (String var : data.split("var")) if (var.contains(param)) return checkVar(var);
106 | return "";
107 | }
108 |
109 | private static String checkVar(String var) {
110 | if (var.contains("'")) return var.split("'")[1];
111 | if (var.contains("\"")) return var.split("\"")[1];
112 | return "";
113 | }
114 |
115 | public static String MD5(String src) {
116 | return MD5(src, "UTF-8");
117 | }
118 |
119 | public static String MD5(String src, String charset) {
120 | try {
121 | MessageDigest md = MessageDigest.getInstance("MD5");
122 | byte[] messageDigest = md.digest(src.getBytes(charset));
123 | BigInteger no = new BigInteger(1, messageDigest);
124 | StringBuilder sb = new StringBuilder(no.toString(16));
125 | while (sb.length() < 32) sb.insert(0, "0");
126 | return sb.toString().toLowerCase();
127 | } catch (Exception e) {
128 | return "";
129 | }
130 | }
131 |
132 | public static DisplayMetrics getDisplayMetrics() {
133 | return Init.context().getResources().getDisplayMetrics();
134 | }
135 |
136 | public static int dp2px(int dp) {
137 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getDisplayMetrics());
138 | }
139 |
140 | public static void loadUrl(WebView webView, String script) {
141 | loadUrl(webView, script, null);
142 | }
143 |
144 | public static void loadUrl(WebView webView, String script, ValueCallback callback) {
145 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) webView.evaluateJavascript(script, callback);
146 | else webView.loadUrl(script);
147 | }
148 |
149 | public static void addView(View view, ViewGroup.LayoutParams params) {
150 | try {
151 | ViewGroup group = Init.getActivity().getWindow().getDecorView().findViewById(android.R.id.content);
152 | group.addView(view, params);
153 | } catch (Exception e) {
154 | e.printStackTrace();
155 | }
156 | }
157 |
158 | public static void loadWebView(String url, WebViewClient client) {
159 | Init.run(() -> {
160 | WebView webView = new WebView(Init.context());
161 | webView.getSettings().setDatabaseEnabled(true);
162 | webView.getSettings().setDomStorageEnabled(true);
163 | webView.getSettings().setJavaScriptEnabled(true);
164 | addView(webView, new ViewGroup.LayoutParams(0, 0));
165 | webView.setWebViewClient(client);
166 | webView.loadUrl(url);
167 | });
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Ying.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.bean.Class;
6 | import com.github.catvod.bean.Filter;
7 | import com.github.catvod.bean.Result;
8 | import com.github.catvod.bean.Vod;
9 | import com.github.catvod.crawler.Spider;
10 | import com.github.catvod.net.OkHttp;
11 | import com.github.catvod.utils.Utils;
12 |
13 | import org.jsoup.Jsoup;
14 | import org.jsoup.nodes.Document;
15 | import org.jsoup.nodes.Element;
16 | import org.jsoup.select.Elements;
17 |
18 | import java.net.URLEncoder;
19 | import java.util.ArrayList;
20 | import java.util.HashMap;
21 | import java.util.LinkedHashMap;
22 | import java.util.List;
23 | import java.util.Map;
24 |
25 | public class Ying extends Spider {
26 |
27 | private static final String siteUrl = "https://www.yhpdm.com";
28 | private static final String listUrl = siteUrl + "/list/";
29 | private static final String showUrl = siteUrl + "/showp/";
30 | private static final String filterUrl = siteUrl + "/yxsf/js/yx_catalog.js";
31 |
32 | private HashMap getHeaders() {
33 | HashMap headers = new HashMap<>();
34 | headers.put("User-Agent", Utils.CHROME);
35 | return headers;
36 | }
37 |
38 | private Filter getFilter(String[] texts) {
39 | List values = new ArrayList<>();
40 | for (int i = 2; i < texts.length; i++) {
41 | if (!texts[i].isEmpty()) values.add(new Filter.Value(texts[i].trim()));
42 | }
43 | return new Filter(texts[0].trim(), texts[1].trim(), values);
44 | }
45 |
46 | private void addClasses(List classes, String[] texts) {
47 | for (int i = 2; i < texts.length; i++) {
48 | if (!texts[i].isEmpty()) classes.add(new Class(texts[i].trim()));
49 | }
50 | }
51 |
52 | private void checkExtend(StringBuilder sb, HashMap extend, String column) {
53 | if (!extend.containsKey(column) || extend.get(column).equals("全部") || extend.get(column).equals("更新时间")) return;
54 | sb.append("&").append(column).append("=").append(extend.get(column));
55 | }
56 |
57 | @Override
58 | public String homeContent(boolean filter) {
59 | List list = new ArrayList<>();
60 | List classes = new ArrayList<>();
61 | List array = new ArrayList<>();
62 | LinkedHashMap> filters = new LinkedHashMap<>();
63 | Document doc1 = Jsoup.parse(OkHttp.string(filterUrl, getHeaders()));
64 | String[] split = doc1.text().split("_labels = ");
65 | for (int i = 0; i < split.length; i++) {
66 | if (split[i].startsWith("[")) {
67 | split[i] = split[i].substring(0, split[i].indexOf(";")).replace("[", "").replace("]", "").replace("\"", "");
68 | if (split[i].startsWith("region")) addClasses(classes, split[i].split(","));
69 | else array.add(getFilter(split[i].split(",")));
70 | }
71 | }
72 | for (Class type : classes) filters.put(type.getTypeId(), array);
73 | Document doc2 = Jsoup.parse(OkHttp.string(listUrl, getHeaders()));
74 | for (Element element : doc2.select("div.lpic > ul > li")) {
75 | String id = element.select("a").attr("href").split("/")[2];
76 | String name = element.select("h2").text();
77 | String pic = element.select("a > img").attr("src");
78 | String remarks = element.select("span > font").text();
79 | remarks = remarks.contains(":") ? remarks.split(" ")[1] : remarks;
80 | list.add(new Vod(id, name, pic, remarks));
81 | }
82 | return Result.string(classes, list, filters);
83 | }
84 |
85 | @Override
86 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
87 | List list = new ArrayList<>();
88 | StringBuilder sb = new StringBuilder();
89 | sb.append("?pagesize=24&pageindex=").append(Integer.parseInt(pg) - 1);
90 | if (!tid.equals("全部")) sb.append("®ion=").append(tid);
91 | checkExtend(sb, extend, "genre");
92 | checkExtend(sb, extend, "letter");
93 | checkExtend(sb, extend, "year");
94 | checkExtend(sb, extend, "season");
95 | checkExtend(sb, extend, "status");
96 | checkExtend(sb, extend, "label");
97 | checkExtend(sb, extend, "resource");
98 | checkExtend(sb, extend, "order");
99 | Document doc = Jsoup.parse(OkHttp.string(listUrl.concat(sb.toString()), getHeaders()));
100 | for (Element element : doc.select("div.lpic > ul > li")) {
101 | String id = element.select("a").attr("href").split("/")[2];
102 | String name = element.select("h2").text();
103 | String pic = element.select("a > img").attr("src");
104 | String remarks = element.select("span > font").text();
105 | remarks = remarks.contains(":") ? remarks.split(" ")[1] : remarks;
106 | list.add(new Vod(id, name, pic, remarks));
107 | }
108 | return Result.string(list);
109 | }
110 |
111 | @Override
112 | public String detailContent(List ids) {
113 | Document doc = Jsoup.parse(OkHttp.string(showUrl.concat(ids.get(0)), getHeaders()));
114 | String name = doc.select("div.rate > h1").text();
115 | String pic = doc.select("div.thumb > img").attr("src");
116 | String content = doc.select("div.info").text();
117 | Elements element = doc.select("div.sinfo > span > a");
118 |
119 | Vod vod = new Vod();
120 | vod.setVodId(ids.get(0));
121 | vod.setVodName(name);
122 | vod.setVodPic(pic);
123 | vod.setVodContent(content);
124 | vod.setVodArea(element.get(1).text());
125 | vod.setVodYear(element.get(0).text());
126 | vod.setTypeName(element.get(2).text());
127 |
128 | Map sites = new LinkedHashMap<>();
129 | Elements sources = doc.select("ul.menu0 > li");
130 | Elements sourceList = doc.select("div.main0 > div");
131 | for (int i = 0; i < sources.size(); i++) {
132 | Element source = sources.get(i);
133 | String sourceName = source.text();
134 | Elements playList = sourceList.get(i).select("a");
135 | List vodItems = new ArrayList<>();
136 | for (int j = 0; j < playList.size(); j++) {
137 | Element e = playList.get(j);
138 | vodItems.add(e.text() + "$" + e.attr("href"));
139 | }
140 | if (vodItems.size() > 0) {
141 | sites.put(sourceName, TextUtils.join("#", vodItems));
142 | }
143 | }
144 | if (sites.size() > 0) {
145 | vod.setVodPlayFrom(TextUtils.join("$$$", sites.keySet()));
146 | vod.setVodPlayUrl(TextUtils.join("$$$", sites.values()));
147 | }
148 | return Result.string(vod);
149 | }
150 |
151 | @Override
152 | public String searchContent(String key, boolean quick) {
153 | List list = new ArrayList<>();
154 | String target = siteUrl + "/s_all?ex=1&kw=" + URLEncoder.encode(key);
155 | Document doc = Jsoup.parse(OkHttp.string(target, getHeaders()));
156 | for (Element element : doc.select("div.lpic > ul > li")) {
157 | String id = element.select("a").attr("href").split("/")[2];
158 | String name = element.select("h2").text();
159 | String pic = element.select("a > img").attr("src");
160 | String remarks = element.select("span > font").text();
161 | remarks = remarks.contains(":") ? remarks.split(" ")[1] : remarks;
162 | list.add(new Vod(id, name, pic, remarks));
163 | }
164 | return Result.string(list);
165 | }
166 |
167 | @Override
168 | public String playerContent(String flag, String id, List vipFlags) {
169 | return Result.get().url(siteUrl + id).parse().header(getHeaders()).string();
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/catvod/spider/Ysj.java:
--------------------------------------------------------------------------------
1 | package com.github.catvod.spider;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.github.catvod.bean.Class;
6 | import com.github.catvod.bean.Filter;
7 | import com.github.catvod.bean.Result;
8 | import com.github.catvod.bean.Vod;
9 | import com.github.catvod.crawler.Spider;
10 | import com.github.catvod.net.OkHttp;
11 | import com.github.catvod.utils.Utils;
12 |
13 | import org.jsoup.Jsoup;
14 | import org.jsoup.nodes.Document;
15 | import org.jsoup.nodes.Element;
16 | import org.jsoup.select.Elements;
17 |
18 | import java.util.ArrayList;
19 | import java.util.HashMap;
20 | import java.util.LinkedHashMap;
21 | import java.util.List;
22 | import java.util.Map;
23 |
24 | public class Ysj extends Spider {
25 |
26 | private static final String siteUrl = "https://ysjdm.net";
27 | private static final String cateUrl = "https://ysjdm.net/index.php/vod/show";
28 | private static final String homeUrl = "https://ysjdm.net/index.php/vod/show/id/20.html";
29 | private static final String detailUrl = "https://ysjdm.net/index.php/vod/detail/id/";
30 | private static final String searchUrl = "https://ysjdm.net/index.php/vod/search.html";
31 | private static final String playUrl = "/index.php/vod/play/id/";
32 |
33 | private HashMap getHeaders() {
34 | HashMap headers = new HashMap<>();
35 | headers.put("User-Agent", Utils.CHROME);
36 | return headers;
37 | }
38 |
39 | private Filter getFilter(String name, String key, List texts) {
40 | List values = new ArrayList<>();
41 | for (String text : texts) {
42 | if (text.isEmpty()) continue;
43 | values.add(new Filter.Value(text, text.replace("全部", "")));
44 | }
45 | return new Filter(key, name, values);
46 | }
47 |
48 | @Override
49 | public String homeContent(boolean filter) {
50 | List list = new ArrayList<>();
51 | List classes = new ArrayList<>();
52 | List array = new ArrayList<>();
53 | LinkedHashMap> filters = new LinkedHashMap<>();
54 | Document doc = Jsoup.parse(OkHttp.string(homeUrl, getHeaders()));
55 | array.add(getFilter("地區", "area", doc.select("div#hl03").select("a").eachText()));
56 | array.add(getFilter("年份", "year", doc.select("div#hl04").select("a").eachText()));
57 | array.add(getFilter("語言", "lang", doc.select("div#hl05").select("a").eachText()));
58 | array.add(getFilter("字母", "letter", doc.select("div#hl06").select("a").eachText()));
59 | for (Element element : doc.select("div#hl02").select("a")) {
60 | String typeId = element.attr("href").split("/")[5];
61 | typeId = typeId.contains(".html") ? "" : typeId;
62 | String typeName = element.text().replace("BD", "");
63 | classes.add(new Class(typeId, typeName));
64 | filters.put(typeId, array);
65 | }
66 | for (Element element : doc.select("li.vodlist_item")) {
67 | String id = element.select("a").attr("href").split("/")[5];
68 | String name = element.select("a").attr("title");
69 | String pic = siteUrl + element.select("a").attr("data-original");
70 | String remark = element.select("span.pic_text").text();
71 | list.add(new Vod(id, name, pic, remark));
72 | }
73 | return Result.string(classes, list, filters);
74 | }
75 |
76 | @Override
77 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) {
78 | StringBuilder sb = new StringBuilder(cateUrl);
79 | if (extend.containsKey("area")) sb.append("/area/").append(extend.get("area"));
80 | if (tid.length() > 0) sb.append("/class/").append(tid);
81 | sb.append("/id/20");
82 | if (extend.containsKey("lang")) sb.append("/lang/").append(extend.get("lang"));
83 | if (extend.containsKey("letter")) sb.append("/letter/").append(extend.get("letter"));
84 | if (extend.containsKey("year")) sb.append("/year/").append(extend.get("year"));
85 | if (!pg.equals("1")) sb.append("/page/").append(pg);
86 | sb.append(".html");
87 | Document doc = Jsoup.parse(OkHttp.string(sb.toString(), getHeaders()));
88 | List list = new ArrayList<>();
89 | for (Element element : doc.select("li.vodlist_item")) {
90 | String id = element.select("a").attr("href").split("/")[5];
91 | String name = element.select("a").attr("title");
92 | String pic = siteUrl + element.select("a").attr("data-original");
93 | String remark = element.select("span.pic_text").text();
94 | list.add(new Vod(id, name, pic, remark));
95 | }
96 | return Result.string(list);
97 | }
98 |
99 | @Override
100 | public String detailContent(List ids) {
101 | Document doc = Jsoup.parse(OkHttp.string(detailUrl.concat(ids.get(0)), getHeaders()));
102 | String name = doc.select("h2.title").text();
103 | String pic = siteUrl + doc.select("a.vodlist_thumb").attr("data-original");
104 | String year = doc.select("li.data").get(0).select("a").get(0).text();
105 | String area = doc.select("li.data").get(0).select("a").get(1).text();
106 | String type = doc.select("li.data").get(0).select("a").get(2).text();
107 | String actor = doc.select("li.data").get(2).text().replace("主演:", "");
108 | String director = doc.select("li.data").get(3).text().replace("导演:", "");
109 | String content = doc.select("div.content_desc > span").text();
110 |
111 | Vod vod = new Vod();
112 | vod.setVodId(ids.get(0));
113 | vod.setVodPic(pic);
114 | vod.setVodYear(year);
115 | vod.setVodName(name);
116 | vod.setVodArea(area);
117 | vod.setVodActor(actor);
118 | vod.setVodContent(content);
119 | vod.setVodDirector(director);
120 | vod.setTypeName(type);
121 |
122 | Map sites = new LinkedHashMap<>();
123 | Elements sources = doc.select("div.play_source_tab > a");
124 | Elements sourceList = doc.select("ul.content_playlist");
125 | for (int i = 0; i < sources.size(); i++) {
126 | Element source = sources.get(i);
127 | String sourceName = source.attr("alt");
128 | Elements playList = sourceList.get(i).select("a");
129 | List vodItems = new ArrayList<>();
130 | for (int j = 0; j < playList.size(); j++) {
131 | Element e = playList.get(j);
132 | String href = e.attr("href").replace(playUrl, "");
133 | vodItems.add(e.text() + "$" + href);
134 | }
135 | if (vodItems.size() > 0) {
136 | sites.put(sourceName, TextUtils.join("#", vodItems));
137 | }
138 | }
139 | if (sites.size() > 0) {
140 | vod.setVodPlayFrom(TextUtils.join("$$$", sites.keySet()));
141 | vod.setVodPlayUrl(TextUtils.join("$$$", sites.values()));
142 | }
143 | return Result.string(vod);
144 | }
145 |
146 | @Override
147 | public String searchContent(String key, boolean quick) {
148 | List