diff --git a/app/build.gradle b/app/build.gradle index ef040da3..2b9f8cf9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,12 +6,18 @@ plugins { android { namespace 'com.github.catvod' - compileSdk 35 + compileSdk { + version = release(36) + } defaultConfig { applicationId "com.github.catvod.demo" minSdk 21 - targetSdk 35 + targetSdk 36 + } + + buildFeatures { + viewBinding true } buildTypes { @@ -28,8 +34,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } configurations.configureEach { @@ -42,10 +48,9 @@ android { dependencies { implementation 'com.squareup.okhttp3:okhttp:' + okhttpVersion implementation 'com.github.thegrizzlylabs:sardine-android:0.9' - implementation 'wang.harlon.quickjs:wrapper-android:2.4.5' - implementation 'com.google.code.gson:gson:2.11.0' - implementation 'cn.wanghaomiao:JsoupXpath:2.5.1' + implementation 'wang.harlon.quickjs:wrapper-android:3.2.3' + implementation 'com.google.code.gson:gson:2.13.2' implementation 'com.hierynomus:smbj:0.14.0' implementation 'com.orhanobut:logger:2.2.0' - implementation 'org.jsoup:jsoup:1.18.3' + implementation 'org.jsoup:jsoup:1.21.2' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d68fdf9b..4c46328c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,7 +14,7 @@ android:usesCleartextTraffic="true"> diff --git a/app/src/main/java/com/github/catvod/MainActivity.java b/app/src/main/java/com/github/catvod/MainActivity.java new file mode 100644 index 00000000..2924320a --- /dev/null +++ b/app/src/main/java/com/github/catvod/MainActivity.java @@ -0,0 +1,142 @@ +package com.github.catvod; + +import android.app.Activity; +import android.os.Bundle; + +import com.github.catvod.crawler.Spider; +import com.github.catvod.databinding.ActivityMainBinding; +import com.github.catvod.spider.Init; +import com.github.catvod.spider.PTT; +import com.github.catvod.spider.Proxy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParser; +import com.orhanobut.logger.AndroidLogAdapter; +import com.orhanobut.logger.Logger; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class MainActivity extends Activity { + + private ActivityMainBinding binding; + private ExecutorService executor; + private Spider spider; + private Gson gson; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + gson = new GsonBuilder().setPrettyPrinting().create(); + Logger.addLogAdapter(new AndroidLogAdapter()); + executor = Executors.newCachedThreadPool(); + executor.execute(this::initSpider); + spider = new PTT(); + initView(); + initEvent(); + } + + private void initView() { + binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + } + + private void initEvent() { + binding.home.setOnClickListener(view -> executor.execute(this::homeContent)); + binding.homeVideo.setOnClickListener(view -> executor.execute(this::homeVideoContent)); + binding.category.setOnClickListener(view -> executor.execute(this::categoryContent)); + binding.detail.setOnClickListener(view -> executor.execute(this::detailContent)); + binding.player.setOnClickListener(view -> executor.execute(this::playerContent)); + binding.search.setOnClickListener(view -> executor.execute(this::searchContent)); + binding.live.setOnClickListener(view -> executor.execute(this::liveContent)); + binding.proxy.setOnClickListener(view -> executor.execute(this::proxy)); + } + + private void initSpider() { + try { + Init.init(getApplicationContext()); + spider.init(this, ""); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void homeContent() { + try { + String result = gson.toJson(JsonParser.parseString(spider.homeContent(true))); + Init.post(() -> binding.result.setText(result)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void homeVideoContent() { + try { + String result = gson.toJson(JsonParser.parseString(spider.homeVideoContent())); + Init.post(() -> binding.result.setText(result)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void categoryContent() { + try { + HashMap extend = new HashMap<>(); + extend.put("c", "19"); + extend.put("year", "2024"); + String result = gson.toJson(JsonParser.parseString(spider.categoryContent("3", "2", true, extend))); + Init.post(() -> binding.result.setText(result)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void detailContent() { + try { + String result = gson.toJson(JsonParser.parseString(spider.detailContent(List.of("78702")))); + Init.post(() -> binding.result.setText(result)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void playerContent() { + try { + String result = gson.toJson(JsonParser.parseString(spider.playerContent("", "382044/1/78", new ArrayList<>()))); + Init.post(() -> binding.result.setText(result)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void searchContent() { + try { + String result = gson.toJson(JsonParser.parseString(spider.searchContent("我的人间烟火", false))); + Init.post(() -> binding.result.setText(result)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void liveContent() { + try { + String result = gson.toJson(JsonParser.parseString(spider.liveContent(""))); + Init.post(() -> binding.result.setText(result)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void proxy() { + try { + Map params = new HashMap<>(); + Logger.t("liveContent").d(Proxy.proxy(params)); + } catch (Throwable e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/bean/alist/Item.java b/app/src/main/java/com/github/catvod/bean/alist/Item.java index bf8f9ebe..e62e0c94 100644 --- a/app/src/main/java/com/github/catvod/bean/alist/Item.java +++ b/app/src/main/java/com/github/catvod/bean/alist/Item.java @@ -111,6 +111,10 @@ public class Item { } public String getVodId(String id) { + return id + "/" + getName(); + } + + public String getVodPath(String id) { return id + getPath() + "/" + getName(); } @@ -127,6 +131,6 @@ public class Item { } public Vod getVod(Drive drive) { - return new Vod(getVodId(drive.getName()), getName(), getPic(), drive.getName(), isFolder()); + return new Vod(getVodPath(drive.getName()), getName(), getPic(), drive.getName(), isFolder()); } } diff --git a/app/src/main/java/com/github/catvod/bean/jianpian/Data.java b/app/src/main/java/com/github/catvod/bean/jianpian/Data.java index 38db8562..0e0880ce 100644 --- a/app/src/main/java/com/github/catvod/bean/jianpian/Data.java +++ b/app/src/main/java/com/github/catvod/bean/jianpian/Data.java @@ -6,13 +6,16 @@ import com.github.catvod.bean.Vod; import com.github.catvod.utils.Util; import com.google.gson.annotations.SerializedName; +import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Data { - @SerializedName(value = "jump_id", alternate = "id") + @SerializedName("jump_id") private String jumpId; + @SerializedName("id") + private String id; @SerializedName(value = "thumbnail", alternate = "path") private String thumbnail; @SerializedName("title") @@ -24,24 +27,30 @@ public class Data { @SerializedName("playlist") private Value playlist; @SerializedName("year") - private Value year; + private String year; @SerializedName("area") - private Value area; + private String area; @SerializedName("types") private List types; @SerializedName("actors") private List actors; @SerializedName("directors") private List directors; - @SerializedName("btbo_downlist") - private List btboDownlist; + @SerializedName("source_list_source") + private List source; + @SerializedName("dataList") + private List dataList; public String getJumpId() { return TextUtils.isEmpty(jumpId) ? "" : jumpId; } - public String getThumbnail() { - return TextUtils.isEmpty(thumbnail) ? "" : thumbnail + "@Referer=www.jianpianapp.com@User-Agent=jianpian-version362"; + public String getId() { + return TextUtils.isEmpty(id) ? "" : id; + } + + public String getThumbnail(String imgDomain) { + return TextUtils.isEmpty(thumbnail) ? "" : "http://" + imgDomain + thumbnail; } public String getTitle() { @@ -61,11 +70,11 @@ public class Data { } public String getYear() { - return year == null ? "" : year.getTitle(); + return year == null ? "" : year; } public String getArea() { - return area == null ? "" : area.getTitle(); + return area == null ? "" : area; } public String getTypes() { @@ -80,12 +89,20 @@ public class Data { return directors == null ? "" : getValues(directors, true); } - public List getBtboDownlist() { - return btboDownlist == null ? Collections.emptyList() : btboDownlist; + public List getSource() { + return source == null ? Collections.emptyList() : source; } - public Vod vod() { - return new Vod(getJumpId(), getTitle(), getThumbnail(), getMask()); + public List getDataList() { + return dataList == null ? Collections.emptyList() : dataList; + } + + public Vod homeVod(String imgDomain) { + return new Vod(getJumpId(), getTitle(), getThumbnail(imgDomain)); + } + + public Vod vod(String imgDomain) { + return new Vod(getId(), getTitle(), getThumbnail(imgDomain), getMask()); } public String getValues(List items, boolean link) { @@ -94,12 +111,6 @@ public class Data { return Util.substring(sb.toString()); } - public String getPlayUrl() { - StringBuilder sb = new StringBuilder(); - for (BtboDown value : getBtboDownlist()) sb.append(value.getVal()).append("#"); - return Util.substring(sb.toString()); - } - public static class Value { @SerializedName(value = "title", alternate = "name") @@ -118,13 +129,51 @@ public class Data { } } - public static class BtboDown { + public static class SourceListSource { - @SerializedName("val") - private String val; + @SerializedName("name") + private String name; + @SerializedName("source_list") + private List list; - public String getVal() { - return TextUtils.isEmpty(val) ? "" : val.replaceAll("ftp", "tvbox-xg:ftp"); + public String getName() { + return TextUtils.isEmpty(name) ? "" : name; + } + + public List getList() { + return list == null ? Collections.emptyList() : list; } } -} + + public static class SourceList { + + @SerializedName("source_name") + private String name; + @SerializedName("url") + private String url; + + public String getName() { + return TextUtils.isEmpty(name) ? "" : name; + } + + public String getUrl() { + return TextUtils.isEmpty(url) ? "" : url.replaceAll("ftp", "tvbox-xg:ftp"); + } + } + + public String getVodFrom() { + List items = new ArrayList<>(); + for (SourceListSource source : getSource()) items.add(source.getName()); + return TextUtils.join("$$$", items); + } + + public String getVodUrl() { + List items = new ArrayList<>(); + for (SourceListSource source : getSource()) { + List urls = new ArrayList<>(); + for (SourceList item : source.getList()) urls.add(item.getName() + "$" + item.getUrl()); + items.add(TextUtils.join("#", urls)); + } + return TextUtils.join("$$$", items); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/bean/jianpian/Detail.java b/app/src/main/java/com/github/catvod/bean/jianpian/Detail.java index 4ab7bc71..4ba05a18 100644 --- a/app/src/main/java/com/github/catvod/bean/jianpian/Detail.java +++ b/app/src/main/java/com/github/catvod/bean/jianpian/Detail.java @@ -15,4 +15,4 @@ public class Detail { public Data getData() { return data == null ? new Data() : data; } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/bean/jianpian/Resp.java b/app/src/main/java/com/github/catvod/bean/jianpian/Resp.java index d21de026..ef88c8b2 100644 --- a/app/src/main/java/com/github/catvod/bean/jianpian/Resp.java +++ b/app/src/main/java/com/github/catvod/bean/jianpian/Resp.java @@ -18,4 +18,4 @@ public class Resp { public List getData() { return data == null ? Collections.emptyList() : data; } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/bean/jianpian/Search.java b/app/src/main/java/com/github/catvod/bean/jianpian/Search.java new file mode 100644 index 00000000..d623af79 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/jianpian/Search.java @@ -0,0 +1,52 @@ +package com.github.catvod.bean.jianpian; + +import android.text.TextUtils; + +import com.github.catvod.bean.Vod; +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.util.Collections; +import java.util.List; + +public class Search { + + @SerializedName("data") + private List data; + @SerializedName("id") + private String id; + @SerializedName(value = "thumbnail", alternate = "path") + private String thumbnail; + @SerializedName("title") + private String title; + @SerializedName("mask") + private String mask; + + public static Search objectFrom(String str) { + return new Gson().fromJson(str, Search.class); + } + + public String getId() { + return TextUtils.isEmpty(id) ? "" : id; + } + + public String getThumbnail(String imgDomain) { + return TextUtils.isEmpty(thumbnail) ? "" : "http://" + imgDomain + thumbnail; + } + + public String getTitle() { + return TextUtils.isEmpty(title) ? "" : title; + } + + public String getMask() { + return TextUtils.isEmpty(mask) ? "" : mask; + } + + public Vod vod(String imgDomain) { + return new Vod(getId(), getTitle(), getThumbnail(imgDomain), getMask()); + } + + public List getData() { + return data == null ? Collections.emptyList() : data; + } +} diff --git a/app/src/main/java/com/github/catvod/bean/mqitv/Config.java b/app/src/main/java/com/github/catvod/bean/mqitv/Config.java new file mode 100644 index 00000000..29ef9e38 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/mqitv/Config.java @@ -0,0 +1,124 @@ +package com.github.catvod.bean.mqitv; + +import android.net.Uri; + +import androidx.annotation.Nullable; + +import com.github.catvod.net.OkHttp; +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Config { + + @SerializedName("name") + private String name; + @SerializedName("url") + private String url; + + private List users; + private List data; + private Uri uri; + + public static List arrayFrom(String str) { + Type listType = new TypeToken>() {}.getType(); + return new Gson().fromJson(str, listType); + } + + public Config(String url) { + this.url = url; + } + + public String getName() { + return name == null ? "" : name; + } + + public String getUrl() { + return url == null ? "" : url; + } + + public List getUsers() { + return users = users == null ? new ArrayList<>() : users; + } + + public List getData() { + return data = data == null ? Data.objectFrom(OkHttp.string(getApi(), 3000)).getData() : data; + } + + public Uri getUri() { + return uri = uri == null ? Uri.parse(getUrl()) : uri; + } + + public String getApi() { + return getUrl() + "/api/post?item=itv_traffic"; + } + + public String getPlayUrl(String port, String playing) { + return "http://" + getUri().getHost() + ":" + port + "/" + playing.replace(":/", ""); + } + + public void loadUser() { + Pattern userPattern = Pattern.compile(".*?([0-9a-zA-Z]{11,}).*", Pattern.CASE_INSENSITIVE); + Pattern macPattern = Pattern.compile(".*?(([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}).*", Pattern.CASE_INSENSITIVE); + for (Data item : getData()) { + for (String userIp : item.getStat().getUserIpList()) { + if (getUsers().size() >= 5) continue; + Matcher userMatcher = userPattern.matcher(userIp); + Matcher macMatcher = macPattern.matcher(userIp); + String user = userMatcher.matches() ? userMatcher.group(1) : ""; + String mac = macMatcher.matches() ? macMatcher.group(1) : ""; + if (!user.isEmpty() && !mac.isEmpty()) { + User u = new User(user, mac).getToken(getUrl()); + if (!u.getToken().isEmpty()) getUsers().add(u); + } + } + } + } + + public User getUser() { + if (getUsers().isEmpty()) loadUser(); + return getUsers().isEmpty() ? new User("", "") : getUsers().get(ThreadLocalRandom.current().nextInt(getUsers().size())); + } + + public String getAuth(String id, String token) { + String data = OkHttp.string(getUrl() + "/ualive?cid=" + id + "&token=" + token); + Matcher matcher = Pattern.compile("\"Reason\":\"(.*?)\"", Pattern.CASE_INSENSITIVE).matcher(data); + if (matcher.find()) return matcher.group(1); + return ""; + } + + public String getM3U8(String id, String token, String port) { + String base = "http://" + getUri().getHost() + ":" + port + "/"; + String m3u8 = OkHttp.string(base + id + ".m3u8?token=" + token); + if (m3u8.isEmpty() || m3u8.contains("\"Reason\"")) return ""; + String[] lines = m3u8.split("\\r?\\n"); + StringBuilder sb = new StringBuilder(); + for (String line : lines) { + if (!line.startsWith("#") && !line.startsWith("http")) line = base + line; + sb.append(line).append("\n"); + } + return sb.toString(); + } + + public void clear() { + this.data.clear(); + this.users.clear(); + this.data = null; + this.users = null; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) return true; + if (!(obj instanceof Config)) return false; + Config it = (Config) obj; + return getUrl().equals(it.getUrl()); + } +} diff --git a/app/src/main/java/com/github/catvod/bean/mqitv/Data.java b/app/src/main/java/com/github/catvod/bean/mqitv/Data.java new file mode 100644 index 00000000..d0015e65 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/mqitv/Data.java @@ -0,0 +1,56 @@ +package com.github.catvod.bean.mqitv; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.util.Collections; +import java.util.List; + +public class Data { + + @SerializedName("data") + private List data; + @SerializedName("id") + private String id; + @SerializedName("name") + private String name; + @SerializedName("playing") + private String playing; + @SerializedName("port") + private String port; + @SerializedName("stat") + private Stat stat; + + public static Data objectFrom(String str) { + try { + Data data = new Gson().fromJson(str, Data.class); + return data == null ? new Data() : data; + } catch (Exception e) { + return new Data(); + } + } + + public List getData() { + return data == null ? Collections.emptyList() : data; + } + + public String getId() { + return id == null ? "" : id; + } + + public String getName() { + return name == null ? "" : name; + } + + public String getPort() { + return port == null ? "" : port; + } + + public String getPlaying() { + return playing == null ? "" : playing; + } + + public Stat getStat() { + return stat == null ? new Stat() : stat; + } +} diff --git a/app/src/main/java/com/github/catvod/bean/mqitv/Stat.java b/app/src/main/java/com/github/catvod/bean/mqitv/Stat.java new file mode 100644 index 00000000..c72e9e87 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/mqitv/Stat.java @@ -0,0 +1,16 @@ +package com.github.catvod.bean.mqitv; + +import com.google.gson.annotations.SerializedName; + +import java.util.Collections; +import java.util.List; + +public class Stat { + + @SerializedName("UserIpList") + private List userIpList; + + public List getUserIpList() { + return userIpList == null ? Collections.emptyList() : userIpList; + } +} diff --git a/app/src/main/java/com/github/catvod/bean/mqitv/User.java b/app/src/main/java/com/github/catvod/bean/mqitv/User.java new file mode 100644 index 00000000..25a18bdf --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/mqitv/User.java @@ -0,0 +1,39 @@ +package com.github.catvod.bean.mqitv; + +import com.github.catvod.net.OkHttp; + +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class User { + + private String id; + private String mac; + private String token; + + public User(String id, String mac) { + this.id = id; + this.mac = mac; + } + + public String getId() { + return id; + } + + public String getMac() { + return mac; + } + + public String getToken() { + return token == null ? "" : token; + } + + public User getToken(String url) { + String result = OkHttp.string(String.format(Locale.getDefault(), "%s/HSAndroidLogin.ecgi?ty=json&net_account=%s&mac_address1=%s&_=%d", url, getId(), getMac(), System.currentTimeMillis())); + Pattern pattern = Pattern.compile("\"Token\"\\s*:\\s*\"(.*?)\"", Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(result); + token = matcher.find() ? matcher.group(1) : ""; + return this; + } +} diff --git a/app/src/main/java/com/github/catvod/bean/xpath/Rule.java b/app/src/main/java/com/github/catvod/bean/xpath/Rule.java deleted file mode 100644 index 78c9f326..00000000 --- a/app/src/main/java/com/github/catvod/bean/xpath/Rule.java +++ /dev/null @@ -1,695 +0,0 @@ -package com.github.catvod.bean.xpath; - -import com.github.catvod.crawler.SpiderDebug; - -import org.json.JSONObject; - -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Rule { - /** - * user-agent - */ - private String ua; - /** - * 取得分類和首頁推薦的Url - */ - private String homeUrl; - /** - * 分類節點 xpath - */ - private String cateNode; - /** - * 分類節點名 xpath - */ - private String cateName; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern cateNameR; - /** - * 分類節點 id xpath - */ - private String cateId; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern cateIdR; - /** - * 手動指定分類如果有則不從 homeUrl 中獲取分類 - */ - private final LinkedHashMap cateManual = new LinkedHashMap<>(); - - /** - * 篩選 - */ - private JSONObject filter; - - /** - * 更新推薦影片節點 xpath - */ - private String homeVodNode; - /** - * 更新推薦影片名稱 xpath - */ - private String homeVodName; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern homeVodNameR; - /** - * 更新推薦影片 id xpath - */ - private String homeVodId; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern homeVodIdR; - /** - * 更新推薦影片圖片 xpath - */ - private String homeVodImg; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern homeVodImgR; - /** - * 更新推薦影片簡介 xpath - */ - private String homeVodMark; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern homeVodMarkR; - /** - * 分類頁地址 - */ - private String cateUrl; - /** - * 分類頁影片節點 xpath - */ - private String cateVodNode; - /** - * 分類頁影片名稱 xpath - */ - private String cateVodName; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern cateVodNameR; - /** - * 分類頁影片影片id xpath - */ - private String cateVodId; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern cateVodIdR; - /** - * 分類頁影片影片圖片 xpath - */ - private String cateVodImg; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern cateVodImgR; - /** - * 分類頁影片影片簡介 xpath - */ - private String cateVodMark; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern cateVodMarkR; - - /** - * 詳情頁面 - */ - private String dtUrl; - /** - * 詳情節點 xpath - */ - private String dtNode; - /** - * 詳情影片 xpath - */ - private String dtName; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtNameR; - /** - * 詳情影片圖片 xpath - */ - private String dtImg; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtImgR; - /** - * 詳情影片分類 xpath - */ - private String dtCate; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtCateR; - /** - * 詳情影片年份 xpath - */ - private String dtYear; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtYearR; - /** - * 詳情影片地區 xpath - */ - private String dtArea; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtAreaR; - /** - * 詳情影片簡介 xpath - */ - private String dtMark; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtMarkR; - /** - * 詳情演員 xpath - */ - private String dtActor; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtActorR; - /** - * 詳情導演 xpath - */ - private String dtDirector; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtDirectorR; - /** - * 詳情說明 xpath - */ - private String dtDesc; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern dtDescR; - - /** - * 詳情播放來源節點 - */ - private String dtFromNode; - /** - * 詳情播放來源名稱 xpath - */ - private String dtFromName; - /** - * 詳情 - */ - private Pattern dtFromNameR; - /** - * 詳情播放地址列表節點 xpath - */ - private String dtUrlNode; - /** - * 詳情播放地址節點 xpath - */ - private String dtUrlSubNode; - /** - * 詳情播放地址id xpath - */ - private String dtUrlId; - /** - * 詳情 - */ - private Pattern dtUrlIdR; - /** - * 詳情播放地址名稱 xpath - */ - private String dtUrlName; - /** - * 詳情 - */ - private Pattern dtUrlNameR; - /** - * 播放頁面url - */ - private String playUrl; - /** - * 播放解析調用ua - */ - private String playUa; - /** - * 播放解析調用referer - */ - private String playReferer; - - /** - * 搜尋頁地址 - */ - private String searchUrl; - - /** - * 搜尋頁影片節點 xpath - */ - private String scVodNode; - /** - * 搜尋頁影片名稱 xpath - */ - private String scVodName; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern scVodNameR; - /** - * 搜尋頁影片id xpath - */ - private String scVodId; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern scVodIdR; - /** - * 搜尋頁影片圖片 xpath - */ - private String scVodImg; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern scVodImgR; - /** - * 搜尋頁影片簡介 xpath - */ - private String scVodMark; - /** - * 正則對取到的數據進行二次處理 - */ - private Pattern scVodMarkR; - - private static Pattern getPattern(JSONObject json, String key) { - String v = json.optString(key).trim(); - if (v.isEmpty()) - return null; - else { - try { - return Pattern.compile(v); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - return null; - } - - private static String doReplaceRegex(Pattern pattern, String src) { - if (pattern == null) - return src; - try { - Matcher matcher = pattern.matcher(src); - if (matcher.find()) { - return matcher.group(1).trim(); - } - } catch (Exception e) { - SpiderDebug.log(e); - } - return src; - } - - public static Rule fromJson(String json) { - try { - JSONObject jsonObj = new JSONObject(json); - Rule rule = new Rule(); - rule.ua = jsonObj.optString("ua"); - rule.homeUrl = jsonObj.optString("homeUrl").trim(); - rule.cateNode = jsonObj.optString("cateNode").trim(); - rule.cateName = jsonObj.optString("cateName").trim(); - rule.cateNameR = getPattern(jsonObj, "cateNameR"); - rule.cateId = jsonObj.optString("cateId").trim(); - rule.cateIdR = getPattern(jsonObj, "cateIdR"); - JSONObject navs = jsonObj.optJSONObject("cateManual"); - if (navs != null) { - Iterator keys = navs.keys(); - while (keys.hasNext()) { - String name = keys.next(); - rule.cateManual.put(name.trim(), navs.getString(name).trim()); - } - } - rule.filter = jsonObj.optJSONObject("filter"); - rule.homeVodNode = jsonObj.optString("homeVodNode").trim(); - rule.homeVodName = jsonObj.optString("homeVodName").trim(); - rule.homeVodNameR = getPattern(jsonObj, "homeVodNameR"); - rule.homeVodId = jsonObj.optString("homeVodId").trim(); - rule.homeVodIdR = getPattern(jsonObj, "homeVodIdR"); - rule.homeVodImg = jsonObj.optString("homeVodImg").trim(); - rule.homeVodImgR = getPattern(jsonObj, "homeVodImgR"); - rule.homeVodMark = jsonObj.optString("homeVodMark").trim(); - rule.homeVodMarkR = getPattern(jsonObj, "homeVodMarkR"); - rule.cateUrl = jsonObj.optString("cateUrl").trim(); - rule.cateVodNode = jsonObj.optString("cateVodNode").trim(); - rule.cateVodName = jsonObj.optString("cateVodName").trim(); - rule.cateVodNameR = getPattern(jsonObj, "cateVodNameR"); - rule.cateVodId = jsonObj.optString("cateVodId").trim(); - rule.cateVodIdR = getPattern(jsonObj, "cateVodIdR"); - rule.cateVodImg = jsonObj.optString("cateVodImg").trim(); - rule.cateVodImgR = getPattern(jsonObj, "cateVodImgR"); - rule.cateVodMark = jsonObj.optString("cateVodMark").trim(); - rule.cateVodMarkR = getPattern(jsonObj, "cateVodMarkR"); - rule.dtUrl = jsonObj.optString("dtUrl"); - rule.dtNode = jsonObj.optString("dtNode"); - rule.dtName = jsonObj.optString("dtName"); - rule.dtNameR = getPattern(jsonObj, "dtNameR"); - rule.dtImg = jsonObj.optString("dtImg"); - rule.dtImgR = getPattern(jsonObj, "dtImgR"); - rule.dtCate = jsonObj.optString("dtCate"); - rule.dtCateR = getPattern(jsonObj, "dtCateR"); - rule.dtYear = jsonObj.optString("dtYear"); - rule.dtYearR = getPattern(jsonObj, "dtYearR"); - rule.dtArea = jsonObj.optString("dtArea"); - rule.dtAreaR = getPattern(jsonObj, "dtAreaR"); - rule.dtMark = jsonObj.optString("dtMark"); - rule.dtMarkR = getPattern(jsonObj, "dtMarkR"); - rule.dtActor = jsonObj.optString("dtActor"); - rule.dtActorR = getPattern(jsonObj, "dtActorR"); - rule.dtDirector = jsonObj.optString("dtDirector"); - rule.dtDirectorR = getPattern(jsonObj, "dtDirectorR"); - rule.dtDesc = jsonObj.optString("dtDesc"); - rule.dtDescR = getPattern(jsonObj, "dtDescR"); - rule.dtFromNode = jsonObj.optString("dtFromNode"); - rule.dtFromName = jsonObj.optString("dtFromName"); - rule.dtFromNameR = getPattern(jsonObj, "dtFromNameR"); - rule.dtUrlNode = jsonObj.optString("dtUrlNode"); - rule.dtUrlSubNode = jsonObj.optString("dtUrlSubNode"); - rule.dtUrlId = jsonObj.optString("dtUrlId"); - rule.dtUrlIdR = getPattern(jsonObj, "dtUrlIdR"); - rule.dtUrlName = jsonObj.optString("dtUrlName"); - rule.dtUrlNameR = getPattern(jsonObj, "dtUrlNameR"); - rule.playUrl = jsonObj.optString("playUrl"); - rule.playUa = jsonObj.optString("playUa"); - rule.playReferer = jsonObj.optString("playReferer"); - rule.searchUrl = jsonObj.optString("searchUrl"); - rule.scVodNode = jsonObj.optString("scVodNode").trim(); - rule.scVodName = jsonObj.optString("scVodName").trim(); - rule.scVodNameR = getPattern(jsonObj, "scVodNameR"); - rule.scVodId = jsonObj.optString("scVodId").trim(); - rule.scVodIdR = getPattern(jsonObj, "scVodIdR"); - rule.scVodImg = jsonObj.optString("scVodImg").trim(); - rule.scVodImgR = getPattern(jsonObj, "scVodImgR"); - rule.scVodMark = jsonObj.optString("scVodMark").trim(); - rule.scVodMarkR = getPattern(jsonObj, "scVodMarkR"); - return rule; - } catch (Exception e) { - SpiderDebug.log(e); - } - return null; - } - - public String getUa() { - return ua; - } - - public String getHomeUrl() { - return homeUrl; - } - - public String getCateNode() { - return cateNode; - } - - public String getCateName() { - return cateName; - } - - public String getCateNameR(String src) { - return doReplaceRegex(cateNameR, src); - } - - public String getCateId() { - return cateId; - } - - public String getCateIdR(String src) { - return doReplaceRegex(cateIdR, src); - } - - public LinkedHashMap getCateManual() { - return cateManual; - } - - public JSONObject getFilter() { - return filter; - } - - public String getHomeVodNode() { - return homeVodNode; - } - - public String getHomeVodName() { - return homeVodName; - } - - public String getHomeVodNameR(String src) { - return doReplaceRegex(homeVodNameR, src); - } - - public String getHomeVodId() { - return homeVodId; - } - - public String getHomeVodIdR(String src) { - return doReplaceRegex(homeVodIdR, src); - } - - public String getHomeVodImg() { - return homeVodImg; - } - - public String getHomeVodImgR(String src) { - return doReplaceRegex(homeVodImgR, src); - } - - public String getHomeVodMark() { - return homeVodMark; - } - - public String getHomeVodMarkR(String src) { - return doReplaceRegex(homeVodMarkR, src); - } - - public String getCateUrl() { - return cateUrl; - } - - public String getCateVodNode() { - return cateVodNode; - } - - public String getCateVodName() { - return cateVodName; - } - - public String getCateVodNameR(String src) { - return doReplaceRegex(cateVodNameR, src); - } - - public String getCateVodId() { - return cateVodId; - } - - public String getCateVodIdR(String src) { - return doReplaceRegex(cateVodIdR, src); - } - - public String getCateVodImg() { - return cateVodImg; - } - - public String getCateVodImgR(String src) { - return doReplaceRegex(cateVodImgR, src); - } - - public String getCateVodMark() { - return cateVodMark; - } - - public String getCateVodMarkR(String src) { - return doReplaceRegex(cateVodNameR, src); - } - - public String getDetailUrl() { - return dtUrl; - } - - public String getDetailNode() { - return dtNode; - } - - public String getDetailName() { - return dtName; - } - - public String getDetailNameR(String src) { - return doReplaceRegex(dtNameR, src); - } - - public String getDetailImg() { - return dtImg; - } - - public String getDetailImgR(String src) { - return doReplaceRegex(dtImgR, src); - } - - public String getDetailCate() { - return dtCate; - } - - public String getDetailCateR(String src) { - return doReplaceRegex(dtCateR, src); - } - - public String getDetailYear() { - return dtYear; - } - - public String getDetailYearR(String src) { - return doReplaceRegex(dtYearR, src); - } - - public String getDetailArea() { - return dtArea; - } - - public String getDetailAreaR(String src) { - return doReplaceRegex(dtAreaR, src); - } - - public String getDetailMark() { - return dtMark; - } - - public String getDetailMarkR(String src) { - return doReplaceRegex(dtMarkR, src); - } - - public String getDetailActor() { - return dtActor; - } - - public String getDetailActorR(String src) { - return doReplaceRegex(dtActorR, src); - } - - public String getDetailDirector() { - return dtDirector; - } - - public String getDetailDirectorR(String src) { - return doReplaceRegex(dtDirectorR, src); - } - - public String getDetailDesc() { - return dtDesc; - } - - public String getDetailDescR(String src) { - return doReplaceRegex(dtDescR, src); - } - - public String getDetailFromNode() { - return dtFromNode; - } - - public String getDetailFromName() { - return dtFromName; - } - - public String getDetailFromNameR(String src) { - return doReplaceRegex(dtFromNameR, src); - } - - public String getDetailUrlNode() { - return dtUrlNode; - } - - public String getDetailUrlSubNode() { - return dtUrlSubNode; - } - - public String getDetailUrlId() { - return dtUrlId; - } - - public String getDetailUrlIdR(String src) { - return doReplaceRegex(dtUrlIdR, src); - } - - public String getDetailUrlName() { - return dtUrlName; - } - - public String getDetailUrlNameR(String src) { - return doReplaceRegex(dtUrlNameR, src); - } - - public String getPlayUrl() { - return playUrl; - } - - public String getPlayUa() { - return playUa; - } - - public String getPlayReferer() { - return playReferer; - } - - public String getSearchUrl() { - return searchUrl; - } - - public String getSearchVodNode() { - return scVodNode; - } - - public String getSearchVodName() { - return scVodName; - } - - public String getSearchVodNameR(String src) { - return doReplaceRegex(scVodNameR, src); - } - - public String getSearchVodId() { - return scVodId; - } - - public String getSearchVodIdR(String src) { - return doReplaceRegex(scVodIdR, src); - } - - public String getSearchVodImg() { - return scVodImg; - } - - public String getSearchVodImgR(String src) { - return doReplaceRegex(scVodImgR, src); - } - - public String getSearchVodMark() { - return scVodMark; - } - - public String getSearchVodMarkR(String src) { - return doReplaceRegex(scVodMarkR, src); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/debug/MainActivity.java b/app/src/main/java/com/github/catvod/debug/MainActivity.java deleted file mode 100644 index e394b18f..00000000 --- a/app/src/main/java/com/github/catvod/debug/MainActivity.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.github.catvod.debug; - -import android.app.Activity; -import android.os.Bundle; -import android.widget.Button; - -import com.github.catvod.R; -import com.github.catvod.crawler.Spider; -import com.github.catvod.spider.Init; -import com.github.catvod.spider.PTT; -import com.orhanobut.logger.AndroidLogAdapter; -import com.orhanobut.logger.Logger; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class MainActivity extends Activity { - - private ExecutorService executor; - private Spider spider; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - Button homeContent = findViewById(R.id.homeContent); - Button homeVideoContent = findViewById(R.id.homeVideoContent); - Button categoryContent = findViewById(R.id.categoryContent); - Button detailContent = findViewById(R.id.detailContent); - Button playerContent = findViewById(R.id.playerContent); - Button searchContent = findViewById(R.id.searchContent); - homeContent.setOnClickListener(view -> executor.execute(this::homeContent)); - homeVideoContent.setOnClickListener(view -> executor.execute(this::homeVideoContent)); - categoryContent.setOnClickListener(view -> executor.execute(this::categoryContent)); - detailContent.setOnClickListener(view -> executor.execute(this::detailContent)); - playerContent.setOnClickListener(view -> executor.execute(this::playerContent)); - searchContent.setOnClickListener(view -> executor.execute(this::searchContent)); - Logger.addLogAdapter(new AndroidLogAdapter()); - executor = Executors.newCachedThreadPool(); - executor.execute(this::initSpider); - } - - private void initSpider() { - try { - Init.init(getApplicationContext()); - spider = new PTT(); - spider.init(this, ""); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public void homeContent() { - try { - Logger.t("homeContent").d(spider.homeContent(true)); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public void homeVideoContent() { - try { - Logger.t("homeVideoContent").d(spider.homeVideoContent()); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public void categoryContent() { - try { - HashMap extend = new HashMap<>(); - extend.put("c", "19"); - extend.put("year", "2024"); - Logger.t("categoryContent").d(spider.categoryContent("3", "2", true, extend)); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public void detailContent() { - try { - Logger.t("detailContent").d(spider.detailContent(Arrays.asList("78702"))); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public void playerContent() { - try { - Logger.t("playerContent").d(spider.playerContent("", "382044/1/78", new ArrayList<>())); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - public void searchContent() { - try { - Logger.t("searchContent").d(spider.searchContent("我的人间烟火", false)); - } catch (Throwable e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/js/Function.java b/app/src/main/java/com/github/catvod/js/Function.java index ffb9e330..1bb2978e 100644 --- a/app/src/main/java/com/github/catvod/js/Function.java +++ b/app/src/main/java/com/github/catvod/js/Function.java @@ -1,7 +1,7 @@ package com.github.catvod.js; -import com.github.catvod.js.utils.Parser; import com.github.catvod.js.utils.JSUtil; +import com.github.catvod.js.utils.Parser; import com.whl.quickjs.wrapper.JSArray; import com.whl.quickjs.wrapper.JSMethod; import com.whl.quickjs.wrapper.QuickJSContext; diff --git a/app/src/main/java/com/github/catvod/net/OkHttp.java b/app/src/main/java/com/github/catvod/net/OkHttp.java index 2dc492a0..895e54ec 100644 --- a/app/src/main/java/com/github/catvod/net/OkHttp.java +++ b/app/src/main/java/com/github/catvod/net/OkHttp.java @@ -24,6 +24,8 @@ import okhttp3.Response; public class OkHttp { + private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(15); + public static final String POST = "POST"; public static final String GET = "GET"; @@ -37,28 +39,28 @@ public class OkHttp { return Loader.INSTANCE; } - public static Response newCall(Request request) throws IOException { - return client().newCall(request).execute(); - } - public static Response newCall(String url) throws IOException { return client().newCall(new Request.Builder().url(url).build()).execute(); } - public static Response newCall(String url, Map header) throws IOException { - return client().newCall(new Request.Builder().url(url).headers(Headers.of(header)).build()).execute(); - } - public static String string(String url) { return string(url, null); } + public static String string(String url, long timeout) { + return string(url, null, null, timeout); + } + public static String string(String url, Map header) { return string(url, null, header); } public static String string(String url, Map params, Map header) { - return url.startsWith("http") ? new OkRequest(GET, url, params, header).execute(client()).getBody() : ""; + return new OkRequest(GET, url, params, header).execute(client()).getBody(); + } + + public static String string(String url, Map params, Map header, long timeout) { + return new OkRequest(GET, url, params, header).execute(client(timeout)).getBody(); } public static String post(String url, Map params) { @@ -94,7 +96,11 @@ public class OkHttp { } private static OkHttpClient.Builder getBuilder() { - return new OkHttpClient.Builder().dns(safeDns()).connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).hostnameVerifier((hostname, session) -> true).sslSocketFactory(getSSLContext().getSocketFactory(), trustAllCertificates()); + return new OkHttpClient.Builder().dns(safeDns()).connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS).readTimeout(TIMEOUT, TimeUnit.MILLISECONDS).writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS).hostnameVerifier((hostname, session) -> true).sslSocketFactory(getSSLContext().getSocketFactory(), trustAllCertificates()); + } + + private static OkHttpClient client(long timeout) { + return client().newBuilder().connectTimeout(timeout, TimeUnit.MILLISECONDS).readTimeout(timeout, TimeUnit.MILLISECONDS).writeTimeout(timeout, TimeUnit.MILLISECONDS).build(); } private static OkHttpClient client() { diff --git a/app/src/main/java/com/github/catvod/net/OkRequest.java b/app/src/main/java/com/github/catvod/net/OkRequest.java index 004add5c..0a01fe22 100644 --- a/app/src/main/java/com/github/catvod/net/OkRequest.java +++ b/app/src/main/java/com/github/catvod/net/OkRequest.java @@ -2,6 +2,7 @@ package com.github.catvod.net; import android.text.TextUtils; +import com.github.catvod.crawler.SpiderDebug; import com.github.catvod.utils.Util; import java.io.IOException; @@ -37,10 +38,10 @@ class OkRequest { this.method = method; this.params = params; this.header = header; - getInstance(); + this.buildRequest(); } - private void getInstance() { + private void buildRequest() { Request.Builder builder = new Request.Builder(); if (method.equals(OkHttp.GET) && params != null) setParams(); if (method.equals(OkHttp.POST)) builder.post(getRequestBody()); @@ -62,10 +63,10 @@ class OkRequest { } public OkResult execute(OkHttpClient client) { - try { - Response response = client.newCall(request).execute(); - return new OkResult(response.code(), response.body().string(), response.headers().toMultimap()); + try (Response res = client.newCall(request).execute()) { + return new OkResult(res.code(), res.body().string(), res.headers().toMultimap()); } catch (IOException e) { + SpiderDebug.log(e); return new OkResult(); } } diff --git a/app/src/main/java/com/github/catvod/spider/AList.java b/app/src/main/java/com/github/catvod/spider/AList.java index 9cf76529..7fc23410 100644 --- a/app/src/main/java/com/github/catvod/spider/AList.java +++ b/app/src/main/java/com/github/catvod/spider/AList.java @@ -18,9 +18,6 @@ import com.github.catvod.net.OkHttp; import com.github.catvod.utils.Util; import org.json.JSONObject; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; import java.util.ArrayList; import java.util.Arrays; @@ -270,29 +267,6 @@ public class AList extends Spider { @Override public List call() { - List alist = alist(); - return !alist.isEmpty() ? alist : xiaoya(); - } - - private List xiaoya() { - List list = new ArrayList<>(); - Document doc = Jsoup.parse(OkHttp.string(drive.searchApi(keyword))); - for (Element a : doc.select("ul > a")) { - String[] splits = a.text().split("#"); - if (!splits[0].contains("/")) continue; - int index = splits[0].lastIndexOf("/"); - boolean file = Util.isMedia(splits[0]); - Item item = new Item(); - item.setType(file ? 0 : 1); - item.setThumb(splits.length > 3 ? splits[4] : ""); - item.setPath("/" + splits[0].substring(0, index)); - item.setName(splits[0].substring(index + 1)); - list.add(item.getVod(drive)); - } - return list; - } - - private List alist() { try { List list = new ArrayList<>(); String response = post(drive, drive.searchApi(), drive.params(keyword)); diff --git a/app/src/main/java/com/github/catvod/spider/Bili.java b/app/src/main/java/com/github/catvod/spider/Bili.java index b1923981..2d6f02ad 100644 --- a/app/src/main/java/com/github/catvod/spider/Bili.java +++ b/app/src/main/java/com/github/catvod/spider/Bili.java @@ -198,7 +198,7 @@ public class Bili extends Spider { String dan = "https://api.bilibili.com/x/v1/dm/list.so?oid=".concat(cid); for (int i = 0; i < acceptDesc.length; i++) { url.add(acceptDesc[i]); - url.add(Proxy.getUrl() + "?do=bili" + "&aid=" + aid + "&cid=" + cid + "&qn=" + acceptQuality[i] + "&type=mpd"); + url.add("proxy://do=bili" + "&aid=" + aid + "&cid=" + cid + "&qn=" + acceptQuality[i] + "&type=mpd"); } return Result.get().url(url).danmaku(Arrays.asList(Danmaku.create().name("B站").url(dan))).dash().header(getHeader()).string(); } diff --git a/app/src/main/java/com/github/catvod/spider/Hanime.java b/app/src/main/java/com/github/catvod/spider/Hanime.java deleted file mode 100644 index c03a05c5..00000000 --- a/app/src/main/java/com/github/catvod/spider/Hanime.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.github.catvod.spider; - -import com.github.catvod.bean.Class; -import com.github.catvod.bean.Filter; -import com.github.catvod.bean.Result; -import com.github.catvod.bean.Vod; -import com.github.catvod.crawler.Spider; -import com.github.catvod.net.OkHttp; -import com.github.catvod.utils.Util; - -import org.json.JSONObject; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -public class Hanime extends Spider { - - private static final String siteUrl = "https://hanime1.me"; - - private HashMap getHeaders() { - HashMap headers = new HashMap<>(); - headers.put("User-Agent", Util.CHROME); - return headers; - } - - private Filter getFilter(String name, String key, List texts) { - List values = new ArrayList<>(); - if (!key.equals("by")) values.add(new Filter.Value("全部", "")); - for (String text : texts) { - if (text.isEmpty()) continue; - values.add(new Filter.Value(text)); - } - return new Filter(key, name, values); - } - - @Override - public String homeContent(boolean filter) throws Exception { - List list = new ArrayList<>(); - List classes = new ArrayList<>(); - LinkedHashMap> filters = new LinkedHashMap<>(); - Document doc1 = Jsoup.parse(OkHttp.string(siteUrl.concat("/search?genre=裏番"), getHeaders())); - List sorts = doc1.select("div.hentai-sort-options-wrapper").eachText(); - List years = doc1.getElementById("year").select("option").eachAttr("value"); - Document doc2 = Jsoup.parse(OkHttp.string(siteUrl, getHeaders())); - for (Element element : doc2.select("a.nav-item")) { - String text = element.text(); - if (text.equals("新番預告") || text.equals("H漫畫")) continue; - classes.add(new Class(text)); - List array = new ArrayList<>(); - array.add(getFilter("排序", "by", sorts)); - array.add(getFilter("年份", "year", years)); - filters.put(text, array); - } - for (Element element : doc2.select("a")) { - if (element.attr("href").contains("watch")) { - String pic = element.select("div > img").attr("src"); - String url = element.attr("href"); - String name = element.select("div > div").text(); - String id = url.split("=")[1]; - if (name.contains("smart_display") || name.isEmpty()) continue; - list.add(new Vod(id, name, pic)); - } - } - return Result.string(classes, list, filters); - } - - @Override - public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception { - List list = new ArrayList<>(); - if (extend.get("by") == null) extend.put("by", "最新上市"); - if (extend.get("year") == null) extend.put("year", ""); - String target = siteUrl.concat("/search?genre=").concat(tid).concat("&page=").concat(pg).concat("&sort=").concat(extend.get("by")).concat("&year=").concat(extend.get("year")); - Document doc = Jsoup.parse(OkHttp.string(target, getHeaders())); - for (Element element : doc.select("div.col-xs-6")) { - String pic = element.select("img").get(1).attr("src"); - String url = element.select("a.overlay").attr("href"); - String name = element.select("div.card-mobile-title").text(); - String id = url.split("=")[1]; - list.add(new Vod(id, name, pic)); - } - if (list.isEmpty()) { - for (Element element : doc.select("a")) { - if (element.attr("href").contains("watch")) { - String pic = element.select("div > img").attr("src"); - String url = element.attr("href"); - String name = element.select("div > div").text(); - String id = url.split("=")[1]; - if (name.contains("smart_display")) continue; - list.add(new Vod(id, name, pic)); - } - } - } - return Result.string(list); - } - - @Override - public String detailContent(List ids) throws Exception { - Document doc = Jsoup.parse(OkHttp.string(siteUrl.concat("/watch?v=").concat(ids.get(0)), getHeaders())); - String name = doc.getElementById("shareBtn-title").text(); - JSONObject json = new JSONObject(doc.select("script[type=application/ld+json]").html().trim()); - String content = json.optString("description"); - String pic = json.optJSONArray("thumbnailUrl").optString(0); - String url = json.optString("contentUrl");; - Vod vod = new Vod(); - vod.setVodId(ids.get(0)); - vod.setVodPic(pic); - vod.setVodName(name); - vod.setVodContent(content); - vod.setVodPlayFrom("Hanime1"); - vod.setVodPlayUrl("播放$" + url); - return Result.string(vod); - } - - @Override - public String searchContent(String key, boolean quick) throws Exception { - List list = new ArrayList<>(); - String target = siteUrl.concat("/search?query=").concat(key).concat("&genre=&sort=&year=&month=&duration="); - Document doc = Jsoup.parse(OkHttp.string(target, getHeaders())); - for (Element element : doc.select("div.col-xs-6")) { - String pic = element.select("img").get(1).attr("src"); - String url = element.select("a.overlay").attr("href"); - String name = element.select("div.card-mobile-title").text(); - String id = url.split("=")[1]; - list.add(new Vod(id, name, pic)); - } - return Result.string(list); - } - - @Override - public String playerContent(String flag, String id, List vipFlags) throws Exception { - return Result.get().url(id).header(getHeaders()).string(); - } -} diff --git a/app/src/main/java/com/github/catvod/spider/Init.java b/app/src/main/java/com/github/catvod/spider/Init.java index 865f8704..6de51f76 100644 --- a/app/src/main/java/com/github/catvod/spider/Init.java +++ b/app/src/main/java/com/github/catvod/spider/Init.java @@ -1,18 +1,17 @@ package com.github.catvod.spider; -import android.Manifest; import android.app.Activity; import android.app.Application; import android.content.Context; -import android.content.pm.PackageManager; -import android.os.Build; +import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.github.catvod.crawler.SpiderDebug; -import java.lang.reflect.Field; -import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -20,6 +19,7 @@ public class Init { private final ExecutorService executor; private final Handler handler; + private Activity activity; private Application app; private static class Loader { @@ -39,52 +39,68 @@ public class Init { return get().app; } + public static Activity activity() { + return get().activity; + } + + private void setActivity(Activity activity) { + this.activity = activity; + } + public static void init(Context context) { get().app = ((Application) context); SpiderDebug.log("自定義爬蟲代碼載入成功!"); + registerActivityLifecycleCallbacks(); + Proxy.init(); } public static void execute(Runnable runnable) { get().executor.execute(runnable); } - public static void run(Runnable runnable) { + public static void post(Runnable runnable) { get().handler.post(runnable); } - public static void run(Runnable runnable, int delay) { + public static void post(Runnable runnable, int delay) { get().handler.postDelayed(runnable, delay); } - public static void checkPermission() { - try { - Activity activity = Init.getActivity(); - if (activity == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return; - if (activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) return; - activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 9999); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static Activity getActivity() throws Exception { - Class activityThreadClass = Class.forName("android.app.ActivityThread"); - Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null); - Field activitiesField = activityThreadClass.getDeclaredField("mActivities"); - activitiesField.setAccessible(true); - Map activities = (Map) activitiesField.get(activityThread); - for (Object activityRecord : activities.values()) { - Class activityRecordClass = activityRecord.getClass(); - Field pausedField = activityRecordClass.getDeclaredField("paused"); - pausedField.setAccessible(true); - if (!pausedField.getBoolean(activityRecord)) { - Field activityField = activityRecordClass.getDeclaredField("activity"); - activityField.setAccessible(true); - Activity activity = (Activity) activityField.get(activityRecord); - SpiderDebug.log(activity.getComponentName().getClassName()); - return activity; + private static void registerActivityLifecycleCallbacks() { + get().app.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { + @Override + public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { + if (activity != activity()) get().setActivity(activity); } - } - return null; + + @Override + public void onActivityStarted(@NonNull Activity activity) { + if (activity != activity()) get().setActivity(activity); + } + + @Override + public void onActivityResumed(@NonNull Activity activity) { + if (activity != activity()) get().setActivity(activity); + } + + @Override + public void onActivityPaused(@NonNull Activity activity) { + if (activity == activity()) get().setActivity(null); + } + + @Override + public void onActivityStopped(@NonNull Activity activity) { + if (activity == activity()) get().setActivity(null); + } + + @Override + public void onActivityDestroyed(@NonNull Activity activity) { + if (activity == activity()) get().setActivity(null); + } + + @Override + public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) { + } + }); } } diff --git a/app/src/main/java/com/github/catvod/spider/Jianpian.java b/app/src/main/java/com/github/catvod/spider/Jianpian.java index 4e7d5c1e..48ff596c 100644 --- a/app/src/main/java/com/github/catvod/spider/Jianpian.java +++ b/app/src/main/java/com/github/catvod/spider/Jianpian.java @@ -1,114 +1,138 @@ -package com.github.catvod.spider; - -import android.content.Context; - -import com.github.catvod.bean.Class; -import com.github.catvod.bean.Result; -import com.github.catvod.bean.Vod; -import com.github.catvod.bean.jianpian.Data; -import com.github.catvod.bean.jianpian.Detail; -import com.github.catvod.bean.jianpian.Resp; -import com.github.catvod.crawler.Spider; -import com.github.catvod.net.OkHttp; -import com.github.catvod.utils.Json; - -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Qile - */ -public class Jianpian extends Spider { - - private final String siteUrl = "http://api2.rinhome.com"; - private String extend; - - private Map getHeader() { - Map headers = new HashMap<>(); - headers.put("User-Agent", "jianpian-android/360"); - headers.put("JPAUTH", "y261ow7kF2dtzlxh1GS9EB8nbTxNmaK/QQIAjctlKiEv"); - return headers; - } - - @Override - public void init(Context context, String extend) throws Exception { - this.extend = extend; - } - - @Override - public String homeContent(boolean filter) throws Exception { - List classes = new ArrayList<>(); - List typeIds = Arrays.asList("0", "1", "2", "3", "4"); - List typeNames = Arrays.asList("全部", "电影", "电视剧", "动漫", "综艺"); - for (int i = 0; i < typeIds.size(); i++) classes.add(new Class(typeIds.get(i), typeNames.get(i))); - return Result.string(classes, Json.parse(OkHttp.string(extend))); - } - - @Override - public String homeVideoContent() { - List list = new ArrayList<>(); - String url = siteUrl + "/api/slide/list?code=unknown9039b6856c3a3306&pos_id=888&channel=wandoujia"; - Resp resp = Resp.objectFrom(OkHttp.string(url, getHeader())); - for (Data data : resp.getData()) list.add(data.vod()); - return Result.string(list); - } - - @Override - public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception { - if (tid.endsWith("/{pg}")) return searchContent(tid.split("/")[0], pg); - List list = new ArrayList<>(); - HashMap ext = new HashMap<>(); - if (extend != null && extend.size() > 0) ext.putAll(extend); - String cateId = ext.get("cateId") == null ? tid : ext.get("cateId"); - String area = ext.get("area") == null ? "0" : ext.get("area"); - String year = ext.get("year") == null ? "0" : ext.get("year"); - String by = ext.get("by") == null ? "hot" : ext.get("by"); - String url = siteUrl + String.format("/api/crumb/list?area=%s&category_id=%s&page=%s&type=0&limit=24&sort=%s&year=%s", area, cateId, pg, by, year); - Resp resp = Resp.objectFrom(OkHttp.string(url, getHeader())); - for (Data data : resp.getData()) list.add(data.vod()); - return Result.string(list); - } - - @Override - public String detailContent(List ids) throws Exception { - String url = siteUrl + "/api/node/detail?channel=wandoujia&token=&id=" + ids.get(0); - Data data = Detail.objectFrom(OkHttp.string(url, getHeader())).getData(); - Vod vod = data.vod(); - vod.setVodPlayFrom("Jianpian"); - vod.setVodYear(data.getYear()); - vod.setVodArea(data.getArea()); - vod.setTypeName(data.getTypes()); - vod.setVodActor(data.getActors()); - vod.setVodPlayUrl(data.getPlayUrl()); - vod.setVodDirector(data.getDirectors()); - vod.setVodContent(data.getDescription()); - return Result.string(vod); - } - - @Override - public String playerContent(String flag, String id, List vipFlags) throws Exception { - return Result.get().url(id).header(getHeader()).string(); - } - - @Override - public String searchContent(String key, boolean quick) throws Exception { - return searchContent(key, "1"); - } - - @Override - public String searchContent(String key, boolean quick, String pg) throws Exception { - return searchContent(key, pg); - } - - public String searchContent(String key, String pg) throws Exception { - List list = new ArrayList<>(); - String url = siteUrl + "/api/video/search?page=" + pg + "&key=" + URLEncoder.encode(key); - Resp resp = Resp.objectFrom(OkHttp.string(url, getHeader())); - for (Data data : resp.getData()) list.add(data.vod()); - return Result.string(list); - } +package com.github.catvod.spider; + +import android.content.Context; + +import com.github.catvod.bean.Class; +import com.github.catvod.bean.Result; +import com.github.catvod.bean.Vod; +import com.github.catvod.bean.jianpian.Data; +import com.github.catvod.bean.jianpian.Detail; +import com.github.catvod.bean.jianpian.Resp; +import com.github.catvod.bean.jianpian.Search; +import com.github.catvod.crawler.Spider; +import com.github.catvod.net.OkHttp; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Qile + */ +public class Jianpian extends Spider { + + private String siteUrl = "https://ev5356.970xw.com"; + private String imgDomain; + private String extend; + + private Map getHeader() { + Map headers = new HashMap<>(); + headers.put("User-Agent", "Mozilla/5.0 (Linux; Android 9; V2196A Build/PQ3A.190705.08211809; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36;webank/h5face;webank/1.0;netType:NETWORK_WIFI;appVersion:416;packageName:com.jp3.xg3"); + headers.put("Referer", siteUrl); + return headers; + } + + @Override + public void init(Context context, String extend) throws Exception { + this.extend = extend; + JsonObject domains = new Gson().fromJson(OkHttp.string("https://dns.alidns.com/resolve?name=swrdsfeiujo25sw.cc&type=TXT"), JsonObject.class); + String parts = domains.getAsJsonArray("Answer").get(0).getAsJsonObject().get("data").getAsString(); + parts = parts.replace("\"", ""); + String[] domain = parts.split(","); + for (String d : domain) { + siteUrl = "https://wangerniu." + d; + String json = OkHttp.string(siteUrl + "/api/appAuthConfig"); + if (!json.isEmpty()) { + JsonObject root = new Gson().fromJson(json, JsonObject.class); + imgDomain = root.getAsJsonObject("data").get("imgDomain").getAsString(); + break; + } + } + } + + @Override + public String homeContent(boolean filter) throws Exception { + List classes = new ArrayList<>(); + List typeIds = Arrays.asList("1", "2", "3", "4", "50", "99"); + List typeNames = Arrays.asList("電影", "電視劇", "動漫", "綜藝", "紀錄片", "Netflix"); + for (int i = 0; i < typeIds.size(); i++) classes.add(new Class(typeIds.get(i), typeNames.get(i))); + return Result.string(classes, JsonParser.parseString(OkHttp.string(extend))); + } + + @Override + public String homeVideoContent() { + List list = new ArrayList<>(); + String url = siteUrl + "/api/slide/list?pos_id=88"; + Resp resp = Resp.objectFrom(OkHttp.string(url, getHeader())); + for (Data data : resp.getData()) list.add(data.homeVod(imgDomain)); + return Result.string(list); + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception { + if (tid.endsWith("/{pg}")) return searchContent(tid.split("/")[0], pg); + if (tid.equals("50") || tid.equals("99") || tid.equals("111")) { + List list = new ArrayList<>(); + String url = siteUrl + String.format("/api/dyTag/list?category_id=%s&page=%s", tid, pg); + Resp resp = Resp.objectFrom(OkHttp.string(url, getHeader())); + for (Data data : resp.getData()) for (Data dataList : data.getDataList()) list.add(dataList.vod(imgDomain)); + return Result.get().page().vod(list).string(); + } else { + List list = new ArrayList<>(); + HashMap ext = new HashMap<>(); + if (extend != null && !extend.isEmpty()) ext.putAll(extend); + String area = ext.get("area") == null ? "0" : ext.get("area"); + String year = ext.get("year") == null ? "0" : ext.get("year"); + String by = ext.get("by") == null ? "updata" : ext.get("by"); + String url = siteUrl + String.format("/api/crumb/list?fcate_pid=%s&area=%s&year=%s&type=0&sort=%s&page=%s&category_id=", tid, area, year, by, pg); + Resp resp = Resp.objectFrom(OkHttp.string(url, getHeader())); + for (Data data : resp.getData()) list.add(data.vod(imgDomain)); + return Result.string(list); + } + } + + @Override + public String detailContent(List ids) throws Exception { + String url = siteUrl + "/api/video/detailv2?id=" + ids.get(0); + Data data = Detail.objectFrom(OkHttp.string(url, getHeader())).getData(); + Vod vod = data.vod(imgDomain); + vod.setVodPlayFrom(data.getVodFrom()); + vod.setVodYear(data.getYear()); + vod.setVodArea(data.getArea()); + vod.setTypeName(data.getTypes()); + vod.setVodActor(data.getActors()); + vod.setVodPlayUrl(data.getVodUrl()); + vod.setVodDirector(data.getDirectors()); + vod.setVodContent(data.getDescription()); + return Result.string(vod); + } + + @Override + public String playerContent(String flag, String id, List vipFlags) throws Exception { + return Result.get().url(id).header(getHeader()).string(); + } + + @Override + public String searchContent(String key, boolean quick) throws Exception { + return searchContent(key, "1"); + } + + @Override + public String searchContent(String key, boolean quick, String pg) throws Exception { + return searchContent(key, pg); + } + + public String searchContent(String key, String pg) throws Exception { + List list = new ArrayList<>(); + String url = siteUrl + String.format("/api/v2/search/videoV2?key=%s&category_id=88&page=%s&pageSize=20", URLEncoder.encode(key), pg); + Search search = Search.objectFrom(OkHttp.string(url, getHeader())); + for (Search data : search.getData()) list.add(data.vod(imgDomain)); + return Result.string(list); + } } \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Local.java b/app/src/main/java/com/github/catvod/spider/Local.java index 3044de04..82af5d56 100644 --- a/app/src/main/java/com/github/catvod/spider/Local.java +++ b/app/src/main/java/com/github/catvod/spider/Local.java @@ -104,7 +104,7 @@ public class Local extends Spider { Vod vod = new Vod(); vod.setVodId(file.getAbsolutePath()); vod.setVodName(file.getName()); - vod.setVodPic(file.isFile() ? Proxy.getUrl() + "?do=local&path=" + Base64.encodeToString(file.getAbsolutePath().getBytes(), Base64.DEFAULT | Base64.URL_SAFE) : Image.FOLDER); + vod.setVodPic(file.isFile() ? "proxy://do=local&path=" + Base64.encodeToString(file.getAbsolutePath().getBytes(), Base64.DEFAULT | Base64.URL_SAFE) : Image.FOLDER); vod.setVodRemarks(format.format(file.lastModified())); vod.setVodTag(file.isDirectory() ? "folder" : "file"); return vod; diff --git a/app/src/main/java/com/github/catvod/spider/MQiTV.java b/app/src/main/java/com/github/catvod/spider/MQiTV.java new file mode 100644 index 00000000..c4d20bdd --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/MQiTV.java @@ -0,0 +1,89 @@ +package com.github.catvod.spider; + +import android.content.Context; + +import com.github.catvod.bean.mqitv.Config; +import com.github.catvod.bean.mqitv.Data; +import com.github.catvod.crawler.Spider; + +import java.io.ByteArrayInputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MQiTV extends Spider { + + private static List configs; + + public static List getConfigs() { + return configs = configs == null ? new ArrayList<>() : configs; + } + + @Override + public void init(Context context, String extend) throws Exception { + configs = Config.arrayFrom(extend); + } + + @Override + public String liveContent(String url) throws Exception { + StringBuilder sb = new StringBuilder(); + for (Config config : getConfigs()) { + if (config.getData().isEmpty()) continue; + sb.append(config.getName()).append(",#genre#").append("\n"); + boolean hasPort = config.getUri().getPort() != -1; + for (Data item : config.getData()) { + String port = hasPort ? item.getPort() : "5003"; + String proxy = "proxy://do=mqitv&id=" + item.getId() + "&ip=" + config.getUrl() + "&playing=" + item.getPlaying() + "&port=" + port + "&type=m3u8"; + sb.append(item.getName()).append(",").append(proxy).append("\n"); + } + } + return sb.toString(); + } + + private static Config getConfig(String ip) { + Config config = new Config(ip); + int index = getConfigs().indexOf(config); + if (index != -1) return getConfigs().get(index); + else getConfigs().add(config); + return config; + } + + public static Object[] proxy(Map params) { + String ip = params.get("ip"); + String port = params.get("port"); + String playing = params.get("playing"); + if (port == null) port = "5003"; + Config config = getConfig(ip); + String token = config.getUser().getToken(); + if (token.isEmpty()) { + return get302(config.getPlayUrl(port, playing)); + } else { + String id = params.get("id"); + String auth = config.getAuth(id, token); + if (!"OK".equals(auth)) config.clear(); + if (!"OK".equals(auth)) return proxy(params); + String m3u8 = config.getM3U8(id, token, port); + return m3u8.isEmpty() ? get302(config.getPlayUrl(port, playing)) : get200(m3u8); + } + } + + private static Object[] get302(String location) { + Map header = new HashMap<>(); + header.put("Location", location); + Object[] result = new Object[4]; + result[0] = 302; + result[1] = "text/plain"; + result[2] = new ByteArrayInputStream("302 Found".getBytes()); + result[3] = header; + return result; + } + + private static Object[] get200(String m3u8) { + Object[] result = new Object[3]; + result[0] = 200; + result[1] = "application/vnd.apple.mpegurl"; + result[2] = new ByteArrayInputStream(m3u8.getBytes()); + return result; + } +} diff --git a/app/src/main/java/com/github/catvod/spider/Market.java b/app/src/main/java/com/github/catvod/spider/Market.java index 33a8d135..f7fe7248 100644 --- a/app/src/main/java/com/github/catvod/spider/Market.java +++ b/app/src/main/java/com/github/catvod/spider/Market.java @@ -42,7 +42,6 @@ public class Market extends Spider { public void init(Context context, String extend) throws Exception { if (extend.startsWith("http")) extend = OkHttp.string(extend); datas = Data.arrayFrom(extend); - Init.checkPermission(); } @Override @@ -63,7 +62,7 @@ public class Market extends Spider { try { if (isBusy()) return ""; setBusy(true); - Init.run(this::setDialog, 500); + Init.post(this::setDialog, 500); Response response = OkHttp.newCall(action); File file = Path.create(new File(Path.download(), Uri.parse(action).getLastPathSegment())); download(file, response.body().byteStream(), Double.parseDouble(response.header("Content-Length", "1"))); @@ -71,6 +70,7 @@ public class Market extends Spider { if (file.getName().endsWith(".apk")) FileUtil.openFile(file); else Result.notify("下載完成"); checkCopy(action); + response.close(); dismiss(); return ""; } catch (Exception e) { @@ -80,8 +80,7 @@ public class Market extends Spider { } private void download(File file, InputStream is, double length) throws Exception { - FileOutputStream os = new FileOutputStream(file); - try (BufferedInputStream input = new BufferedInputStream(is)) { + try (BufferedInputStream input = new BufferedInputStream(is); FileOutputStream os = new FileOutputStream(file)) { byte[] buffer = new byte[4096]; int readBytes; long totalBytes = 0; @@ -104,9 +103,9 @@ public class Market extends Spider { } private void setDialog() { - Init.run(() -> { + Init.post(() -> { try { - dialog = new ProgressDialog(Init.getActivity()); + dialog = new ProgressDialog(Init.activity()); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); if (isBusy()) dialog.show(); @@ -117,7 +116,7 @@ public class Market extends Spider { } private void dismiss() { - Init.run(() -> { + Init.post(() -> { try { setBusy(false); if (dialog != null) dialog.dismiss(); @@ -128,7 +127,7 @@ public class Market extends Spider { } private void setProgress(int value) { - Init.run(() -> { + Init.post(() -> { try { if (dialog != null) dialog.setProgress(value); } catch (Exception e) { diff --git a/app/src/main/java/com/github/catvod/spider/Proxy.java b/app/src/main/java/com/github/catvod/spider/Proxy.java index e8530bf7..48183ef4 100644 --- a/app/src/main/java/com/github/catvod/spider/Proxy.java +++ b/app/src/main/java/com/github/catvod/spider/Proxy.java @@ -1,20 +1,24 @@ package com.github.catvod.spider; -import com.github.catvod.crawler.Spider; import com.github.catvod.crawler.SpiderDebug; import com.github.catvod.net.OkHttp; import java.io.ByteArrayInputStream; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.util.Map; -public class Proxy extends Spider { +public class Proxy { - private static int port = -1; + private static Method method; + private static int port; public static Object[] proxy(Map params) throws Exception { switch (params.get("do")) { case "ck": - return new Object[]{200, "text/plain; charset=utf-8", new ByteArrayInputStream("ok".getBytes("UTF-8"))}; + return new Object[]{200, "text/plain; charset=utf-8", new ByteArrayInputStream("ok".getBytes(StandardCharsets.UTF_8))}; + case "mqitv": + return MQiTV.proxy(params); case "bili": return Bili.proxy(params); case "webdav": @@ -26,27 +30,41 @@ public class Proxy extends Spider { } } - static void adjustPort() { - if (Proxy.port > 0) return; - int port = 9978; - while (port < 10000) { - String resp = OkHttp.string("http://127.0.0.1:" + port + "/proxy?do=ck", null); - if (resp.equals("ok")) { - SpiderDebug.log("Found local server port " + port); - Proxy.port = port; - break; - } - port++; + public static void init() { + try { + Class clz = Class.forName("com.github.catvod.Proxy"); + port = (int) clz.getMethod("getPort").invoke(null); + method = clz.getMethod("getUrl", boolean.class); + SpiderDebug.log("本地代理端口:" + port); + } catch (Throwable e) { + findPort(); } } public static int getPort() { - adjustPort(); return port; } public static String getUrl() { - adjustPort(); - return "http://127.0.0.1:" + port + "/proxy"; + return getUrl(true); + } + + public static String getUrl(boolean local) { + try { + return (String) method.invoke(null, local); + } catch (Throwable e) { + return "http://127.0.0.1:" + port + "/proxy"; + } + } + + private static void findPort() { + if (port > 0) return; + for (int p = 8964; p < 9999; p++) { + if ("ok".equals(OkHttp.string("http://127.0.0.1:" + p + "/proxy?do=ck", null))) { + SpiderDebug.log("本地代理端口:" + p); + port = p; + break; + } + } } } diff --git a/app/src/main/java/com/github/catvod/spider/Push.java b/app/src/main/java/com/github/catvod/spider/Push.java index 550eb2d9..7989440c 100644 --- a/app/src/main/java/com/github/catvod/spider/Push.java +++ b/app/src/main/java/com/github/catvod/spider/Push.java @@ -38,7 +38,7 @@ public class Push extends Spider { vod.setVodId(url); vod.setVodPic(Image.PUSH); vod.setTypeName("FongMi"); - vod.setVodName(url.startsWith("file://") ? new File(url).getName() : url); + vod.setVodName(url.startsWith("file://") ? new File(url).getName() : ""); if (url.contains("://") && url.contains("#")) url = url.replace("#", "***"); if (Util.isThunder(url)) { vod.setVodPlayUrl(url); diff --git a/app/src/main/java/com/github/catvod/spider/WebDAV.java b/app/src/main/java/com/github/catvod/spider/WebDAV.java index 3176bad3..973085aa 100644 --- a/app/src/main/java/com/github/catvod/spider/WebDAV.java +++ b/app/src/main/java/com/github/catvod/spider/WebDAV.java @@ -174,7 +174,7 @@ public class WebDAV extends Spider { } private String getProxyUrl(String url) { - return Proxy.getUrl() + "?do=webdav&url=" + url; + return "proxy://do=webdav&url=" + url; } public static Object[] vod(Map params) throws IOException { diff --git a/app/src/main/java/com/github/catvod/spider/XPath.java b/app/src/main/java/com/github/catvod/spider/XPath.java deleted file mode 100644 index 26eb1b74..00000000 --- a/app/src/main/java/com/github/catvod/spider/XPath.java +++ /dev/null @@ -1,345 +0,0 @@ -package com.github.catvod.spider; - -import android.content.Context; -import android.text.TextUtils; - -import com.github.catvod.bean.Class; -import com.github.catvod.bean.Result; -import com.github.catvod.bean.Vod; -import com.github.catvod.bean.xpath.Rule; -import com.github.catvod.crawler.Spider; -import com.github.catvod.crawler.SpiderDebug; -import com.github.catvod.net.OkHttp; -import com.github.catvod.utils.Util; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.seimicrawler.xpath.JXDocument; -import org.seimicrawler.xpath.JXNode; - -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Set; - -public class XPath extends Spider { - - private HashMap getHeaders() { - HashMap headers = new HashMap<>(); - headers.put("User-Agent", rule.getUa().isEmpty() ? Util.CHROME : rule.getUa()); - return headers; - } - - @Override - public void init(Context context, String extend) { - this.ext = extend; - } - - @Override - public String homeContent(boolean filter) { - fetchRule(); - List list = new ArrayList<>(); - List classes = new ArrayList<>(); - if (!rule.getCateManual().isEmpty()) { - Set keys = rule.getCateManual().keySet(); - for (String k : keys) { - classes.add(new Class(rule.getCateManual().get(k), k)); - } - } - String webUrl = rule.getHomeUrl(); - JXDocument doc = JXDocument.create(fetch(webUrl)); - if (rule.getCateManual().isEmpty()) { - List navNodes = doc.selN(rule.getCateNode()); - for (int i = 0; i < navNodes.size(); i++) { - String name = navNodes.get(i).selOne(rule.getCateName()).asString().trim(); - name = rule.getCateNameR(name); - String id = navNodes.get(i).selOne(rule.getCateId()).asString().trim(); - id = rule.getCateIdR(id); - classes.add(new Class(id, name)); - } - } - if (!rule.getHomeVodNode().isEmpty()) { - List vodNodes = doc.selN(rule.getHomeVodNode()); - for (int i = 0; i < vodNodes.size(); i++) { - String name = vodNodes.get(i).selOne(rule.getHomeVodName()).asString().trim(); - name = rule.getHomeVodNameR(name); - String id = vodNodes.get(i).selOne(rule.getHomeVodId()).asString().trim(); - id = rule.getHomeVodIdR(id); - String pic = vodNodes.get(i).selOne(rule.getHomeVodImg()).asString().trim(); - pic = rule.getHomeVodImgR(pic); - pic = Util.fixUrl(webUrl, pic); - String mark = ""; - if (!rule.getHomeVodMark().isEmpty()) { - try { - mark = vodNodes.get(i).selOne(rule.getHomeVodMark()).asString().trim(); - mark = rule.getHomeVodMarkR(mark); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - list.add(new Vod(id, name, pic, mark)); - } - } - return Result.string(classes, list, rule.getFilter()); - } - - protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { - return rule.getCateUrl().replace("{cateId}", tid).replace("{catePg}", pg); - } - - @Override - public String categoryContent(String tid, String pg, boolean filter, HashMap extend) { - fetchRule(); - List list = new ArrayList<>(); - String webUrl = categoryUrl(tid, pg, filter, extend); - JXDocument doc = JXDocument.create(fetch(webUrl)); - List vodNodes = doc.selN(rule.getCateVodNode()); - for (int i = 0; i < vodNodes.size(); i++) { - String name = vodNodes.get(i).selOne(rule.getCateVodName()).asString().trim(); - name = rule.getCateVodNameR(name); - String id = vodNodes.get(i).selOne(rule.getCateVodId()).asString().trim(); - id = rule.getCateVodIdR(id); - String pic = vodNodes.get(i).selOne(rule.getCateVodImg()).asString().trim(); - pic = rule.getCateVodImgR(pic); - pic = Util.fixUrl(webUrl, pic); - String mark = ""; - if (!rule.getCateVodMark().isEmpty()) { - try { - mark = vodNodes.get(i).selOne(rule.getCateVodMark()).asString().trim(); - mark = rule.getCateVodMarkR(mark); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - list.add(new Vod(id, name, pic, mark)); - } - return Result.string(list); - } - - @Override - public String detailContent(List ids) { - fetchRule(); - String webUrl = rule.getDetailUrl().replace("{vid}", ids.get(0)); - String webContent = fetch(webUrl); - JXDocument doc = JXDocument.create(webContent); - JXNode vodNode = doc.selNOne(rule.getDetailNode()); - String cover = "", title = "", desc = "", category = "", area = "", year = "", remark = "", director = "", actor = ""; - title = vodNode.selOne(rule.getDetailName()).asString().trim(); - title = rule.getDetailNameR(title); - cover = vodNode.selOne(rule.getDetailImg()).asString().trim(); - cover = rule.getDetailImgR(cover); - cover = Util.fixUrl(webUrl, cover); - if (!rule.getDetailCate().isEmpty()) { - try { - category = vodNode.selOne(rule.getDetailCate()).asString().trim(); - category = rule.getDetailCateR(category); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - if (!rule.getDetailYear().isEmpty()) { - try { - year = vodNode.selOne(rule.getDetailYear()).asString().trim(); - year = rule.getDetailYearR(year); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - if (!rule.getDetailArea().isEmpty()) { - try { - area = vodNode.selOne(rule.getDetailArea()).asString().trim(); - area = rule.getDetailAreaR(area); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - if (!rule.getDetailMark().isEmpty()) { - try { - remark = vodNode.selOne(rule.getDetailMark()).asString().trim(); - remark = rule.getDetailMarkR(remark); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - if (!rule.getDetailActor().isEmpty()) { - try { - actor = vodNode.selOne(rule.getDetailActor()).asString().trim(); - actor = rule.getDetailActorR(actor); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - if (!rule.getDetailDirector().isEmpty()) { - try { - director = vodNode.selOne(rule.getDetailDirector()).asString().trim(); - director = rule.getDetailDirectorR(director); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - if (!rule.getDetailDesc().isEmpty()) { - try { - desc = vodNode.selOne(rule.getDetailDesc()).asString().trim(); - desc = rule.getDetailDescR(desc); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - - Vod vod = new Vod(); - vod.setVodId(ids.get(0)); - vod.setVodName(title); - vod.setVodPic(cover); - vod.setTypeName(category); - vod.setVodYear(year); - vod.setVodArea(area); - vod.setVodRemarks(remark); - vod.setVodActor(actor); - vod.setVodDirector(director); - vod.setVodContent(desc); - - ArrayList playFrom = new ArrayList<>(); - List fromNodes = doc.selN(rule.getDetailFromNode()); - for (int i = 0; i < fromNodes.size(); i++) { - String name = fromNodes.get(i).selOne(rule.getDetailFromName()).asString().trim(); - name = rule.getDetailFromNameR(name); - playFrom.add(name); - } - - ArrayList playList = new ArrayList<>(); - List urlListNodes = doc.selN(rule.getDetailUrlNode()); - for (int i = 0; i < urlListNodes.size(); i++) { - List urlNodes = urlListNodes.get(i).sel(rule.getDetailUrlSubNode()); - List vodItems = new ArrayList<>(); - for (int j = 0; j < urlNodes.size(); j++) { - String name = urlNodes.get(j).selOne(rule.getDetailUrlName()).asString().trim(); - name = rule.getDetailUrlNameR(name); - String id = urlNodes.get(j).selOne(rule.getDetailUrlId()).asString().trim(); - id = rule.getDetailUrlIdR(id); - vodItems.add(name + "$" + id); - } - // 排除播放列表為空的播放源 - if (vodItems.isEmpty() && playFrom.size() > i) { - playFrom.set(i, ""); - } - playList.add(TextUtils.join("#", vodItems)); - } - // 排除播放列表為空的播放源 - for (int i = playFrom.size() - 1; i >= 0; i--) { - if (playFrom.get(i).isEmpty()) playFrom.remove(i); - } - for (int i = playList.size() - 1; i >= 0; i--) { - if (playList.get(i).isEmpty()) playList.remove(i); - } - for (int i = playList.size() - 1; i >= 0; i--) { - if (i >= playFrom.size()) playList.remove(i); - } - vod.setVodPlayFrom(TextUtils.join("$$$", playFrom)); - vod.setVodPlayUrl(TextUtils.join("$$$", playList)); - return Result.string(vod); - } - - @Override - public String playerContent(String flag, String id, List vipFlags) { - fetchRule(); - String webUrl = rule.getPlayUrl().isEmpty() ? id : rule.getPlayUrl().replace("{playUrl}", id); - SpiderDebug.log(webUrl); - HashMap headers = new HashMap<>(); - if (!rule.getPlayUa().isEmpty()) headers.put("User-Agent", rule.getPlayUa()); - if (!rule.getPlayReferer().isEmpty()) headers.put("Referer", rule.getPlayReferer()); - return Result.get().parse().url(webUrl).header(headers).string(); - } - - @Override - public String searchContent(String key, boolean quick) throws Exception { - fetchRule(); - if (rule.getSearchUrl().isEmpty()) return ""; - String webUrl = rule.getSearchUrl().replace("{wd}", URLEncoder.encode(key)); - String webContent = fetch(webUrl); - List list = new ArrayList<>(); - if (rule.getSearchVodNode().startsWith("json:")) { - String[] node = rule.getSearchVodNode().substring(5).split(">"); - JSONObject data = new JSONObject(webContent); - for (int i = 0; i < node.length; i++) { - if (i == node.length - 1) { - JSONArray vodArray = data.getJSONArray(node[i]); - for (int j = 0; j < vodArray.length(); j++) { - JSONObject vod = vodArray.getJSONObject(j); - String name = vod.optString(rule.getSearchVodName()).trim(); - name = rule.getSearchVodNameR(name); - String id = vod.optString(rule.getSearchVodId()).trim(); - id = rule.getSearchVodIdR(id); - String pic = vod.optString(rule.getSearchVodImg()).trim(); - pic = rule.getSearchVodImgR(pic); - pic = Util.fixUrl(webUrl, pic); - String mark = vod.optString(rule.getSearchVodMark()).trim(); - mark = rule.getSearchVodMarkR(mark); - list.add(new Vod(id, name, pic, mark)); - } - } else { - data = data.getJSONObject(node[i]); - } - } - } else { - JXDocument doc = JXDocument.create(webContent); - List vodNodes = doc.selN(rule.getSearchVodNode()); - for (int i = 0; i < vodNodes.size(); i++) { - String name = vodNodes.get(i).selOne(rule.getSearchVodName()).asString().trim(); - name = rule.getSearchVodNameR(name); - String id = vodNodes.get(i).selOne(rule.getSearchVodId()).asString().trim(); - id = rule.getSearchVodIdR(id); - String pic = vodNodes.get(i).selOne(rule.getSearchVodImg()).asString().trim(); - pic = rule.getSearchVodImgR(pic); - pic = Util.fixUrl(webUrl, pic); - String mark = ""; - if (!rule.getCateVodMark().isEmpty()) { - try { - mark = vodNodes.get(i).selOne(rule.getSearchVodMark()).asString().trim(); - mark = rule.getSearchVodMarkR(mark); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - list.add(new Vod(id, name, pic, mark)); - } - } - return Result.string(list); - } - - @Override - public boolean manualVideoCheck() { - return false; - } - - @Override - public boolean isVideoFormat(String url) { - return Util.isVideoFormat(url); - } - - protected String ext = null; - protected Rule rule = null; - - protected void fetchRule() { - if (rule == null) { - if (ext != null) { - if (ext.startsWith("http")) { - String json = OkHttp.string(ext, null); - rule = Rule.fromJson(json); - loadRuleExt(json); - } else { - rule = Rule.fromJson(ext); - loadRuleExt(ext); - } - } - } - } - - protected void loadRuleExt(String json) { - } - - protected String fetch(String webUrl) { - SpiderDebug.log(webUrl); - return OkHttp.string(webUrl, getHeaders()); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/XPathFilter.java b/app/src/main/java/com/github/catvod/spider/XPathFilter.java deleted file mode 100644 index 387b99bb..00000000 --- a/app/src/main/java/com/github/catvod/spider/XPathFilter.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.github.catvod.spider; - -import android.text.TextUtils; - -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class XPathFilter extends XPath { - - @Override - protected void loadRuleExt(String json) { - super.loadRuleExt(json); - } - - @Override - protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { - String cateUrl = rule.getCateUrl(); - if (filter && extend != null && !extend.isEmpty()) { - for (String key : extend.keySet()) { - String value = extend.get(key); - if (!TextUtils.isEmpty(value)) { - cateUrl = cateUrl.replace("{" + key + "}", URLEncoder.encode(value)); - } - } - } - cateUrl = cateUrl.replace("{cateId}", tid).replace("{catePg}", pg); - Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(cateUrl); - while (m.find()) { - String n = m.group(0).replace("{", "").replace("}", ""); - cateUrl = cateUrl.replace(m.group(0), "").replace("/" + n + "/", ""); - } - return cateUrl; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/XPathMac.java b/app/src/main/java/com/github/catvod/spider/XPathMac.java deleted file mode 100644 index 0154b52c..00000000 --- a/app/src/main/java/com/github/catvod/spider/XPathMac.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.github.catvod.spider; - -import android.content.Context; -import android.text.TextUtils; -import android.util.Base64; - -import com.github.catvod.crawler.SpiderDebug; -import com.github.catvod.utils.Util; -import com.google.gson.Gson; - -import org.json.JSONException; -import org.json.JSONObject; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.select.Elements; - -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class XPathMac extends XPath { - - // 嘗試分析直連 - private boolean decodePlayUrl; - // 嘗試匹配官源標識以調用應用配置中的解析列表 - private boolean decodeVipFlag; - // 播放器配置js - private String playerConfigJs = ""; - // 播放器配置js取值正則 - private String playerConfigJsRegex = "[\\W|\\S|.]*?MacPlayerConfig.player_list[\\W|\\S|.]*?=([\\W|\\S|.]*?),MacPlayerConfig.downer_list"; - // 站點里播放源對應的真實官源 - private final HashMap show2VipFlag = new HashMap<>(); - - /** - * mac cms 直連和官源調用應用內播放列表支持 - * - * @param context - * @param extend - */ - public void init(Context context, String extend) { - super.init(context, extend); - } - - @Override - protected void loadRuleExt(String json) { - try { - JSONObject jsonObj = new JSONObject(json); - decodePlayUrl = jsonObj.optBoolean("dcPlayUrl", false); - decodeVipFlag = jsonObj.optBoolean("dcVipFlag", false); - JSONObject dcShow2Vip = jsonObj.optJSONObject("dcShow2Vip"); - if (dcShow2Vip != null) { - Iterator keys = dcShow2Vip.keys(); - while (keys.hasNext()) { - String name = keys.next(); - show2VipFlag.put(name.trim(), dcShow2Vip.getString(name).trim()); - } - } - playerConfigJs = jsonObj.optString("pCfgJs").trim(); - playerConfigJsRegex = jsonObj.optString("pCfgJsR", playerConfigJsRegex).trim(); - } catch (JSONException e) { - SpiderDebug.log(e); - } - } - - @Override - public String homeContent(boolean filter) { - String result = super.homeContent(filter); - if (!result.isEmpty() && !playerConfigJs.isEmpty()) { // 嘗試通過playerConfigJs獲取展示和flag匹配關系 - String webContent = fetch(playerConfigJs); - Matcher matcher = Pattern.compile(playerConfigJsRegex).matcher(webContent); - if (matcher.find()) { - try { - JSONObject jsonObject = new JSONObject(matcher.group(1)); - Iterator keys = jsonObject.keys(); - while (keys.hasNext()) { - String key = keys.next(); - JSONObject keyObj = jsonObject.optJSONObject(key); - if (keyObj == null) continue; - String show = keyObj.optString("show").trim(); - if (show.isEmpty()) continue; - show2VipFlag.put(show, key); - } - } catch (Exception e) { - SpiderDebug.log(e); - } - } - } - return result; - } - - @Override - public String detailContent(List ids) { - String result = super.detailContent(ids); - if (decodeVipFlag && !result.isEmpty()) { - try { - JSONObject jsonObject = new JSONObject(result); - String[] playFrom = jsonObject.optJSONArray("list").getJSONObject(0).optString("vod_play_from").split("\\$\\$\\$"); - if (playFrom.length > 0) { - for (int i = 0; i < playFrom.length; i++) { - if (show2VipFlag.containsKey(playFrom[i])) { - playFrom[i] = show2VipFlag.get(playFrom[i]); - } - } - jsonObject.optJSONArray("list").getJSONObject(0).put("vod_play_from", TextUtils.join("$$$", playFrom)); - result = jsonObject.toString(); - } - } catch (Throwable th) { - SpiderDebug.log(th); - } - } - return result; - } - - @Override - public String playerContent(String flag, String id, List vipFlags) { - fetchRule(); - String webUrl = rule.getPlayUrl().isEmpty() ? id : rule.getPlayUrl().replace("{playUrl}", id); - String videoUrl = null; - // 嘗試分析直連 - if (decodePlayUrl) { - try { - Document doc = Jsoup.parse(fetch(webUrl)); - Elements allScript = doc.select("script"); - for (int i = 0; i < allScript.size(); i++) { - String scContent = allScript.get(i).html().trim(); - if (scContent.startsWith("var player_")) { - int start = scContent.indexOf('{'); - int end = scContent.lastIndexOf('}') + 1; - String json = scContent.substring(start, end); - JSONObject player = new JSONObject(json); - String videoUrlTmp = player.getString("url"); - if (player.has("encrypt")) { - int encrypt = player.getInt("encrypt"); - if (encrypt == 1) { - videoUrlTmp = URLDecoder.decode(videoUrlTmp); - } else if (encrypt == 2) { - videoUrlTmp = new String(Base64.decode(videoUrlTmp, Base64.DEFAULT)); - videoUrlTmp = URLDecoder.decode(videoUrlTmp); - } - } - videoUrl = videoUrlTmp; - break; - } - } - } catch (Exception e) { - SpiderDebug.log(e); - } - } - if (videoUrl != null) { - // 適配2.0.6的調用應用內解析列表的支持, 需要配合直連分析和匹配官源解析一起使用,參考cjt影視和極品直連 - if (decodeVipFlag && Util.isVip(videoUrl)) { // 使用jx:1 - try { - JSONObject result = new JSONObject(); - result.put("parse", 1); - result.put("jx", "1"); - result.put("url", videoUrl); - return result.toString(); - } catch (Exception e) { - SpiderDebug.log(e); - } - } else if (decodeVipFlag && vipFlags.contains(flag)) { // 是否使用應用內解析列表解析官源 - try { - JSONObject result = new JSONObject(); - result.put("parse", 1); - result.put("playUrl", ""); - result.put("url", videoUrl); - result.put("header", ""); - return result.toString(); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - // 如果是視頻直連 直接返回免解 - else if (isVideoFormat(videoUrl)) { - try { - JSONObject result = new JSONObject(); - result.put("parse", 0); - result.put("playUrl", ""); - result.put("url", videoUrl); - HashMap headers = new HashMap<>(); - if (!rule.getPlayUa().isEmpty()) headers.put("User-Agent", rule.getPlayUa()); - if (!rule.getPlayReferer().isEmpty()) headers.put("Referer", rule.getPlayReferer()); - result.put("header", new Gson().toJson(headers)); - return result.toString(); - } catch (Exception e) { - SpiderDebug.log(e); - } - } - } - // 上述都失敗了就按默認模式走 - return super.playerContent(flag, id, vipFlags); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/XPathMacFilter.java b/app/src/main/java/com/github/catvod/spider/XPathMacFilter.java deleted file mode 100644 index 78f9ecc8..00000000 --- a/app/src/main/java/com/github/catvod/spider/XPathMacFilter.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.github.catvod.spider; - -import android.text.TextUtils; - -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class XPathMacFilter extends XPathMac { - - @Override - protected String categoryUrl(String tid, String pg, boolean filter, HashMap extend) { - String cateUrl = rule.getCateUrl(); - if (filter && extend != null && !extend.isEmpty()) { - for (String key : extend.keySet()) { - String value = extend.get(key); - if (!TextUtils.isEmpty(value)) { - cateUrl = cateUrl.replace("{" + key + "}", URLEncoder.encode(value)); - } - } - } - cateUrl = cateUrl.replace("{cateId}", tid).replace("{catePg}", pg); - Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(cateUrl); - while (m.find()) { - String n = m.group(0).replace("{", "").replace("}", ""); - cateUrl = cateUrl.replace(m.group(0), "").replace("/" + n + "/", ""); - } - return cateUrl; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/YHDM.java b/app/src/main/java/com/github/catvod/spider/YHDM.java index a633da48..00b5ad3a 100644 --- a/app/src/main/java/com/github/catvod/spider/YHDM.java +++ b/app/src/main/java/com/github/catvod/spider/YHDM.java @@ -53,9 +53,7 @@ public class YHDM extends Spider { List classes = new ArrayList<>(); List typeIds = Arrays.asList("guochandongman", "ribendongman", "dongmandianying", "omeidongman"); List typeNames = Arrays.asList("国产动漫", "日本动漫", "动漫电影", "欧美动漫"); - for (int i = 0; i < typeIds.size(); i++) - classes.add(new Class(typeIds.get(i), typeNames.get(i))); - + for (int i = 0; i < typeIds.size(); i++) classes.add(new Class(typeIds.get(i), typeNames.get(i))); Document doc = Jsoup.parse(OkHttp.string(siteUrl, getHeader())); List list = new ArrayList<>(); for (Element li : doc.select(".stui-vodlist.clearfix .myui-vodlist__box")) { diff --git a/app/src/main/java/com/github/catvod/utils/FileProvider.java b/app/src/main/java/com/github/catvod/utils/FileProvider.java index 8440a50d..70bad865 100644 --- a/app/src/main/java/com/github/catvod/utils/FileProvider.java +++ b/app/src/main/java/com/github/catvod/utils/FileProvider.java @@ -12,13 +12,14 @@ import android.content.res.XmlResourceParser; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; -import android.os.Bundle; import android.os.Environment; import android.os.ParcelFileDescriptor; import android.provider.OpenableColumns; import android.text.TextUtils; import android.webkit.MimeTypeMap; +import androidx.annotation.NonNull; + import org.xmlpull.v1.XmlPullParserException; import java.io.File; @@ -57,16 +58,16 @@ public class FileProvider extends ContentProvider { synchronized (sCache) { sCache.remove(authority); } - mStrategy = getPathStrategy(context, authority, 0); + mStrategy = getPathStrategy(context, authority); } public static Uri getUriForFile(Context context, String authority, File file) { - final PathStrategy strategy = getPathStrategy(context, authority, 0); + final PathStrategy strategy = getPathStrategy(context, authority); return strategy.getUriForFile(file); } @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { final File file = mStrategy.getFileForUri(uri); String displayName = uri.getQueryParameter(DISPLAYNAME_FIELD); if (projection == null) { @@ -92,7 +93,7 @@ public class FileProvider extends ContentProvider { } @Override - public String getType(Uri uri) { + public String getType(@NonNull Uri uri) { final File file = mStrategy.getFileForUri(uri); final int lastDot = file.getName().lastIndexOf('.'); if (lastDot >= 0) { @@ -106,38 +107,36 @@ public class FileProvider extends ContentProvider { } @Override - public Uri insert(Uri uri, ContentValues values) { + public Uri insert(@NonNull Uri uri, ContentValues values) { throw new UnsupportedOperationException("No external inserts"); } @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) { throw new UnsupportedOperationException("No external updates"); } @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { + public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) { final File file = mStrategy.getFileForUri(uri); return file.delete() ? 1 : 0; } @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { final File file = mStrategy.getFileForUri(uri); final int fileMode = modeToMode(mode); return ParcelFileDescriptor.open(file, fileMode); } - private static PathStrategy getPathStrategy(Context context, String authority, int resourceId) { + private static PathStrategy getPathStrategy(Context context, String authority) { PathStrategy strat; synchronized (sCache) { strat = sCache.get(authority); if (strat == null) { try { - strat = parsePathStrategy(context, authority, resourceId); - } catch (IOException e) { - throw new IllegalArgumentException("Failed to parse " + META_DATA_FILE_PROVIDER_PATHS + " meta-data", e); - } catch (XmlPullParserException e) { + strat = parsePathStrategy(context, authority); + } catch (IOException | XmlPullParserException e) { throw new IllegalArgumentException("Failed to parse " + META_DATA_FILE_PROVIDER_PATHS + " meta-data", e); } sCache.put(authority, strat); @@ -146,14 +145,10 @@ public class FileProvider extends ContentProvider { return strat; } - static XmlResourceParser getFileProviderPathsMetaData(Context context, String authority, ProviderInfo info, int resourceId) { + static XmlResourceParser getFileProviderPathsMetaData(Context context, String authority, ProviderInfo info) { if (info == null) { throw new IllegalArgumentException("Couldn't find meta-data for provider with authority " + authority); } - if (info.metaData == null && resourceId != 0) { - info.metaData = new Bundle(1); - info.metaData.putInt(META_DATA_FILE_PROVIDER_PATHS, resourceId); - } final XmlResourceParser in = info.loadXmlMetaData(context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS); if (in == null) { throw new IllegalArgumentException("Missing " + META_DATA_FILE_PROVIDER_PATHS + " meta-data"); @@ -161,10 +156,10 @@ public class FileProvider extends ContentProvider { return in; } - private static PathStrategy parsePathStrategy(Context context, String authority, int resourceId) throws IOException, XmlPullParserException { + private static PathStrategy parsePathStrategy(Context context, String authority) throws IOException, XmlPullParserException { final SimplePathStrategy strat = new SimplePathStrategy(authority); final ProviderInfo info = context.getPackageManager().resolveContentProvider(authority, PackageManager.GET_META_DATA); - final XmlResourceParser in = getFileProviderPathsMetaData(context, authority, info, resourceId); + final XmlResourceParser in = getFileProviderPathsMetaData(context, authority, info); int type; while ((type = in.next()) != END_DOCUMENT) { if (type == START_TAG) { diff --git a/app/src/main/java/com/github/catvod/utils/FileUtil.java b/app/src/main/java/com/github/catvod/utils/FileUtil.java index 198276f7..fe2183df 100644 --- a/app/src/main/java/com/github/catvod/utils/FileUtil.java +++ b/app/src/main/java/com/github/catvod/utils/FileUtil.java @@ -8,9 +8,7 @@ import android.text.TextUtils; import com.github.catvod.spider.Init; import java.io.File; -import java.io.FileInputStream; import java.net.URLConnection; -import java.security.MessageDigest; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -39,22 +37,6 @@ public class FileUtil { } } - public static String md5(File file) { - try { - MessageDigest digest = MessageDigest.getInstance("MD5"); - FileInputStream fis = new FileInputStream(file); - byte[] bytes = new byte[4096]; - int count; - while ((count = fis.read(bytes)) != -1) digest.update(bytes, 0, count); - fis.close(); - StringBuilder sb = new StringBuilder(); - for (byte b : digest.digest()) sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); - return sb.toString(); - } catch (Exception e) { - return ""; - } - } - private static Uri getShareUri(File file) { return Build.VERSION.SDK_INT < Build.VERSION_CODES.N ? Uri.fromFile(file) : FileProvider.getUriForFile(Init.context(), Init.context().getPackageName() + ".provider", file); } diff --git a/app/src/main/java/com/github/catvod/utils/Notify.java b/app/src/main/java/com/github/catvod/utils/Notify.java index 3014c2a5..b6503515 100644 --- a/app/src/main/java/com/github/catvod/utils/Notify.java +++ b/app/src/main/java/com/github/catvod/utils/Notify.java @@ -18,7 +18,7 @@ public class Notify { } public static void show(String text) { - Init.run(() -> get().makeText(text)); + Init.post(() -> get().makeText(text)); } private void makeText(String message) { diff --git a/app/src/main/java/com/github/catvod/utils/Path.java b/app/src/main/java/com/github/catvod/utils/Path.java index e2cf7aa4..4a5c8a1f 100644 --- a/app/src/main/java/com/github/catvod/utils/Path.java +++ b/app/src/main/java/com/github/catvod/utils/Path.java @@ -10,6 +10,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -63,7 +64,7 @@ public class Path { byte[] data = new byte[is.available()]; is.read(data); is.close(); - return new String(data, "UTF-8"); + return new String(data, StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); return ""; diff --git a/app/src/main/java/com/github/catvod/utils/ResUtil.java b/app/src/main/java/com/github/catvod/utils/ResUtil.java deleted file mode 100644 index dc9cf5a4..00000000 --- a/app/src/main/java/com/github/catvod/utils/ResUtil.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.github.catvod.utils; - -import android.util.DisplayMetrics; -import android.util.TypedValue; - -import com.github.catvod.spider.Init; - -public class ResUtil { - - private static DisplayMetrics getDisplayMetrics() { - return Init.context().getResources().getDisplayMetrics(); - } - - public static int dp2px(int dp) { - return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getDisplayMetrics()); - } -} diff --git a/app/src/main/java/com/github/catvod/utils/Util.java b/app/src/main/java/com/github/catvod/utils/Util.java index 46b2e5d5..ecd04a96 100644 --- a/app/src/main/java/com/github/catvod/utils/Util.java +++ b/app/src/main/java/com/github/catvod/utils/Util.java @@ -3,35 +3,21 @@ package com.github.catvod.utils; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; -import android.net.Uri; -import android.os.Build; -import android.view.View; -import android.view.ViewGroup; -import android.webkit.ValueCallback; -import android.webkit.WebView; -import android.webkit.WebViewClient; import com.github.catvod.spider.Init; +import java.text.DecimalFormat; import java.util.Arrays; import java.util.List; -import java.util.Locale; import java.util.regex.Pattern; public class Util { - public static final Pattern RULE = Pattern.compile("http((?!http).){12,}?\\.(m3u8|mp4|mkv|flv|mp3|m4a|aac)\\?.*|http((?!http).){12,}\\.(m3u8|mp4|mkv|flv|mp3|m4a|aac)|http((?!http).)*?video/tos*"); public static final Pattern THUNDER = Pattern.compile("(magnet|thunder|ed2k):.*"); - public static final String CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36"; + public static final String CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36"; public static final List MEDIA = Arrays.asList("mp4", "mkv", "mov", "wav", "wma", "wmv", "flv", "avi", "iso", "mpg", "ts", "mp3", "aac", "flac", "m4a", "ape", "ogg"); public static final List SUB = Arrays.asList("srt", "ass", "ssa", "vtt"); - public static boolean isVip(String url) { - 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"); - for (String host : hosts) if (url.contains(host)) return true; - return false; - } - public static boolean isThunder(String url) { return THUNDER.matcher(url).find() || isTorrent(url); } @@ -40,11 +26,6 @@ public class Util { return !url.startsWith("magnet") && url.split(";")[0].endsWith(".torrent"); } - public static boolean isVideoFormat(String url) { - if (url.contains("url=http") || url.contains(".js") || url.contains(".css") || url.contains(".html")) return false; - return RULE.matcher(url).find(); - } - public static boolean isSub(String text) { return SUB.contains(getExt(text).toLowerCase()); } @@ -59,31 +40,9 @@ public class Util { public static String getSize(double size) { if (size <= 0) return ""; - if (size > 1024 * 1024 * 1024 * 1024.0) { - size /= (1024 * 1024 * 1024 * 1024.0); - return String.format(Locale.getDefault(), "%.2f%s", size, "TB"); - } else if (size > 1024 * 1024 * 1024.0) { - size /= (1024 * 1024 * 1024.0); - return String.format(Locale.getDefault(), "%.2f%s", size, "GB"); - } else if (size > 1024 * 1024.0) { - size /= (1024 * 1024.0); - return String.format(Locale.getDefault(), "%.2f%s", size, "MB"); - } else { - size /= 1024.0; - return String.format(Locale.getDefault(), "%.2f%s", size, "KB"); - } - } - - public static String fixUrl(String base, String src) { - if (src.startsWith("//")) { - Uri parse = Uri.parse(base); - return parse.getScheme() + ":" + src; - } else if (!src.contains("://")) { - Uri parse = Uri.parse(base); - return parse.getScheme() + "://" + parse.getHost() + src; - } else { - return src; - } + String[] units = new String[]{"bytes", "KB", "MB", "GB", "TB"}; + int digitGroups = (int) (Math.log10(size) / Math.log10(1024)); + return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; } public static String removeExt(String text) { @@ -118,46 +77,4 @@ public class Util { manager.setPrimaryClip(ClipData.newPlainText("fongmi", text)); Notify.show("已複製 " + text); } - - public static void loadUrl(WebView webView, String script) { - loadUrl(webView, script, null); - } - - public static void loadUrl(WebView webView, String script, ValueCallback callback) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - webView.evaluateJavascript(script, callback); - } else { - webView.loadUrl("javascript:" + script); - } - } - - public static void addView(View view, ViewGroup.LayoutParams params) { - try { - ViewGroup group = Init.getActivity().getWindow().getDecorView().findViewById(android.R.id.content); - group.addView(view, params); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static void removeView(View view) { - try { - ViewGroup group = Init.getActivity().getWindow().getDecorView().findViewById(android.R.id.content); - group.removeView(view); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static void loadWebView(String url, WebViewClient client) { - Init.run(() -> { - WebView webView = new WebView(Init.context()); - webView.getSettings().setDatabaseEnabled(true); - webView.getSettings().setDomStorageEnabled(true); - webView.getSettings().setJavaScriptEnabled(true); - addView(webView, new ViewGroup.LayoutParams(0, 0)); - webView.setWebViewClient(client); - webView.loadUrl(url); - }); - } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 8df9bef6..d9f1f0b6 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,69 +1,95 @@ - + android:orientation="vertical"> - -