├── .github └── workflows │ └── main.yml ├── .gitignore ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── github │ │ └── catvod │ │ ├── ali │ │ └── API.java │ │ ├── bean │ │ ├── Class.java │ │ ├── Filter.java │ │ ├── Result.java │ │ ├── Sub.java │ │ ├── Vod.java │ │ ├── ali │ │ │ ├── Biz.java │ │ │ ├── Code.java │ │ │ ├── Data.java │ │ │ ├── Item.java │ │ │ ├── OAuth.java │ │ │ └── User.java │ │ ├── alist │ │ │ ├── Drive.java │ │ │ ├── Item.java │ │ │ └── Sorter.java │ │ ├── paper │ │ │ └── Data.java │ │ ├── upyun │ │ │ ├── Data.java │ │ │ └── Item.java │ │ ├── webdav │ │ │ ├── Drive.java │ │ │ └── Sorter.java │ │ ├── xpath │ │ │ └── Rule.java │ │ └── yiso │ │ │ └── Item.java │ │ ├── crawler │ │ ├── Spider.java │ │ └── SpiderDebug.java │ │ ├── demo │ │ └── MainActivity.java │ │ ├── net │ │ ├── Cronet.java │ │ ├── OkHttp.java │ │ ├── OkRequest.java │ │ ├── OkResult.java │ │ └── SSLSocketFactoryCompat.java │ │ ├── spider │ │ ├── AList.java │ │ ├── Ali.java │ │ ├── Bili.java │ │ ├── Dm84.java │ │ ├── Doll.java │ │ ├── Dovx.java │ │ ├── Eighteen.java │ │ ├── Hanime.java │ │ ├── Init.java │ │ ├── Jable.java │ │ ├── Local.java │ │ ├── Miss.java │ │ ├── PanSearch.java │ │ ├── PanSou.java │ │ ├── Proxy.java │ │ ├── Push.java │ │ ├── Supjav.java │ │ ├── TuGou.java │ │ ├── UpYun.java │ │ ├── WebDAV.java │ │ ├── XPath.java │ │ ├── XPathFilter.java │ │ ├── XPathMac.java │ │ ├── XPathMacFilter.java │ │ ├── Ying.java │ │ ├── Ysj.java │ │ └── Zhaozy.java │ │ └── utils │ │ ├── FileUtil.java │ │ ├── Image.java │ │ ├── Prefers.java │ │ ├── QRCode.java │ │ ├── ReflectUtil.java │ │ └── Utils.java │ └── res │ ├── layout │ └── activity_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.webp │ ├── mipmap-mdpi │ └── ic_launcher.webp │ ├── mipmap-xhdpi │ └── ic_launcher.webp │ ├── mipmap-xxhdpi │ └── ic_launcher.webp │ └── values │ └── strings.xml ├── build.bat ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jar ├── 3rd │ ├── apktool_2.4.1.jar │ ├── baksmali-2.5.2.jar │ └── oss.jar ├── custom_spider.jar ├── custom_spider.jar.md5 ├── genJar.bat └── spider.jar │ ├── apktool.yml │ └── original │ └── META-INF │ └── MANIFEST.MF ├── json ├── adult.json ├── alist.json ├── bili.json ├── config.json ├── duboku.json └── webdav.json ├── settings.gradle ├── tools ├── .gitignore ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties └── src │ └── main │ ├── java │ └── com │ │ └── fongmi │ │ └── tools │ │ ├── Run.java │ │ ├── Util.java │ │ └── bean │ │ ├── Channel.java │ │ ├── Data.java │ │ └── Group.java │ └── resources │ ├── data.json │ └── live.txt └── txt ├── adult.txt └── cookie.txt /.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']" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | *build 4 | *.jks 5 | *i.java 6 | /local.properties -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CatVodSpider 2 | 3 | #仓库fokk自fongmi大佬,仅仅适配了影视仓本地配置token方法,以及增加了githubAction打包,其他与fongmi仓库一致 4 | 5 | ### Based on CatVod 6 | 7 | https://github.com/CatVodTVOfficial/CatVodTVSpider 8 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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/Dm84.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 | /** 26 | * @author FongMi 27 | */ 28 | public class Dm84 extends Spider { 29 | 30 | private static final String siteUrl = "https://dm84.tv"; 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 name, String key, List texts) { 39 | List values = new ArrayList<>(); 40 | for (String text : texts) { 41 | if (text.isEmpty()) continue; 42 | String n = text.replace("按", ""); 43 | String v = key.equals("by") ? replaceBy(text) : text; 44 | values.add(new Filter.Value(n, v)); 45 | } 46 | return new Filter(key, name, values); 47 | } 48 | 49 | private String replaceBy(String text) { 50 | return text.replace("按时间", "time").replace("按人气", "hits").replace("按评分", "score"); 51 | } 52 | 53 | @Override 54 | public String homeContent(boolean filter) { 55 | List list = new ArrayList<>(); 56 | List classes = new ArrayList<>(); 57 | LinkedHashMap> filters = new LinkedHashMap<>(); 58 | Document doc = Jsoup.parse(OkHttp.string(siteUrl, getHeaders())); 59 | for (Element element : doc.select("ul.nav_row > li > a")) { 60 | if (element.attr("href").startsWith("/list")) { 61 | String id = element.attr("href").split("-")[1].substring(0, 1); 62 | String name = element.text().substring(0, 2); 63 | classes.add(new Class(id, name)); 64 | } 65 | } 66 | for (Class item : classes) { 67 | doc = Jsoup.parse(OkHttp.string(siteUrl + "/list-" + item.getTypeId() + ".html", getHeaders())); 68 | Elements elements = doc.select("ul.list_filter > li > div"); 69 | List array = new ArrayList<>(); 70 | array.add(getFilter("類型", "type", elements.get(0).select("a").eachText())); 71 | array.add(getFilter("時間", "year", elements.get(1).select("a").eachText())); 72 | array.add(getFilter("排序", "by", elements.get(2).select("a").eachText())); 73 | filters.put(item.getTypeId(), array); 74 | } 75 | for (Element element : doc.select("div.item")) { 76 | String img = element.select("a.cover").attr("data-bg"); 77 | String url = element.select("a.title").attr("href"); 78 | String name = element.select("a.title").text(); 79 | String remark = element.select("span.desc").text(); 80 | String id = url.split("/")[2]; 81 | list.add(new Vod(id, name, img, remark)); 82 | } 83 | return Result.string(classes, list, filters); 84 | } 85 | 86 | @Override 87 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { 88 | List list = new ArrayList<>(); 89 | if (extend.get("type") == null) extend.put("type", ""); 90 | if (extend.get("year") == null) extend.put("year", ""); 91 | if (extend.get("by") == null) extend.put("by", "time"); 92 | String by = extend.get("by"); 93 | String type = URLEncoder.encode(extend.get("type")); 94 | String year = extend.get("year"); 95 | String target = siteUrl + String.format("/show-%s--%s-%s--%s-%s.html", tid, by, type, year, pg); 96 | Document doc = Jsoup.parse(OkHttp.string(target, getHeaders())); 97 | for (Element element : doc.select("div.item")) { 98 | String img = element.select("a.cover").attr("data-bg"); 99 | String url = element.select("a.title").attr("href"); 100 | String name = element.select("a.title").text(); 101 | String remark = element.select("span.desc").text(); 102 | String id = url.split("/")[2]; 103 | list.add(new Vod(id, name, img, remark)); 104 | } 105 | return Result.string(list); 106 | } 107 | 108 | @Override 109 | public String detailContent(List ids) { 110 | Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat("/v/").concat(ids.get(0)), getHeaders())); 111 | String name = doc.select("h1.v_title").text(); 112 | String remarks = doc.select("p.v_desc > span.desc").text(); 113 | String img = doc.select("meta[property=og:image]").attr("content"); 114 | String area = doc.select("meta[name=og:video:area]").attr("content"); 115 | String type = doc.select("meta[name=og:video:class]").attr("content"); 116 | String actor = doc.select("meta[name=og:video:actor]").attr("content"); 117 | String content = doc.select("meta[property=og:description]").attr("content"); 118 | String year = doc.select("meta[name=og:video:release_date]").attr("content"); 119 | String director = doc.select("meta[name=og:video:director]").attr("content"); 120 | 121 | Vod vod = new Vod(); 122 | vod.setVodId(ids.get(0)); 123 | vod.setVodPic(img); 124 | vod.setVodYear(year); 125 | vod.setVodName(name); 126 | vod.setVodArea(area); 127 | vod.setVodActor(actor); 128 | vod.setVodRemarks(remarks); 129 | vod.setVodContent(content); 130 | vod.setVodDirector(director); 131 | vod.setTypeName(type); 132 | 133 | Map sites = new LinkedHashMap<>(); 134 | Elements sources = doc.select("ul.tab_control > li"); 135 | Elements sourceList = doc.select("ul.play_list"); 136 | for (int i = 0; i < sources.size(); i++) { 137 | Element source = sources.get(i); 138 | String sourceName = source.text(); 139 | Elements playList = sourceList.get(i).select("a"); 140 | List vodItems = new ArrayList<>(); 141 | for (int j = 0; j < playList.size(); j++) { 142 | Element e = playList.get(j); 143 | vodItems.add(e.text() + "$" + e.attr("href")); 144 | } 145 | if (vodItems.size() > 0) { 146 | sites.put(sourceName, TextUtils.join("#", vodItems)); 147 | } 148 | } 149 | if (sites.size() > 0) { 150 | vod.setVodPlayFrom(TextUtils.join("$$$", sites.keySet())); 151 | vod.setVodPlayUrl(TextUtils.join("$$$", sites.values())); 152 | } 153 | return Result.string(vod); 154 | } 155 | 156 | @Override 157 | public String searchContent(String key, boolean quick) { 158 | List list = new ArrayList<>(); 159 | String target = siteUrl.concat("/s----------.html?wd=").concat(key); 160 | Document doc = Jsoup.parse(OkHttp.string(target, getHeaders())); 161 | for (Element element : doc.select("div.item")) { 162 | String img = element.select("a.cover").attr("data-bg"); 163 | String url = element.select("a.title").attr("href"); 164 | String name = element.select("a.title").text(); 165 | String remark = element.select("span.desc").text(); 166 | String id = url.split("/")[2]; 167 | list.add(new Vod(id, name, img, remark)); 168 | } 169 | return Result.string(list); 170 | } 171 | 172 | @Override 173 | public String playerContent(String flag, String id, List vipFlags) { 174 | Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat(id), getHeaders())); 175 | String url = doc.select("iframe").attr("src"); 176 | return Result.get().url(url).parse().header(getHeaders()).string(); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/spider/Supjav.java: -------------------------------------------------------------------------------- 1 | package com.github.catvod.spider; 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.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 Supjav extends Spider { 26 | 27 | private static final String siteUrl = "https://supjav.com/zh/"; 28 | private static final String playUrl = "https://lk1.supremejav.com/"; 29 | 30 | private HashMap getHeaders() { 31 | return getHeaders(siteUrl); 32 | } 33 | 34 | private HashMap getHeaders(String referer) { 35 | HashMap headers = new HashMap<>(); 36 | headers.put("User-Agent", Utils.CHROME); 37 | headers.put("Referer", referer); 38 | return headers; 39 | } 40 | 41 | @Override 42 | public String homeContent(boolean filter) { 43 | List list = new ArrayList<>(); 44 | List classes = new ArrayList<>(); 45 | Document doc = Jsoup.parse(OkHttp.string(siteUrl, getHeaders())); 46 | for (Element element : doc.select("ul.nav > li > a")) { 47 | String href = element.attr("href"); 48 | if (href.split("/").length < 5) continue; 49 | String typeId = href.replace(siteUrl, ""); 50 | String typeName = element.text(); 51 | classes.add(new Class(typeId, typeName)); 52 | } 53 | for (Element element : doc.select("div.post")) { 54 | String src = element.select("img").attr("src"); 55 | String data = element.select("img").attr("data-original"); 56 | String url = element.select("a").attr("href"); 57 | String name = element.select("a").attr("title"); 58 | String pic = TextUtils.isEmpty(data) ? src : data; 59 | String id = url.split("/")[4]; 60 | list.add(new Vod(id, name, pic)); 61 | } 62 | return Result.string(classes, list); 63 | } 64 | 65 | @Override 66 | public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { 67 | List list = new ArrayList<>(); 68 | Document doc = Jsoup.parse(OkHttp.string(siteUrl + tid + "/page/" + pg, getHeaders())); 69 | for (Element element : doc.select("div.post")) { 70 | String pic = element.select("img").attr("data-original"); 71 | String url = element.select("a").attr("href"); 72 | String name = element.select("a").attr("title"); 73 | String id = url.split("/")[4]; 74 | list.add(new Vod(id, name, pic)); 75 | } 76 | return Result.string(list); 77 | } 78 | 79 | @Override 80 | public String detailContent(List ids) { 81 | Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat(ids.get(0)), getHeaders())); 82 | String name = doc.select("div.post-meta > img").attr("alt"); 83 | String img = doc.select("div.post-meta > img").attr("src"); 84 | String type = doc.select("p.cat > a").text(); 85 | String director = "", actor = ""; 86 | for (Element p : doc.select("div.cats > p")) { 87 | if (p.select("span").text().contains("Maker")) { 88 | director = p.select("a").text(); 89 | } 90 | if (p.select("span").text().contains("Cast")) { 91 | actor = p.select("a").text(); 92 | } 93 | } 94 | 95 | Vod vod = new Vod(); 96 | vod.setVodId(ids.get(0)); 97 | vod.setVodPic(img); 98 | vod.setVodName(name); 99 | vod.setVodActor(actor); 100 | vod.setVodDirector(director); 101 | vod.setTypeName(type); 102 | 103 | Map sites = new LinkedHashMap<>(); 104 | Elements sources = doc.select("a.btn-server"); 105 | for (int i = 0; i < sources.size(); i++) { 106 | Element source = sources.get(i); 107 | String sourceName = source.text(); 108 | if (sourceName.equals("JPA")) continue; 109 | String sourceUrl = source.attr("data-link"); 110 | sites.put(sourceName, "播放" + "$" + sourceUrl); 111 | } 112 | if (sites.size() > 0) { 113 | vod.setVodPlayFrom(TextUtils.join("$$$", sites.keySet())); 114 | vod.setVodPlayUrl(TextUtils.join("$$$", sites.values())); 115 | } 116 | return Result.string(vod); 117 | } 118 | 119 | @Override 120 | public String searchContent(String key, boolean quick) { 121 | List list = new ArrayList<>(); 122 | Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat("?s=").concat(URLEncoder.encode(key)), getHeaders())); 123 | for (Element element : doc.select("div.post")) { 124 | String pic = element.select("img").attr("data-original"); 125 | String url = element.select("a").attr("href"); 126 | String name = element.select("a").attr("title"); 127 | String id = url.split("/")[4]; 128 | list.add(new Vod(id, name, pic)); 129 | } 130 | return Result.string(list); 131 | } 132 | 133 | @Override 134 | public String playerContent(String flag, String id, List vipFlags) { 135 | Map> respHeaders = new HashMap<>(); 136 | OkHttp.stringNoRedirect(playUrl + "supjav.php?c=" + new StringBuilder(id).reverse(), getHeaders(playUrl), respHeaders); 137 | String redirect = OkHttp.getRedirectLocation(respHeaders); 138 | switch (flag) { 139 | case "TV": 140 | return parseTV(redirect); 141 | case "ST": 142 | return parseST(redirect); 143 | case "DS": 144 | return parseDS(redirect); 145 | default: 146 | return Result.get().url(id).parse().string(); 147 | } 148 | } 149 | 150 | private String parseTV(String redirect) { 151 | String data = OkHttp.string(redirect, getHeaders(playUrl)); 152 | return Result.get().url(Utils.getVar(data, "urlPlay")).header(getHeaders(redirect)).string(); 153 | } 154 | 155 | private String parseST(String redirect) { 156 | Map> respHeaders = new HashMap<>(); 157 | String data = OkHttp.string(redirect, getHeaders(playUrl)); 158 | String robot = Jsoup.parse(data).getElementById("robotlink").text(); 159 | robot = robot.substring(0, robot.indexOf("&token=") + 7); 160 | for (String text : data.split("&token=")) { 161 | if (!text.contains("').substring(")) continue; 162 | robot = "https:/" + robot + text.split("'")[0] + "&stream=1"; 163 | OkHttp.stringNoRedirect(robot, getHeaders(redirect), respHeaders); 164 | String url = OkHttp.getRedirectLocation(respHeaders); 165 | return Result.get().url(url).header(getHeaders(redirect)).string(); 166 | } 167 | return ""; 168 | } 169 | 170 | private String parseDS(String redirect) { 171 | String host = "https://" + Uri.parse(redirect).getHost(); 172 | Map> respHeaders = new HashMap<>(); 173 | OkHttp.stringNoRedirect(redirect, getHeaders(playUrl), respHeaders); 174 | redirect = host + OkHttp.getRedirectLocation(respHeaders); 175 | String data = OkHttp.string(redirect, getHeaders()); 176 | for (String text : data.split("'")) { 177 | if (!text.startsWith("/pass_md5/")) continue; 178 | String token = text.split("/")[3]; 179 | String url = OkHttp.string(host + text, getHeaders(redirect)); 180 | url = url + getDSRnd() + "?token=" + token + "&expiry=" + System.currentTimeMillis(); 181 | return Result.get().url(url).header(getHeaders(redirect)).string(); 182 | } 183 | return ""; 184 | } 185 | 186 | private String getDSRnd() { 187 | StringBuilder sb = new StringBuilder(); 188 | String t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 189 | for (int o = 0; o < 10; o++) sb.append(t.charAt((int) Math.floor(Math.random() * t.length()))); 190 | return sb.toString(); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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/spider/XPathMac.java: -------------------------------------------------------------------------------- 1 | package com.github.catvod.spider; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.util.Base64; 6 | 7 | import com.github.catvod.crawler.SpiderDebug; 8 | import com.github.catvod.utils.Utils; 9 | import com.google.gson.Gson; 10 | 11 | import org.json.JSONException; 12 | import org.json.JSONObject; 13 | import org.jsoup.Jsoup; 14 | import org.jsoup.nodes.Document; 15 | import org.jsoup.select.Elements; 16 | 17 | import java.net.URLDecoder; 18 | import java.util.HashMap; 19 | import java.util.Iterator; 20 | import java.util.List; 21 | import java.util.regex.Matcher; 22 | import java.util.regex.Pattern; 23 | 24 | public class XPathMac extends XPath { 25 | 26 | // 嘗試分析直連 27 | private boolean decodePlayUrl; 28 | // 嘗試匹配官源標識以調用應用配置中的解析列表 29 | private boolean decodeVipFlag; 30 | // 播放器配置js 31 | private String playerConfigJs = ""; 32 | // 播放器配置js取值正則 33 | private String playerConfigJsRegex = "[\\W|\\S|.]*?MacPlayerConfig.player_list[\\W|\\S|.]*?=([\\W|\\S|.]*?),MacPlayerConfig.downer_list"; 34 | // 站點里播放源對應的真實官源 35 | private final HashMap show2VipFlag = new HashMap<>(); 36 | 37 | /** 38 | * mac cms 直連和官源調用應用內播放列表支持 39 | * 40 | * @param context 41 | * @param extend 42 | */ 43 | public void init(Context context, String extend) { 44 | super.init(context, extend); 45 | } 46 | 47 | @Override 48 | protected void loadRuleExt(String json) { 49 | try { 50 | JSONObject jsonObj = new JSONObject(json); 51 | decodePlayUrl = jsonObj.optBoolean("dcPlayUrl", false); 52 | decodeVipFlag = jsonObj.optBoolean("dcVipFlag", false); 53 | JSONObject dcShow2Vip = jsonObj.optJSONObject("dcShow2Vip"); 54 | if (dcShow2Vip != null) { 55 | Iterator keys = dcShow2Vip.keys(); 56 | while (keys.hasNext()) { 57 | String name = keys.next(); 58 | show2VipFlag.put(name.trim(), dcShow2Vip.getString(name).trim()); 59 | } 60 | } 61 | playerConfigJs = jsonObj.optString("pCfgJs").trim(); 62 | playerConfigJsRegex = jsonObj.optString("pCfgJsR", playerConfigJsRegex).trim(); 63 | } catch (JSONException e) { 64 | SpiderDebug.log(e); 65 | } 66 | } 67 | 68 | @Override 69 | public String homeContent(boolean filter) { 70 | String result = super.homeContent(filter); 71 | if (result.length() > 0 && playerConfigJs.length() > 0) { // 嘗試通過playerConfigJs獲取展示和flag匹配關系 72 | String webContent = fetch(playerConfigJs); 73 | Matcher matcher = Pattern.compile(playerConfigJsRegex).matcher(webContent); 74 | if (matcher.find()) { 75 | try { 76 | JSONObject jsonObject = new JSONObject(matcher.group(1)); 77 | Iterator keys = jsonObject.keys(); 78 | while (keys.hasNext()) { 79 | String key = keys.next(); 80 | JSONObject keyObj = jsonObject.optJSONObject(key); 81 | if (keyObj == null) continue; 82 | String show = keyObj.optString("show").trim(); 83 | if (show.isEmpty()) continue; 84 | show2VipFlag.put(show, key); 85 | } 86 | } catch (Exception e) { 87 | SpiderDebug.log(e); 88 | } 89 | } 90 | } 91 | return result; 92 | } 93 | 94 | @Override 95 | public String detailContent(List ids) { 96 | String result = super.detailContent(ids); 97 | if (decodeVipFlag && result.length() > 0) { 98 | try { 99 | JSONObject jsonObject = new JSONObject(result); 100 | String[] playFrom = jsonObject.optJSONArray("list").getJSONObject(0).optString("vod_play_from").split("\\$\\$\\$"); 101 | if (playFrom.length > 0) { 102 | for (int i = 0; i < playFrom.length; i++) { 103 | if (show2VipFlag.containsKey(playFrom[i])) { 104 | playFrom[i] = show2VipFlag.get(playFrom[i]); 105 | } 106 | } 107 | jsonObject.optJSONArray("list").getJSONObject(0).put("vod_play_from", TextUtils.join("$$$", playFrom)); 108 | result = jsonObject.toString(); 109 | } 110 | } catch (Throwable th) { 111 | SpiderDebug.log(th); 112 | } 113 | } 114 | return result; 115 | } 116 | 117 | @Override 118 | public String playerContent(String flag, String id, List vipFlags) { 119 | fetchRule(); 120 | String webUrl = rule.getPlayUrl().isEmpty() ? id : rule.getPlayUrl().replace("{playUrl}", id); 121 | String videoUrl = null; 122 | // 嘗試分析直連 123 | if (decodePlayUrl) { 124 | try { 125 | Document doc = Jsoup.parse(fetch(webUrl)); 126 | Elements allScript = doc.select("script"); 127 | for (int i = 0; i < allScript.size(); i++) { 128 | String scContent = allScript.get(i).html().trim(); 129 | if (scContent.startsWith("var player_")) { 130 | int start = scContent.indexOf('{'); 131 | int end = scContent.lastIndexOf('}') + 1; 132 | String json = scContent.substring(start, end); 133 | JSONObject player = new JSONObject(json); 134 | String videoUrlTmp = player.getString("url"); 135 | if (player.has("encrypt")) { 136 | int encrypt = player.getInt("encrypt"); 137 | if (encrypt == 1) { 138 | videoUrlTmp = URLDecoder.decode(videoUrlTmp); 139 | } else if (encrypt == 2) { 140 | videoUrlTmp = new String(Base64.decode(videoUrlTmp, Base64.DEFAULT)); 141 | videoUrlTmp = URLDecoder.decode(videoUrlTmp); 142 | } 143 | } 144 | videoUrl = videoUrlTmp; 145 | break; 146 | } 147 | } 148 | } catch (Exception e) { 149 | SpiderDebug.log(e); 150 | } 151 | } 152 | if (videoUrl != null) { 153 | // 適配2.0.6的調用應用內解析列表的支持, 需要配合直連分析和匹配官源解析一起使用,參考cjt影視和極品直連 154 | if (decodeVipFlag && Utils.isVip(videoUrl)) { // 使用jx:1 155 | try { 156 | JSONObject result = new JSONObject(); 157 | result.put("parse", 1); 158 | result.put("jx", "1"); 159 | result.put("url", videoUrl); 160 | return result.toString(); 161 | } catch (Exception e) { 162 | SpiderDebug.log(e); 163 | } 164 | } else if (decodeVipFlag && vipFlags.contains(flag)) { // 是否使用應用內解析列表解析官源 165 | try { 166 | JSONObject result = new JSONObject(); 167 | result.put("parse", 1); 168 | result.put("playUrl", ""); 169 | result.put("url", videoUrl); 170 | result.put("header", ""); 171 | return result.toString(); 172 | } catch (Exception e) { 173 | SpiderDebug.log(e); 174 | } 175 | } 176 | // 如果是視頻直連 直接返回免解 177 | else if (isVideoFormat(videoUrl)) { 178 | try { 179 | JSONObject result = new JSONObject(); 180 | result.put("parse", 0); 181 | result.put("playUrl", ""); 182 | result.put("url", videoUrl); 183 | HashMap headers = new HashMap<>(); 184 | if (rule.getPlayUa().length() > 0) headers.put("User-Agent", rule.getPlayUa()); 185 | if (rule.getPlayReferer().length() > 0) headers.put("Referer", rule.getPlayReferer()); 186 | result.put("header", new Gson().toJson(headers)); 187 | return result.toString(); 188 | } catch (Exception e) { 189 | SpiderDebug.log(e); 190 | } 191 | } 192 | } 193 | // 上述都失敗了就按默認模式走 194 | return super.playerContent(flag, id, vipFlags); 195 | } 196 | } -------------------------------------------------------------------------------- /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/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 list = new ArrayList<>(); 149 | String target = searchUrl.concat("?wd=").concat(key).concat("&submit="); 150 | Document doc = Jsoup.parse(OkHttp.string(target, getHeaders())); 151 | if (doc.html().contains("很抱歉,暂无相关视频")) return Result.string(list); 152 | for (Element element : doc.select("li.searchlist_item")) { 153 | String id = element.select("a").attr("href").split("/")[5]; 154 | String name = element.select("a").attr("title"); 155 | String pic = siteUrl + element.select("a").attr("data-original"); 156 | String remark = element.select("span.pic_text").text(); 157 | list.add(new Vod(id, name, pic, remark)); 158 | } 159 | return Result.string(list); 160 | } 161 | 162 | @Override 163 | public String playerContent(String flag, String id, List vipFlags) { 164 | return Result.get().url(siteUrl + playUrl + id).parse().header(getHeaders()).string(); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CatVodSpider 3 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call "%~dp0\gradlew" assembleRelease --no-daemon 4 | 5 | call "%~dp0\jar\genJar.bat" %1 6 | 7 | pause -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id 'ru.cleverpumpkin.proguard-dictionaries-generator' version '1.0.8' apply false 4 | id 'com.android.application' version '7.2.2' apply false 5 | id 'com.android.library' version '7.2.2' apply false 6 | } 7 | 8 | task clean(type: Delete) { 9 | delete rootProject.buildDir 10 | } -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /jar/3rd/apktool_2.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/jar/3rd/apktool_2.4.1.jar -------------------------------------------------------------------------------- /jar/3rd/baksmali-2.5.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/jar/3rd/baksmali-2.5.2.jar -------------------------------------------------------------------------------- /jar/3rd/oss.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/jar/3rd/oss.jar -------------------------------------------------------------------------------- /jar/custom_spider.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/jar/custom_spider.jar -------------------------------------------------------------------------------- /jar/custom_spider.jar.md5: -------------------------------------------------------------------------------- 1 | 8b50403c7f94d6d04c1812adfb2957b6 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tools/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /tools/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nbwzlyd/CatVodSpider/d60d1ca90b8f732afff00cb4017a18684e8aa06a/tools/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /txt/cookie.txt: -------------------------------------------------------------------------------- 1 | DedeUserID=690781341;DedeUserID__ckMd5=cabc96906269c5b6;SESSDATA=2245ba24%2C1684212125%2C466fd%2Ab2;bili_jct=de6fdb60c10f8a83910aa55d79407b4e; --------------------------------------------------------------------------------