diff --git a/app/src/leanback/AndroidManifest.xml b/app/src/leanback/AndroidManifest.xml
index 79e92f8f3..751e6736d 100644
--- a/app/src/leanback/AndroidManifest.xml
+++ b/app/src/leanback/AndroidManifest.xml
@@ -77,6 +77,7 @@
+
diff --git a/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java b/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java
index 9b6a16e67..fb93149d2 100644
--- a/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java
+++ b/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java
@@ -7,9 +7,11 @@ import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.bean.Drm;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.bean.Live;
+import com.fongmi.android.tv.player.Players;
import com.fongmi.android.tv.utils.UrlUtil;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Path;
+import com.github.catvod.utils.Util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -60,15 +62,17 @@ public class LiveParser {
Channel channel = Channel.create("");
for (String line : text.split("\n")) {
if (Thread.interrupted()) break;
- if (line.startsWith("#EXTINF:")) {
+ if (setting.find(line)) {
+ setting.check(line);
+ } else if (line.startsWith("#EXTINF:")) {
Group group = live.find(Group.create(extract(line, GROUP)));
channel = group.find(Channel.create(extract(line, NAME)));
channel.setLogo(extract(line, LOGO));
- } else if (line.contains("://")) {
+ } else if (!line.startsWith("#") && line.contains("://")) {
+ String[] split = line.split("\\|");
+ for (String s : split) setting.check(s);
+ channel.getUrls().add(split[0]);
setting.copy(channel).clear();
- channel.getUrls().add(line);
- } else {
- setting.check(line);
}
}
}
@@ -125,17 +129,24 @@ public class LiveParser {
return new Setting();
}
+ public boolean find(String line) {
+ return line.startsWith("ua") || line.startsWith("parse") || line.startsWith("click") || line.startsWith("player") || line.startsWith("referer") || line.startsWith("#EXTVLCOPT:") || line.startsWith("#KODIPROP:");
+ }
+
public void check(String line) {
- if (line.startsWith("ua")) ua(line);
- if (line.startsWith("parse")) parse(line);
- if (line.startsWith("click")) click(line);
- if (line.startsWith("player")) player(line);
- if (line.startsWith("referer")) referer(line);
- if (line.startsWith("#EXTVLCOPT:http-user-agent")) ua(line);
- if (line.startsWith("#EXTVLCOPT:http-referer")) referer(line);
- if (line.startsWith("#KODIPROP:inputstream.adaptive.license_key")) key(line);
- if (line.startsWith("#KODIPROP:inputstream.adaptive.license_type")) type(line);
if (line.contains("#genre#")) clear();
+ else if (line.startsWith("ua")) ua(line);
+ else if (line.startsWith("parse")) parse(line);
+ else if (line.startsWith("click")) click(line);
+ else if (line.startsWith("player")) player(line);
+ else if (line.startsWith("user-agent")) ua(line);
+ else if (line.startsWith("User-Agent")) ua(line);
+ else if (line.startsWith("referer")) referer(line);
+ else if (line.startsWith("Referer")) referer(line);
+ else if (line.startsWith("#EXTVLCOPT:http-user-agent")) ua(line);
+ else if (line.startsWith("#EXTVLCOPT:http-referer")) referer(line);
+ else if (line.startsWith("#KODIPROP:inputstream.adaptive.license_key")) key(line);
+ else if (line.startsWith("#KODIPROP:inputstream.adaptive.license_type")) type(line);
}
public Setting copy(Channel channel) {
@@ -150,7 +161,7 @@ public class LiveParser {
private void ua(String line) {
try {
- ua = line.split("=")[1].trim();
+ ua = line.split("ua=")[1].trim().replace("\"", "");
} catch (Exception e) {
ua = null;
}
@@ -158,7 +169,7 @@ public class LiveParser {
private void referer(String line) {
try {
- referer = line.split("=")[1].trim();
+ referer = line.split("referer=")[1].trim().replace("\"", "");
} catch (Exception e) {
referer = null;
}
@@ -166,7 +177,7 @@ public class LiveParser {
private void parse(String line) {
try {
- parse = Integer.parseInt(line.split("=")[1].trim());
+ parse = Integer.parseInt(line.split("parse=")[1].trim());
} catch (Exception e) {
parse = null;
}
@@ -174,7 +185,7 @@ public class LiveParser {
private void click(String line) {
try {
- click = line.split("=")[1].trim();
+ click = line.split("click=")[1].trim();
} catch (Exception e) {
click = null;
}
@@ -182,7 +193,7 @@ public class LiveParser {
private void player(String line) {
try {
- player = Integer.parseInt(line.split("=")[1].trim());
+ player = Integer.parseInt(line.split("player=")[1].trim());
} catch (Exception e) {
player = null;
}
@@ -190,20 +201,32 @@ public class LiveParser {
private void key(String line) {
try {
- key = line.split("=")[1].trim();
+ key = line.split("license_key=")[1].trim();
+ if (!key.startsWith("http") && !key.startsWith("{") && key.contains(":")) convert();
} catch (Exception e) {
key = null;
+ } finally {
+ player = Players.EXO;
}
}
private void type(String line) {
try {
- type = line.split("=")[1].trim();
+ type = line.split("license_type=")[1].trim();
} catch (Exception e) {
type = null;
+ } finally {
+ player = Players.EXO;
}
}
+ private void convert() {
+ String[] split = key.split(":");
+ String k = Util.base64(Util.hex2byte(split[1])).replace("=", "");
+ String kid = Util.base64(Util.hex2byte(split[0])).replace("=", "");
+ key = String.format("{ \"keys\":[ { \"kty\":\"oct\", \"k\":\"%s\", \"kid\":\"%s\" } ], \"type\":\"temporary\" }", k, kid);
+ }
+
private void clear() {
ua = null;
key = null;
diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Parse.java b/app/src/main/java/com/fongmi/android/tv/bean/Parse.java
index 3aaaa4e01..e262759a1 100644
--- a/app/src/main/java/com/fongmi/android/tv/bean/Parse.java
+++ b/app/src/main/java/com/fongmi/android/tv/bean/Parse.java
@@ -112,6 +112,10 @@ public class Parse {
if (getExt().getHeader() == null) getExt().setHeader(header);
}
+ public boolean isEmpty() {
+ return getType() == 0 && getUrl().isEmpty();
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
diff --git a/app/src/main/java/com/fongmi/android/tv/player/ParseJob.java b/app/src/main/java/com/fongmi/android/tv/player/ParseJob.java
index 532d962b1..89298c52d 100644
--- a/app/src/main/java/com/fongmi/android/tv/player/ParseJob.java
+++ b/app/src/main/java/com/fongmi/android/tv/player/ParseJob.java
@@ -55,7 +55,7 @@ public class ParseJob implements ParseCallback {
if (useParse) parse = ApiConfig.get().getParse();
if (result.getPlayUrl().startsWith("json:")) parse = Parse.get(1, result.getPlayUrl().substring(5));
if (result.getPlayUrl().startsWith("parse:")) parse = ApiConfig.get().getParse(result.getPlayUrl().substring(6));
- if (parse == null) parse = Parse.get(0, result.getPlayUrl());
+ if (parse.isEmpty()) parse.setUrl(result.getPlayUrl());
parse.setHeader(result.getHeader());
parse.setClick(getClick(result));
}
@@ -99,7 +99,7 @@ public class ParseJob implements ParseCallback {
case 3: //Json聚合
jsonMix(webUrl, flag);
break;
- case 4: //上帝模式
+ case 4: //超級解析
godParse(webUrl, flag);
break;
}
diff --git a/app/src/main/java/com/fongmi/android/tv/player/extractor/JianPian.java b/app/src/main/java/com/fongmi/android/tv/player/extractor/JianPian.java
index b32a04518..d16c3ed92 100644
--- a/app/src/main/java/com/fongmi/android/tv/player/extractor/JianPian.java
+++ b/app/src/main/java/com/fongmi/android/tv/player/extractor/JianPian.java
@@ -15,7 +15,7 @@ public class JianPian implements Source.Extractor {
@Override
public boolean match(String scheme, String host) {
- return scheme.equals("tvbox-xg") || scheme.equals("jianpian");
+ return scheme.equals("tvbox-xg") || scheme.equals("jianpian") || scheme.equals("ftp");
}
private void init() {
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 83a1a6856..ae54f3723 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
@@ -19,7 +19,7 @@ import java.util.regex.Pattern;
public class Sniffer {
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|video):[^\\s]+", Pattern.MULTILINE);
+ public static final Pattern AI_PUSH = Pattern.compile("(http|https|rtmp|rtsp|smb|ftp|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/AndroidManifest.xml b/app/src/mobile/AndroidManifest.xml
index 1e1aed32b..c9ecbaecf 100644
--- a/app/src/mobile/AndroidManifest.xml
+++ b/app/src/mobile/AndroidManifest.xml
@@ -61,6 +61,7 @@
+