diff --git a/app/build.gradle b/app/build.gradle index dfee2a2e4..709ef0689 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ android { minSdk 21 targetSdk 28 versionCode 210 - versionName "20231211" + versionName "20231214" javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] @@ -125,6 +125,7 @@ dependencies { implementation 'org.nanohttpd:nanohttpd:2.3.1' implementation('org.simpleframework:simple-xml:2.7.1') { exclude group: 'stax', module: 'stax-api' exclude group: 'xpp3', module: 'xpp3' } implementation(ext: 'aar', name: 'dlna-core', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'go-proxy-video', group: 'fongmi', version: 'release') leanbackImplementation(ext: 'aar', name: 'dlna-dmr', group: 'fongmi', version: 'release') leanbackImplementation 'androidx.leanback:leanback:1.2.0-alpha04' leanbackImplementation 'me.jessyan:autosize:1.2.1' diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java index 9cf557958..9cf434899 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java @@ -77,6 +77,7 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit @Override protected void initView() { + mBinding.vod.requestFocus(); mBinding.vodUrl.setText(ApiConfig.getDesc()); mBinding.liveUrl.setText(LiveConfig.getDesc()); mBinding.wallUrl.setText(WallConfig.getDesc()); diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index 4c49041ab..774900d80 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -625,8 +625,14 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List } private void setQualityActivated(Result result) { - mPlayers.start(result, isUseParse(), getSite().isChangeable() ? getSite().getTimeout() : -1); - mBinding.danmaku.hide(); + try { + result.setUrl(Source.get().fetch(result)); + mPlayers.start(result, isUseParse(), getSite().isChangeable() ? getSite().getTimeout() : -1); + mBinding.danmaku.hide(); + } catch (Exception e) { + ErrorEvent.extract(e.getMessage()); + e.printStackTrace(); + } } private void reverseEpisode(boolean scroll) { diff --git a/app/src/main/java/com/fongmi/android/tv/App.java b/app/src/main/java/com/fongmi/android/tv/App.java index 9cbc8313d..44e2cdd81 100644 --- a/app/src/main/java/com/fongmi/android/tv/App.java +++ b/app/src/main/java/com/fongmi/android/tv/App.java @@ -18,7 +18,6 @@ import com.fongmi.android.tv.utils.Notify; import com.github.catvod.Init; import com.github.catvod.bean.Doh; import com.github.catvod.net.OkHttp; -import com.github.catvod.utils.Github; import com.google.gson.Gson; import com.orhanobut.logger.AndroidLogAdapter; import com.orhanobut.logger.LogAdapter; @@ -41,7 +40,7 @@ public class App extends Application { public App() { instance = this; - executor = Executors.newFixedThreadPool(Constant.THREAD_POOL); + executor = Executors.newFixedThreadPool(Constant.THREAD_POOL * 2); handler = HandlerCompat.createAsync(Looper.getMainLooper()); gson = new Gson(); } diff --git a/app/src/main/java/com/fongmi/android/tv/api/ApiConfig.java b/app/src/main/java/com/fongmi/android/tv/api/ApiConfig.java index 3c9640141..d1138d436 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/ApiConfig.java +++ b/app/src/main/java/com/fongmi/android/tv/api/ApiConfig.java @@ -120,7 +120,7 @@ public class ApiConfig { } public void load(Callback callback) { - new Thread(() -> loadConfig(callback)).start(); + App.execute(() -> loadConfig(callback)); } private void loadConfig(Callback callback) { diff --git a/app/src/main/java/com/fongmi/android/tv/api/JsLoader.java b/app/src/main/java/com/fongmi/android/tv/api/JsLoader.java index f51c61284..22400ddcf 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/JsLoader.java +++ b/app/src/main/java/com/fongmi/android/tv/api/JsLoader.java @@ -55,7 +55,7 @@ public class JsLoader { private Spider find(Map params) { if (!params.containsKey("siteKey")) return spiders.get(recent); Site site = ApiConfig.get().getSite(params.get("siteKey")); - return site.isEmpty() ? null : ApiConfig.get().getSpider(site); + return site.isEmpty() ? new SpiderNull() : ApiConfig.get().getSpider(site); } public Object[] proxyInvoke(Map params) { diff --git a/app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java b/app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java index c4b52e925..e6e2106ba 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java +++ b/app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java @@ -93,7 +93,7 @@ public class LiveConfig { } public void load(Callback callback) { - new Thread(() -> loadConfig(callback)).start(); + App.execute(() -> loadConfig(callback)); } private void loadConfig(Callback callback) { diff --git a/app/src/main/java/com/fongmi/android/tv/api/PyLoader.java b/app/src/main/java/com/fongmi/android/tv/api/PyLoader.java index 4783f038e..b0ab7f7db 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/PyLoader.java +++ b/app/src/main/java/com/fongmi/android/tv/api/PyLoader.java @@ -3,6 +3,7 @@ package com.fongmi.android.tv.api; import android.content.Context; import com.fongmi.android.tv.App; +import com.fongmi.android.tv.bean.Site; import com.github.catvod.crawler.Spider; import com.github.catvod.crawler.SpiderNull; @@ -51,11 +52,15 @@ public class PyLoader { } } + private Spider find(Map params) { + if (!params.containsKey("siteKey")) return spiders.get(recent); + Site site = ApiConfig.get().getSite(params.get("siteKey")); + return site.isEmpty() ? new SpiderNull() : ApiConfig.get().getSpider(site); + } + public Object[] proxyInvoke(Map params) { try { - Spider spider = spiders.get(recent); - if (spider == null) return null; - return spider.proxyLocal(params); + return find(params).proxyLocal(params); } catch (Throwable e) { e.printStackTrace(); return null; diff --git a/app/src/main/java/com/fongmi/android/tv/api/WallConfig.java b/app/src/main/java/com/fongmi/android/tv/api/WallConfig.java index 997e71bb8..07474cd4b 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/WallConfig.java +++ b/app/src/main/java/com/fongmi/android/tv/api/WallConfig.java @@ -75,7 +75,7 @@ public class WallConfig { } public void load(Callback callback) { - new Thread(() -> loadConfig(callback)).start(); + App.execute(() -> loadConfig(callback)); } private void loadConfig(Callback callback) { diff --git a/app/src/main/java/com/fongmi/android/tv/player/Source.java b/app/src/main/java/com/fongmi/android/tv/player/Source.java index 26d181aa2..1c67441cf 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/Source.java +++ b/app/src/main/java/com/fongmi/android/tv/player/Source.java @@ -6,6 +6,7 @@ import com.fongmi.android.tv.player.extractor.BiliBili; import com.fongmi.android.tv.player.extractor.Force; import com.fongmi.android.tv.player.extractor.JianPian; import com.fongmi.android.tv.player.extractor.Push; +import com.fongmi.android.tv.player.extractor.Sniffer; import com.fongmi.android.tv.player.extractor.TVBus; import com.fongmi.android.tv.player.extractor.Thunder; import com.fongmi.android.tv.player.extractor.Youtube; @@ -33,6 +34,7 @@ public class Source { extractors.add(new Force()); extractors.add(new JianPian()); extractors.add(new Push()); + extractors.add(new Sniffer()); extractors.add(new Thunder()); extractors.add(new TVBus()); extractors.add(new Youtube()); @@ -50,12 +52,15 @@ public class Source { String url = result.getUrl().v(); Extractor extractor = getExtractor(url); if (extractor != null) result.setParse(0); + if (extractor instanceof Sniffer) result.setParse(1); return extractor == null ? url : extractor.fetch(url); } public String fetch(Channel channel) throws Exception { String url = channel.getCurrent().split("\\$")[0]; Extractor extractor = getExtractor(url); + if (extractor != null) channel.setParse(0); + if (extractor instanceof Sniffer) channel.setParse(1); return extractor == null ? url : extractor.fetch(url); } diff --git a/app/src/main/java/com/fongmi/android/tv/player/extractor/Sniffer.java b/app/src/main/java/com/fongmi/android/tv/player/extractor/Sniffer.java new file mode 100644 index 000000000..dd03be331 --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/player/extractor/Sniffer.java @@ -0,0 +1,24 @@ +package com.fongmi.android.tv.player.extractor; + +import com.fongmi.android.tv.player.Source; + +public class Sniffer implements Source.Extractor { + + @Override + public boolean match(String scheme, String host) { + return scheme.equals("video"); + } + + @Override + public String fetch(String url) throws Exception { + return url.substring(8); + } + + @Override + public void stop() { + } + + @Override + public void exit() { + } +} diff --git a/app/src/main/java/com/fongmi/android/tv/server/Nano.java b/app/src/main/java/com/fongmi/android/tv/server/Nano.java index f44342c89..f115fb27b 100644 --- a/app/src/main/java/com/fongmi/android/tv/server/Nano.java +++ b/app/src/main/java/com/fongmi/android/tv/server/Nano.java @@ -69,6 +69,7 @@ public class Nano extends NanoHTTPD { Map files = new HashMap<>(); if (session.getMethod() == Method.POST) parse(session, files); if (url.contains("?")) url = url.substring(0, url.indexOf('?')); + if (url.startsWith("/go")) return go(); if (url.startsWith("/m3u8")) return m3u8(session); if (url.startsWith("/proxy")) return proxy(session); if (url.startsWith("/tvbus")) return success(LiveConfig.getResp()); @@ -91,6 +92,11 @@ public class Nano extends NanoHTTPD { } } + private Response go() { + Server.get().go(); + return success(); + } + private Response m3u8(IHTTPSession session) { String url = session.getParms().get("url"); String result = M3U8.get(url, session.getHeaders()); diff --git a/app/src/main/java/com/fongmi/android/tv/server/Server.java b/app/src/main/java/com/fongmi/android/tv/server/Server.java index a18361399..4768028ae 100644 --- a/app/src/main/java/com/fongmi/android/tv/server/Server.java +++ b/app/src/main/java/com/fongmi/android/tv/server/Server.java @@ -1,20 +1,15 @@ package com.fongmi.android.tv.server; -import android.content.Context; -import android.net.wifi.WifiManager; -import android.text.format.Formatter; - import com.fongmi.android.tv.App; -import com.fongmi.quickjs.utils.Proxy; +import com.github.catvod.Proxy; +import com.github.catvod.utils.Util; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.Enumeration; +import go_proxy_video.GoVideoProxy; +import go_proxy_video.Go_proxy_video; public class Server { + private GoVideoProxy proxy; private Nano nano; private int port; @@ -43,7 +38,13 @@ public class Server { } public String getAddress(boolean local) { - return "http://" + (local ? "127.0.0.1" : getIP()) + ":" + getPort(); + return "http://" + (local ? "127.0.0.1" : Util.getIp()) + ":" + getPort(); + } + + public void go() { + if (proxy != null) proxy.stop(); + proxy = Go_proxy_video.newGoVideoProxy(); + App.execute(() -> proxy.start()); } public void start() { @@ -67,29 +68,9 @@ public class Server { nano.stop(); nano = null; } - } - - public String getIP() { - try { - WifiManager manager = (WifiManager) App.get().getApplicationContext().getSystemService(Context.WIFI_SERVICE); - int address = manager.getConnectionInfo().getIpAddress(); - if (address != 0) return Formatter.formatIpAddress(address); - return getHostAddress(); - } catch (Exception e) { - return ""; - } - } - - private String getHostAddress() throws SocketException { - for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { - NetworkInterface interfaces = en.nextElement(); - for (Enumeration addresses = interfaces.getInetAddresses(); addresses.hasMoreElements(); ) { - InetAddress inetAddress = addresses.nextElement(); - if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) { - return inetAddress.getHostAddress(); - } - } + if (proxy != null) { + proxy.stop(); + proxy = null; } - return ""; } } diff --git a/app/src/main/java/com/fongmi/android/tv/server/process/Action.java b/app/src/main/java/com/fongmi/android/tv/server/process/Action.java index 0e0c18b67..8fbd578d3 100644 --- a/app/src/main/java/com/fongmi/android/tv/server/process/Action.java +++ b/app/src/main/java/com/fongmi/android/tv/server/process/Action.java @@ -39,27 +39,28 @@ public class Action implements Process { switch (Objects.requireNonNullElse(params.get("do"), "")) { case "search": onSearch(params); - break; + return Nano.success(); case "push": onPush(params); - break; + return Nano.success(); case "setting": onSetting(params); - break; + return Nano.success(); case "file": onFile(params); - break; + return Nano.success(); case "refresh": onRefresh(params); - break; + return Nano.success(); case "cast": onCast(params); - break; + return Nano.success(); case "sync": onSync(params); - break; + return Nano.success(); + default: + return Nano.error(null); } - return Nano.success(); } private void onSearch(Map params) { diff --git a/app/src/main/java/com/fongmi/android/tv/utils/M3U8.java b/app/src/main/java/com/fongmi/android/tv/utils/M3U8.java index 12b29f5f3..883efb738 100644 --- a/app/src/main/java/com/fongmi/android/tv/utils/M3U8.java +++ b/app/src/main/java/com/fongmi/android/tv/utils/M3U8.java @@ -67,7 +67,7 @@ public class M3U8 { private static Headers getHeader(Map headers) { Headers.Builder builder = new Headers.Builder(); - for (Map.Entry header : headers.entrySet()) if (header.getKey().equalsIgnoreCase(HttpHeaders.USER_AGENT) || header.getKey().equalsIgnoreCase(HttpHeaders.REFERER)) builder.add(header.getKey(), header.getValue()); + for (Map.Entry header : headers.entrySet()) if (header.getKey().equalsIgnoreCase(HttpHeaders.USER_AGENT) || header.getKey().equalsIgnoreCase(HttpHeaders.REFERER) || header.getKey().equalsIgnoreCase(HttpHeaders.COOKIE)) builder.add(header.getKey(), header.getValue()); builder.add(HttpHeaders.RANGE, "bytes=0-"); return builder.build(); } diff --git a/app/src/main/java/com/fongmi/android/tv/utils/Sniffer.java b/app/src/main/java/com/fongmi/android/tv/utils/Sniffer.java index 5b2fe9208..ca20f590c 100644 --- a/app/src/main/java/com/fongmi/android/tv/utils/Sniffer.java +++ b/app/src/main/java/com/fongmi/android/tv/utils/Sniffer.java @@ -22,7 +22,7 @@ public class Sniffer { private static final String TAG = Sniffer.class.getSimpleName(); public static final Pattern CLICKER = Pattern.compile("\\[a=cr:(\\{.*?\\})\\/](.*?)\\[\\/a]"); - public static final Pattern AI_PUSH = Pattern.compile("(http|https|rtmp|rtsp|smb|thunder|magnet|ed2k|mitv|tvbox-xg|jianpian):[^\\s]+", Pattern.MULTILINE); + public static final Pattern AI_PUSH = Pattern.compile("(http|https|rtmp|rtsp|smb|thunder|magnet|ed2k|mitv|tvbox-xg|jianpian|video):[^\\s]+", Pattern.MULTILINE); public static final Pattern SNIFFER = 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 List THUNDER = Arrays.asList("thunder", "magnet", "ed2k"); diff --git a/app/src/mobile/java/com/fongmi/android/tv/cast/CastVideo.java b/app/src/mobile/java/com/fongmi/android/tv/cast/CastVideo.java index 327c10187..40e3df806 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/cast/CastVideo.java +++ b/app/src/mobile/java/com/fongmi/android/tv/cast/CastVideo.java @@ -2,6 +2,7 @@ package com.fongmi.android.tv.cast; import com.fongmi.android.tv.server.Server; import com.github.catvod.utils.Path; +import com.github.catvod.utils.Util; public class CastVideo { @@ -14,7 +15,7 @@ public class CastVideo { private CastVideo(String name, String url) { if (url.startsWith("file")) url = Server.get().getAddress() + "/" + url.replace(Path.rootPath(), ""); - if (url.contains("127.0.0.1")) url = url.replace("127.0.0.1", Server.get().getIP()); + if (url.contains("127.0.0.1")) url = url.replace("127.0.0.1", Util.getIp()); this.name = name; this.url = url; } diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java index c66573380..d7ca8940a 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java @@ -79,7 +79,7 @@ import java.util.List; import tv.danmaku.ijk.media.player.ui.IjkVideoView; -public class LiveActivity extends BaseActivity implements CustomKeyDownLive.Listener, TrackDialog.Listener, Biometric.Callback, PassCallback, LiveCallback, GroupAdapter.OnClickListener, ChannelAdapter.OnClickListener, SubtitleCallback, CastDialog.Listener { +public class LiveActivity extends BaseActivity implements CustomKeyDownLive.Listener, TrackDialog.Listener, Biometric.Callback, PassCallback, LiveCallback, GroupAdapter.OnClickListener, ChannelAdapter.OnClickListener, SubtitleCallback, CastDialog.Listener, InfoDialog.Listener { private ActivityLiveBinding mBinding; private ChannelAdapter mChannelAdapter; @@ -329,7 +329,6 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List private void onInfo() { InfoDialog.create(this).title(mBinding.control.title.getText()).headers(mPlayers.getHeaders()).url(mPlayers.getUrl()).show(); - setRedirect(true); } private void onBack() { @@ -1006,6 +1005,18 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List else showControl(); } + @Override + public void onShare(CharSequence title, String url) { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Intent.EXTRA_TEXT, url); + intent.putExtra("name", title); + intent.putExtra("title", title); + intent.setType("text/plain"); + startActivity(Util.getChooser(intent)); + setRedirect(true); + } + @Override protected void onUserLeaveHint() { super.onUserLeaveHint(); diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index 1936c70cc..dd7260a8a 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -118,7 +118,7 @@ import master.flame.danmaku.danmaku.model.IDisplay; import master.flame.danmaku.danmaku.model.android.DanmakuContext; import tv.danmaku.ijk.media.player.ui.IjkVideoView; -public class VideoActivity extends BaseActivity implements Clock.Callback, CustomKeyDownVod.Listener, TrackDialog.Listener, ControlDialog.Listener, FlagAdapter.OnClickListener, EpisodeAdapter.OnClickListener, QualityAdapter.OnClickListener, QuickAdapter.OnClickListener, ParseAdapter.OnClickListener, SubtitleCallback, CastDialog.Listener { +public class VideoActivity extends BaseActivity implements Clock.Callback, CustomKeyDownVod.Listener, TrackDialog.Listener, ControlDialog.Listener, FlagAdapter.OnClickListener, EpisodeAdapter.OnClickListener, QualityAdapter.OnClickListener, QuickAdapter.OnClickListener, ParseAdapter.OnClickListener, SubtitleCallback, CastDialog.Listener, InfoDialog.Listener { private ActivityVideoBinding mBinding; private ViewGroup.LayoutParams mFrameParams; @@ -607,8 +607,14 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo @Override public void onItemClick(Result result) { - mPlayers.start(result, isUseParse(), getSite().isChangeable() ? getSite().getTimeout() : -1); - mBinding.danmaku.hide(); + try { + result.setUrl(Source.get().fetch(result)); + mPlayers.start(result, isUseParse(), getSite().isChangeable() ? getSite().getTimeout() : -1); + mBinding.danmaku.hide(); + } catch (Exception e) { + ErrorEvent.extract(e.getMessage()); + e.printStackTrace(); + } } @Override @@ -698,7 +704,6 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo private void onInfo() { InfoDialog.create(this).title(mBinding.control.title.getText()).headers(mPlayers.getHeaders()).url(mPlayers.getUrl()).show(); - setRedirect(true); } private void onFull() { @@ -1146,6 +1151,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo @Subscribe(threadMode = ThreadMode.MAIN) public void onActionEvent(ActionEvent event) { + if (isRedirect()) return; if (ActionEvent.PLAY.equals(event.getAction()) || ActionEvent.PAUSE.equals(event.getAction())) { mBinding.control.play.performClick(); } else if (ActionEvent.NEXT.equals(event.getAction())) { @@ -1159,14 +1165,26 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo @Subscribe(threadMode = ThreadMode.MAIN) public void onRefreshEvent(RefreshEvent event) { - if (event.getType() == RefreshEvent.Type.DETAIL) getDetail(); - else if (event.getType() == RefreshEvent.Type.PLAYER) onRefresh(); - else if (event.getType() == RefreshEvent.Type.DANMAKU) checkDanmu(event.getPath()); - else if (event.getType() == RefreshEvent.Type.SUBTITLE) mPlayers.setSub(Sub.from(event.getPath())); + if (isRedirect()) return; + switch (event.getType()) { + case DETAIL: + getDetail(); + break; + case PLAYER: + onRefresh(); + break; + case DANMAKU: + checkDanmu(event.getPath()); + break; + case SUBTITLE: + mPlayers.setSub(Sub.from(event.getPath())); + break; + } } @Subscribe(threadMode = ThreadMode.MAIN) public void onPlayerEvent(PlayerEvent event) { + if (isRedirect()) return; switch (event.getState()) { case 0: setPosition(); @@ -1249,6 +1267,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo @Subscribe(threadMode = ThreadMode.MAIN) public void onErrorEvent(ErrorEvent event) { + if (isRedirect()) return; if (mPlayers.addRetry() > event.getRetry()) checkError(event); else onRefresh(); } @@ -1593,6 +1612,18 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo } } + @Override + public void onShare(CharSequence title, String url) { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Intent.EXTRA_TEXT, url); + intent.putExtra("name", title); + intent.putExtra("title", title); + intent.setType("text/plain"); + startActivity(Util.getChooser(intent)); + setRedirect(true); + } + @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java index 1bb5e4811..56068a020 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java @@ -32,6 +32,7 @@ import com.fongmi.android.tv.ui.adapter.DeviceAdapter; import com.fongmi.android.tv.utils.Notify; import com.github.catvod.net.OkHttp; import com.github.catvod.utils.Path; +import com.github.catvod.utils.Util; import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import org.fourthline.cling.support.lastchange.EventedValue; @@ -77,7 +78,7 @@ public class CastDialog extends BaseDialog implements DeviceAdapter.OnClickListe String fd = history.getVodId(); if (fd.startsWith("/")) fd = Server.get().getAddress() + "/file://" + fd.replace(Path.rootPath(), ""); if (fd.startsWith("file")) fd = Server.get().getAddress() + "/" + fd.replace(Path.rootPath(), ""); - if (fd.contains("127.0.0.1")) fd = fd.replace("127.0.0.1", Server.get().getIP()); + if (fd.contains("127.0.0.1")) fd = fd.replace("127.0.0.1", Util.getIp()); body.add("history", history.toString().replace(id, fd)); return this; } diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/InfoDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/InfoDialog.java index 95f78464f..3009ac0d0 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/InfoDialog.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/InfoDialog.java @@ -1,7 +1,6 @@ package com.fongmi.android.tv.ui.dialog; import android.app.Activity; -import android.content.Intent; import android.view.LayoutInflater; import android.view.View; @@ -18,7 +17,7 @@ import java.util.Map; public class InfoDialog { private final DialogInfoBinding binding; - private final Activity activity; + private final Listener callback; private AlertDialog dialog; private CharSequence title; private String header; @@ -29,7 +28,8 @@ public class InfoDialog { } public InfoDialog(Activity activity) { - this.binding = DialogInfoBinding.inflate(LayoutInflater.from(this.activity = activity)); + this.binding = DialogInfoBinding.inflate(LayoutInflater.from(activity)); + this.callback = (Listener) activity; } public InfoDialog title(CharSequence title) { @@ -74,13 +74,7 @@ public class InfoDialog { } private void onShare(View view) { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(Intent.EXTRA_TEXT, url); - intent.putExtra("name", title); - intent.putExtra("title", title); - intent.setType("text/plain"); - activity.startActivity(Util.getChooser(intent)); + callback.onShare(title, url); dialog.dismiss(); } @@ -89,4 +83,9 @@ public class InfoDialog { Util.copy(url); return true; } + + public interface Listener { + + void onShare(CharSequence title, String url); + } } diff --git a/catvod/src/main/java/com/github/catvod/Proxy.java b/catvod/src/main/java/com/github/catvod/Proxy.java new file mode 100644 index 000000000..27092bfc0 --- /dev/null +++ b/catvod/src/main/java/com/github/catvod/Proxy.java @@ -0,0 +1,20 @@ +package com.github.catvod; + +import com.github.catvod.utils.Util; + +public class Proxy { + + private static int port = 9978; + + public static void set(int port) { + Proxy.port = port; + } + + public static int getPort() { + return port; + } + + public static String getUrl(boolean local) { + return "http://" + (local ? "127.0.0.1" : Util.getIp()) + ":" + getPort() + "/proxy"; + } +} diff --git a/catvod/src/main/java/com/github/catvod/utils/Util.java b/catvod/src/main/java/com/github/catvod/utils/Util.java index e0dc2b8cc..c619f3d9e 100644 --- a/catvod/src/main/java/com/github/catvod/utils/Util.java +++ b/catvod/src/main/java/com/github/catvod/utils/Util.java @@ -1,14 +1,24 @@ package com.github.catvod.utils; +import android.content.Context; import android.net.Uri; +import android.net.wifi.WifiManager; import android.text.TextUtils; +import android.text.format.Formatter; import android.util.Base64; +import com.github.catvod.Init; + import java.io.File; import java.io.FileInputStream; import java.math.BigInteger; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Enumeration; public class Util { @@ -67,4 +77,28 @@ public class Util { return false; } } + + public static String getIp() { + try { + WifiManager manager = (WifiManager) Init.context().getApplicationContext().getSystemService(Context.WIFI_SERVICE); + int address = manager.getConnectionInfo().getIpAddress(); + if (address != 0) return Formatter.formatIpAddress(address); + return getHostAddress(); + } catch (Exception e) { + return ""; + } + } + + private static String getHostAddress() throws SocketException { + for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { + NetworkInterface interfaces = en.nextElement(); + for (Enumeration addresses = interfaces.getInetAddresses(); addresses.hasMoreElements(); ) { + InetAddress inetAddress = addresses.nextElement(); + if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) { + return inetAddress.getHostAddress(); + } + } + } + return ""; + } } diff --git a/ijkplayer/build.gradle b/ijkplayer/build.gradle index 914a7d6bf..802edde4c 100644 --- a/ijkplayer/build.gradle +++ b/ijkplayer/build.gradle @@ -9,6 +9,10 @@ android { minSdk 21 targetSdk 28 } + + lint { + disable 'UnsafeOptInUsageError' + } } dependencies { diff --git a/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/SubtitleParser.java b/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/SubtitleParser.java index a02acd1b9..0a2b739e6 100644 --- a/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/SubtitleParser.java +++ b/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/SubtitleParser.java @@ -15,7 +15,7 @@ public class SubtitleParser { private static final String DIALOGUE_LINE_PREFIX = "Dialogue:"; public static List parse(String text) { - if (TextUtils.isEmpty(text) || text.length() >= 4096) return null; + if (TextUtils.isEmpty(text) || text.length() >= 512) return null; if (text.startsWith(DIALOGUE_LINE_PREFIX)) text = parseDialogueLine(text); text = text.replaceAll("\r\n", "
").replaceAll("\r", "
").replaceAll("\n", "
").replaceAll("\\{\\\\.*?\\}", ""); if (text.endsWith("
")) text = text.substring(0, text.lastIndexOf("
")); diff --git a/pyramid/src/main/java/com/undcover/freedom/pyramid/Loader.java b/pyramid/src/main/java/com/undcover/freedom/pyramid/Loader.java index c4b8071ba..53be6d712 100644 --- a/pyramid/src/main/java/com/undcover/freedom/pyramid/Loader.java +++ b/pyramid/src/main/java/com/undcover/freedom/pyramid/Loader.java @@ -24,7 +24,7 @@ public class Loader { @Keep public Spider spider(Context context, String key, String api) { if (app == null) init(context); - PyObject obj = app.callAttr("init_py", cache, key, api); + PyObject obj = app.callAttr("spider", cache, key, api); return new Spider(app, obj); } } diff --git a/pyramid/src/main/java/com/undcover/freedom/pyramid/Spider.java b/pyramid/src/main/java/com/undcover/freedom/pyramid/Spider.java index 9251c7708..2acddaf2f 100644 --- a/pyramid/src/main/java/com/undcover/freedom/pyramid/Spider.java +++ b/pyramid/src/main/java/com/undcover/freedom/pyramid/Spider.java @@ -6,6 +6,7 @@ import android.text.TextUtils; import androidx.collection.ArrayMap; import com.chaquo.python.PyObject; +import com.github.catvod.Proxy; import com.github.catvod.net.OkHttp; import com.google.gson.Gson; @@ -69,12 +70,12 @@ public class Spider extends com.github.catvod.crawler.Spider { @Override public String searchContent(String key, boolean quick, String pg) { - return app.callAttr("searchContent", obj, key, quick, pg).toString(); + return app.callAttr("searchContentPage", obj, key, quick, pg).toString(); } @Override public String playerContent(String flag, String id, List vipFlags) { - return app.callAttr("playerContent", obj, flag, id, gson.toJson(vipFlags)).toString(); + return replaceProxy(app.callAttr("playerContent", obj, flag, id, gson.toJson(vipFlags)).toString()); } @Override @@ -102,10 +103,14 @@ public class Spider extends com.github.catvod.crawler.Spider { return new Object[]{code, type, OkHttp.newCall(url, header, param).execute().body().byteStream()}; } else { if (content.isEmpty()) content = OkHttp.newCall(url, header).execute().body().string(); - return new Object[]{code, type, new ByteArrayInputStream(content.getBytes())}; + return new Object[]{code, type, new ByteArrayInputStream(replaceProxy(content).getBytes())}; } } + private String replaceProxy(String content) { + return content.replace("http://127.0.0.1:UndCover/proxy?", Proxy.getUrl(true) + "?do=py&"); + } + private Headers getHeader(String header) throws JSONException { Headers.Builder builder = new Headers.Builder(); if (TextUtils.isEmpty(header)) return builder.build(); diff --git a/pyramid/src/main/python/app.py b/pyramid/src/main/python/app.py index e3fa4b8c4..6f5d5f0b9 100644 --- a/pyramid/src/main/python/app.py +++ b/pyramid/src/main/python/app.py @@ -4,12 +4,21 @@ from importlib.machinery import SourceFileLoader import json -def create_file(file_path): - if os.path.exists(file_path) is False: - os.makedirs(file_path) +def spider(cache, key, api): + name = os.path.basename(api) + path = cache + '/' + name + downloadFile(path, api) + return SourceFileLoader(name, path).load_module().Spider() + + +def downloadFile(name, api): + if api.startswith('http'): + writeFile(name, redirect(api).content) + else: + writeFile(name, str.encode(api)) -def write_file(name, content): +def writeFile(name, content): with open(name, 'wb') as f: f.write(content) @@ -22,20 +31,6 @@ def redirect(url): return rsp -def download_file(name, api): - if api.startswith('http'): - write_file(name, redirect(api).content) - else: - write_file(name, str.encode(api)) - - -def init_py(cache, key, api): - name = os.path.basename(api) - path = cache + '/' + name - download_file(path, api) - return SourceFileLoader(name, path).load_module().Spider() - - def str2json(content): return json.loads(content) @@ -80,6 +75,12 @@ def searchContent(ru, key, quick): return formatJo +def searchContentPage(ru, key, quick, pg): + result = ru.searchContentPage(key, quick, pg) + formatJo = json.dumps(result, ensure_ascii=False) + return formatJo + + def localProxy(ru, param): result = ru.localProxy(str2json(param)) return result diff --git a/pyramid/src/main/python/base/spider.py b/pyramid/src/main/python/base/spider.py index 2dc949799..31819ffb6 100644 --- a/pyramid/src/main/python/base/spider.py +++ b/pyramid/src/main/python/base/spider.py @@ -40,6 +40,9 @@ class Spider(metaclass=ABCMeta): def searchContent(self, key, quick): pass + def searchContentPage(self, key, quick, pg): + pass + @abstractmethod def playerContent(self, flag, id, vipFlags): pass @@ -63,9 +66,6 @@ class Spider(metaclass=ABCMeta): def getDependence(self): return [] - def setExtendInfo(self, extend): - self.extend = extend - def regStr(self, src, reg, group=1): m = re.search(reg, src) src = '' @@ -80,18 +80,18 @@ class Spider(metaclass=ABCMeta): clean = re.sub('[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\U0001F680-\U0001F6FF\U0001F1E0-\U0001F1FF]', '', src) return clean - def fetch(self, url, headers={}, cookies=""): - rsp = requests.get(url, headers=headers, cookies=cookies) + def fetch(self, url, cookies=None, headers=None, timeout=5, verify=True): + rsp = requests.get(url, cookies=cookies, headers=headers, timeout=timeout, verify=verify) rsp.encoding = 'utf-8' return rsp - def post(self, url, data, headers={}, cookies={}): - rsp = requests.post(url, data=data, headers=headers, cookies=cookies) + def post(self, url, data, cookies=None, headers=None, timeout=5, verify=True): + rsp = requests.post(url, data=data, cookies=cookies, headers=headers, timeout=timeout, verify=verify) rsp.encoding = 'utf-8' return rsp - def postJson(self, url, json, headers={}, cookies={}): - rsp = requests.post(url, json=json, headers=headers, cookies=cookies) + def postJson(self, url, json, cookies=None, headers=None, timeout=5, verify=True): + rsp = requests.post(url, json=json, cookies=cookies, headers=headers, timeout=timeout, verify=verify) rsp.encoding = 'utf-8' return rsp @@ -105,5 +105,5 @@ class Spider(metaclass=ABCMeta): else: return ele[0] - def loadModule(self, name, fileName): - return SourceFileLoader(name, fileName).load_module() + def loadModule(self, name, path): + return SourceFileLoader(name, path).load_module() diff --git a/pyramid/src/main/python/runner.py b/pyramid/src/main/python/runner.py index 203462740..8ad616f8d 100644 --- a/pyramid/src/main/python/runner.py +++ b/pyramid/src/main/python/runner.py @@ -26,6 +26,9 @@ class Runner(): def searchContent(self, key, quick): return self.spider.searchContent(key, quick) + def searchContentPage(self, key, quick, pg): + return self.spider.searchContentPage(key, quick, pg) + def playerContent(self, flag, id, vipFlags): return self.spider.playerContent(flag, id, vipFlags) diff --git a/pyramid/src/main/python/trigger.py b/pyramid/src/main/python/trigger.py index 8524930eb..5a1cec1b1 100644 --- a/pyramid/src/main/python/trigger.py +++ b/pyramid/src/main/python/trigger.py @@ -23,6 +23,10 @@ class Trigger(): def searchContent(sp_obj, key, quick): return sp_obj.searchContent(key, quick) + @staticmethod + def searchContentPage(sp_obj, key, quick, pg): + return sp_obj.searchContentPage(key, quick, pg) + @staticmethod def playerContent(sp_obj, flag, id, vipFlags): return sp_obj.playerContent(flag, id, vipFlags) diff --git a/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java b/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java index 1195124bb..65c1f64aa 100644 --- a/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java +++ b/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java @@ -8,7 +8,7 @@ import com.fongmi.quickjs.utils.Connect; import com.fongmi.quickjs.utils.Crypto; import com.fongmi.quickjs.utils.JSUtil; import com.fongmi.quickjs.utils.Parser; -import com.fongmi.quickjs.utils.Proxy; +import com.github.catvod.Proxy; import com.github.catvod.utils.Trans; import com.orhanobut.logger.Logger; import com.whl.quickjs.wrapper.JSArray; @@ -78,13 +78,13 @@ public class Global { @Keep @JSMethod public String getProxy(Boolean local) { - return Proxy.getUrl() + "?do=js"; + return Proxy.getUrl(local) + "?do=js"; } @Keep @JSMethod public String js2Proxy(Boolean dynamic, Integer siteType, String siteKey, String url, JSObject headers) { - return getProxy(true) + "&from=catvod" + "&siteType=" + siteType + "&siteKey=" + siteKey + "&header=" + URLEncoder.encode(headers.stringify()) + "&url=" + URLEncoder.encode(url); + return getProxy(!dynamic) + "&from=catvod" + "&siteType=" + siteType + "&siteKey=" + siteKey + "&header=" + URLEncoder.encode(headers.stringify()) + "&url=" + URLEncoder.encode(url); } @Keep diff --git a/quickjs/src/main/java/com/fongmi/quickjs/utils/Proxy.java b/quickjs/src/main/java/com/fongmi/quickjs/utils/Proxy.java deleted file mode 100644 index 5e2866de3..000000000 --- a/quickjs/src/main/java/com/fongmi/quickjs/utils/Proxy.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fongmi.quickjs.utils; - -public class Proxy { - - private static int port = 9978; - - public static void set(int port) { - Proxy.port = port; - } - - public static String getUrl() { - return "http://127.0.0.1:" + port + "/proxy"; - } -}