Merge branch 'dev' into release

okjack
FongMi 2 years ago
commit 5d604bb01e
  1. 3
      app/build.gradle
  2. 1
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java
  3. 10
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  4. 3
      app/src/main/java/com/fongmi/android/tv/App.java
  5. 2
      app/src/main/java/com/fongmi/android/tv/api/ApiConfig.java
  6. 2
      app/src/main/java/com/fongmi/android/tv/api/JsLoader.java
  7. 2
      app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java
  8. 11
      app/src/main/java/com/fongmi/android/tv/api/PyLoader.java
  9. 2
      app/src/main/java/com/fongmi/android/tv/api/WallConfig.java
  10. 5
      app/src/main/java/com/fongmi/android/tv/player/Source.java
  11. 24
      app/src/main/java/com/fongmi/android/tv/player/extractor/Sniffer.java
  12. 6
      app/src/main/java/com/fongmi/android/tv/server/Nano.java
  13. 49
      app/src/main/java/com/fongmi/android/tv/server/Server.java
  14. 17
      app/src/main/java/com/fongmi/android/tv/server/process/Action.java
  15. 2
      app/src/main/java/com/fongmi/android/tv/utils/M3U8.java
  16. 2
      app/src/main/java/com/fongmi/android/tv/utils/Sniffer.java
  17. 3
      app/src/mobile/java/com/fongmi/android/tv/cast/CastVideo.java
  18. 15
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  19. 47
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  20. 3
      app/src/mobile/java/com/fongmi/android/tv/ui/dialog/CastDialog.java
  21. 19
      app/src/mobile/java/com/fongmi/android/tv/ui/dialog/InfoDialog.java
  22. 20
      catvod/src/main/java/com/github/catvod/Proxy.java
  23. 34
      catvod/src/main/java/com/github/catvod/utils/Util.java
  24. 4
      ijkplayer/build.gradle
  25. 2
      ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/SubtitleParser.java
  26. 2
      pyramid/src/main/java/com/undcover/freedom/pyramid/Loader.java
  27. 11
      pyramid/src/main/java/com/undcover/freedom/pyramid/Spider.java
  28. 37
      pyramid/src/main/python/app.py
  29. 22
      pyramid/src/main/python/base/spider.py
  30. 3
      pyramid/src/main/python/runner.py
  31. 4
      pyramid/src/main/python/trigger.py
  32. 6
      quickjs/src/main/java/com/fongmi/quickjs/method/Global.java
  33. 14
      quickjs/src/main/java/com/fongmi/quickjs/utils/Proxy.java

@ -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'

@ -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());

@ -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) {

@ -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();
}

@ -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) {

@ -55,7 +55,7 @@ public class JsLoader {
private Spider find(Map<String, String> 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<String, String> params) {

@ -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) {

@ -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<String, String> 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<String, String> 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;

@ -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) {

@ -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);
}

@ -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() {
}
}

@ -69,6 +69,7 @@ public class Nano extends NanoHTTPD {
Map<String, String> 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());

@ -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<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface interfaces = en.nextElement();
for (Enumeration<InetAddress> 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 "";
}
}

@ -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<String, String> params) {

@ -67,7 +67,7 @@ public class M3U8 {
private static Headers getHeader(Map<String, String> headers) {
Headers.Builder builder = new Headers.Builder();
for (Map.Entry<String, String> header : headers.entrySet()) if (header.getKey().equalsIgnoreCase(HttpHeaders.USER_AGENT) || header.getKey().equalsIgnoreCase(HttpHeaders.REFERER)) builder.add(header.getKey(), header.getValue());
for (Map.Entry<String, String> 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();
}

@ -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<String> THUNDER = Arrays.asList("thunder", "magnet", "ed2k");

@ -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;
}

@ -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();

@ -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);

@ -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;
}

@ -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);
}
}

@ -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";
}
}

@ -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<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface interfaces = en.nextElement();
for (Enumeration<InetAddress> addresses = interfaces.getInetAddresses(); addresses.hasMoreElements(); ) {
InetAddress inetAddress = addresses.nextElement();
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
return inetAddress.getHostAddress();
}
}
}
return "";
}
}

@ -9,6 +9,10 @@ android {
minSdk 21
targetSdk 28
}
lint {
disable 'UnsafeOptInUsageError'
}
}
dependencies {

@ -15,7 +15,7 @@ public class SubtitleParser {
private static final String DIALOGUE_LINE_PREFIX = "Dialogue:";
public static List<Cue> 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", "<br>").replaceAll("\r", "<br>").replaceAll("\n", "<br>").replaceAll("\\{\\\\.*?\\}", "");
if (text.endsWith("<br>")) text = text.substring(0, text.lastIndexOf("<br>"));

@ -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);
}
}

@ -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<String> 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();

@ -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

@ -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()

@ -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)

@ -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)

@ -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

@ -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";
}
}
Loading…
Cancel
Save