|
|
|
@ -1,8 +1,5 @@ |
|
|
|
package com.fongmi.android.tv.api.config; |
|
|
|
package com.fongmi.android.tv.api.config; |
|
|
|
|
|
|
|
|
|
|
|
import android.net.Uri; |
|
|
|
|
|
|
|
import android.text.TextUtils; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.fongmi.android.tv.App; |
|
|
|
import com.fongmi.android.tv.App; |
|
|
|
import com.fongmi.android.tv.R; |
|
|
|
import com.fongmi.android.tv.R; |
|
|
|
import com.fongmi.android.tv.Setting; |
|
|
|
import com.fongmi.android.tv.Setting; |
|
|
|
@ -17,9 +14,8 @@ import com.fongmi.android.tv.bean.Keep; |
|
|
|
import com.fongmi.android.tv.bean.Live; |
|
|
|
import com.fongmi.android.tv.bean.Live; |
|
|
|
import com.fongmi.android.tv.bean.Rule; |
|
|
|
import com.fongmi.android.tv.bean.Rule; |
|
|
|
import com.fongmi.android.tv.db.AppDatabase; |
|
|
|
import com.fongmi.android.tv.db.AppDatabase; |
|
|
|
|
|
|
|
import com.fongmi.android.tv.event.RefreshEvent; |
|
|
|
import com.fongmi.android.tv.impl.Callback; |
|
|
|
import com.fongmi.android.tv.impl.Callback; |
|
|
|
import com.fongmi.android.tv.server.Server; |
|
|
|
|
|
|
|
import com.fongmi.android.tv.ui.activity.LiveActivity; |
|
|
|
|
|
|
|
import com.fongmi.android.tv.utils.Notify; |
|
|
|
import com.fongmi.android.tv.utils.Notify; |
|
|
|
import com.fongmi.android.tv.utils.UrlUtil; |
|
|
|
import com.fongmi.android.tv.utils.UrlUtil; |
|
|
|
import com.github.catvod.bean.Header; |
|
|
|
import com.github.catvod.bean.Header; |
|
|
|
@ -28,29 +24,22 @@ import com.github.catvod.net.OkHttp; |
|
|
|
import com.github.catvod.utils.Json; |
|
|
|
import com.github.catvod.utils.Json; |
|
|
|
import com.google.gson.JsonObject; |
|
|
|
import com.google.gson.JsonObject; |
|
|
|
|
|
|
|
|
|
|
|
import java.io.InterruptedIOException; |
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.concurrent.Future; |
|
|
|
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger; |
|
|
|
|
|
|
|
import java.util.function.Function; |
|
|
|
import java.util.function.Function; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
|
|
|
public class LiveConfig { |
|
|
|
public class LiveConfig extends BaseConfig { |
|
|
|
|
|
|
|
|
|
|
|
private static final String TAG = LiveConfig.class.getSimpleName(); |
|
|
|
private static final String TAG = LiveConfig.class.getSimpleName(); |
|
|
|
private final AtomicInteger taskId = new AtomicInteger(0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Live home; |
|
|
|
private Live home; |
|
|
|
private Config config; |
|
|
|
|
|
|
|
private List<Live> lives; |
|
|
|
private List<Live> lives; |
|
|
|
private List<Rule> rules; |
|
|
|
private List<Rule> rules; |
|
|
|
private List<String> ads; |
|
|
|
private List<String> ads; |
|
|
|
private Future<?> future; |
|
|
|
|
|
|
|
private boolean sync; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class Loader { |
|
|
|
private static class Loader { |
|
|
|
static volatile LiveConfig INSTANCE = new LiveConfig(); |
|
|
|
static volatile LiveConfig INSTANCE = new LiveConfig(); |
|
|
|
@ -85,7 +74,8 @@ public class LiveConfig { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static boolean hasUrl() { |
|
|
|
public static boolean hasUrl() { |
|
|
|
return getUrl() != null && !getUrl().isEmpty(); |
|
|
|
String url = getUrl(); |
|
|
|
|
|
|
|
return url != null && !url.isEmpty(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void load(Config config, Callback callback) { |
|
|
|
public static void load(Config config, Callback callback) { |
|
|
|
@ -106,55 +96,39 @@ public class LiveConfig { |
|
|
|
public LiveConfig clear() { |
|
|
|
public LiveConfig clear() { |
|
|
|
home = null; |
|
|
|
home = null; |
|
|
|
lives = null; |
|
|
|
lives = null; |
|
|
|
|
|
|
|
rules = null; |
|
|
|
|
|
|
|
ads = null; |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private boolean isCanceled(Throwable e) { |
|
|
|
@Override |
|
|
|
return "Canceled".equals(e.getMessage()) || e instanceof InterruptedException || e instanceof InterruptedIOException; |
|
|
|
protected String getTag() { |
|
|
|
|
|
|
|
return TAG; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void load() { |
|
|
|
@Override |
|
|
|
if (sync) return; |
|
|
|
protected Config defaultConfig() { |
|
|
|
load(new Callback()); |
|
|
|
return Config.live(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void load(Callback callback) { |
|
|
|
@Override |
|
|
|
int id = taskId.incrementAndGet(); |
|
|
|
protected void doLoad(int id, Config config, Callback callback) throws Throwable { |
|
|
|
if (future != null && !future.isDone()) future.cancel(true); |
|
|
|
String json = Decoder.getJson(UrlUtil.convert(config.getUrl()), TAG); |
|
|
|
future = App.submit(() -> loadConfig(id, config, callback)); |
|
|
|
if (Json.isObj(json)) checkJson(id, config, callback, Json.parse(json).getAsJsonObject()); |
|
|
|
callback.start(); |
|
|
|
else parseText(id, config, callback, json); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void loadConfig(int id, Config config, Callback callback) { |
|
|
|
public void load() { |
|
|
|
try { |
|
|
|
if (sync) return; |
|
|
|
OkHttp.cancel(TAG); |
|
|
|
load(new Callback()); |
|
|
|
Server.get().start(); |
|
|
|
|
|
|
|
String json = Decoder.getJson(UrlUtil.convert(config.getUrl()), TAG); |
|
|
|
|
|
|
|
if (Json.isObj(json)) checkJson(id, config, callback, Json.parse(json).getAsJsonObject()); |
|
|
|
|
|
|
|
else parseText(id, config, callback, json); |
|
|
|
|
|
|
|
if (taskId.get() == id && config.equals(this.config)) config.update(); |
|
|
|
|
|
|
|
} catch (Throwable e) { |
|
|
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
if (isCanceled(e)) return; |
|
|
|
|
|
|
|
if (taskId.get() != id) return; |
|
|
|
|
|
|
|
if (TextUtils.isEmpty(config.getUrl())) App.post(() -> callback.error("")); |
|
|
|
|
|
|
|
else App.post(() -> callback.error(Notify.getError(R.string.error_config_get, e))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void parseText(int id, Config config, Callback callback, String text) { |
|
|
|
private void parseText(int id, Config config, Callback callback, String text) { |
|
|
|
Live live = new Live(parseName(config.getUrl()), config.getUrl()).sync(); |
|
|
|
Live live = new Live(UrlUtil.getName(config.getUrl()), config.getUrl()).sync(); |
|
|
|
lives = new ArrayList<>(List.of(live)); |
|
|
|
lives = new ArrayList<>(List.of(live)); |
|
|
|
LiveParser.text(live, text); |
|
|
|
LiveParser.text(live, text); |
|
|
|
setHome(config, live, false); |
|
|
|
setHome(config, live, false); |
|
|
|
if (taskId.get() == id) App.post(callback::success); |
|
|
|
if (getTaskId() == id) App.post(callback::success); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String parseName(String url) { |
|
|
|
|
|
|
|
Uri uri = Uri.parse(url); |
|
|
|
|
|
|
|
String path = UrlUtil.path(uri); |
|
|
|
|
|
|
|
String host = UrlUtil.host(uri); |
|
|
|
|
|
|
|
return !path.isEmpty() ? path : !host.isEmpty() ? host : url; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void checkJson(int id, Config config, Callback callback, JsonObject object) { |
|
|
|
private void checkJson(int id, Config config, Callback callback, JsonObject object) { |
|
|
|
@ -170,7 +144,7 @@ public class LiveConfig { |
|
|
|
private void parseDepot(int id, Config config, Callback callback, JsonObject object) { |
|
|
|
private void parseDepot(int id, Config config, Callback callback, JsonObject object) { |
|
|
|
List<Depot> items = Depot.arrayFrom(object.getAsJsonArray("urls").toString()); |
|
|
|
List<Depot> items = Depot.arrayFrom(object.getAsJsonArray("urls").toString()); |
|
|
|
List<Config> configs = new ArrayList<>(); |
|
|
|
List<Config> configs = new ArrayList<>(); |
|
|
|
for (Depot item : items) configs.add(Config.find(item, 1)); |
|
|
|
for (Depot item : items) configs.add(Config.find(item, LIVE)); |
|
|
|
loadConfig(id, this.config = configs.get(0), callback); |
|
|
|
loadConfig(id, this.config = configs.get(0), callback); |
|
|
|
Config.delete(config.getUrl()); |
|
|
|
Config.delete(config.getUrl()); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -179,11 +153,11 @@ public class LiveConfig { |
|
|
|
try { |
|
|
|
try { |
|
|
|
initList(object); |
|
|
|
initList(object); |
|
|
|
initLive(config, object); |
|
|
|
initLive(config, object); |
|
|
|
if (taskId.get() != id) return; |
|
|
|
if (getTaskId() != id) return; |
|
|
|
if (callback != null) App.post(callback::success); |
|
|
|
if (callback != null) App.post(callback::success); |
|
|
|
} catch (Throwable e) { |
|
|
|
} catch (Throwable e) { |
|
|
|
e.printStackTrace(); |
|
|
|
e.printStackTrace(); |
|
|
|
if (taskId.get() != id) return; |
|
|
|
if (getTaskId() != id) return; |
|
|
|
if (callback != null) App.post(() -> callback.error(Notify.getError(R.string.error_config_parse, e))); |
|
|
|
if (callback != null) App.post(() -> callback.error(Notify.getError(R.string.error_config_parse, e))); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -205,13 +179,8 @@ public class LiveConfig { |
|
|
|
setHome(config, getLives().isEmpty() ? new Live() : getLives().stream().filter(item -> item.getName().equals(config.getHome())).findFirst().orElse(getLives().get(0)), false); |
|
|
|
setHome(config, getLives().isEmpty() ? new Live() : getLives().stream().filter(item -> item.getName().equals(config.getHome())).findFirst().orElse(getLives().get(0)), false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void bootLive() { |
|
|
|
|
|
|
|
Setting.putBootLive(false); |
|
|
|
|
|
|
|
LiveActivity.start(App.get()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void parse(JsonObject object) { |
|
|
|
public void parse(JsonObject object) { |
|
|
|
int id = taskId.incrementAndGet(); |
|
|
|
int id = nextTaskId(); |
|
|
|
parseConfig(id, getConfig(), null, object); |
|
|
|
parseConfig(id, getConfig(), null, object); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -219,7 +188,7 @@ public class LiveConfig { |
|
|
|
if (home != null && !channel.getGroup().isHidden()) home.keep(channel).save(); |
|
|
|
if (home != null && !channel.getGroup().isHidden()) home.keep(channel).save(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setKeep(List<Group> items) { |
|
|
|
public void applyKeepsToGroups(List<Group> items) { |
|
|
|
Set<String> key = Keep.getLive().stream().map(Keep::getKey).collect(Collectors.toSet()); |
|
|
|
Set<String> key = Keep.getLive().stream().map(Keep::getKey).collect(Collectors.toSet()); |
|
|
|
items.stream().filter(group -> !group.isKeep()) |
|
|
|
items.stream().filter(group -> !group.isKeep()) |
|
|
|
.flatMap(group -> group.getChannel().stream()) |
|
|
|
.flatMap(group -> group.getChannel().stream()) |
|
|
|
@ -227,7 +196,7 @@ public class LiveConfig { |
|
|
|
.forEach(channel -> items.get(0).add(channel)); |
|
|
|
.forEach(channel -> items.get(0).add(channel)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public int[] find(List<Group> items) { |
|
|
|
public int[] findKeepPosition(List<Group> items) { |
|
|
|
String[] splits = getHome().getKeep().split(AppDatabase.SYMBOL); |
|
|
|
String[] splits = getHome().getKeep().split(AppDatabase.SYMBOL); |
|
|
|
if (splits.length < 3) return new int[]{1, 0}; |
|
|
|
if (splits.length < 3) return new int[]{1, 0}; |
|
|
|
for (int i = 0; i < items.size(); i++) { |
|
|
|
for (int i = 0; i < items.size(); i++) { |
|
|
|
@ -243,7 +212,7 @@ public class LiveConfig { |
|
|
|
return new int[]{1, 0}; |
|
|
|
return new int[]{1, 0}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public int[] find(String number, List<Group> items) { |
|
|
|
public int[] findByChannelNumber(String number, List<Group> items) { |
|
|
|
for (int i = 0; i < items.size(); i++) { |
|
|
|
for (int i = 0; i < items.size(); i++) { |
|
|
|
int j = items.get(i).find(Integer.parseInt(number)); |
|
|
|
int j = items.get(i).find(Integer.parseInt(number)); |
|
|
|
if (j != -1) return new int[]{i, j}; |
|
|
|
if (j != -1) return new int[]{i, j}; |
|
|
|
@ -251,10 +220,6 @@ public class LiveConfig { |
|
|
|
return new int[]{-1, -1}; |
|
|
|
return new int[]{-1, -1}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean needSync(String url) { |
|
|
|
|
|
|
|
return sync || TextUtils.isEmpty(config.getUrl()) || url.equals(config.getUrl()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public List<Live> getLives() { |
|
|
|
public List<Live> getLives() { |
|
|
|
return lives == null ? lives = new ArrayList<>() : lives; |
|
|
|
return lives == null ? lives = new ArrayList<>() : lives; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -292,10 +257,6 @@ public class LiveConfig { |
|
|
|
this.ads = ads; |
|
|
|
this.ads = ads; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Config getConfig() { |
|
|
|
|
|
|
|
return config == null ? Config.live() : config; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Live getHome() { |
|
|
|
public Live getHome() { |
|
|
|
return home == null ? new Live() : home; |
|
|
|
return home == null ? new Live() : home; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -314,7 +275,6 @@ public class LiveConfig { |
|
|
|
config.home(home.getName()); |
|
|
|
config.home(home.getName()); |
|
|
|
if (save) config.save(); |
|
|
|
if (save) config.save(); |
|
|
|
getLives().forEach(item -> item.setActivated(home)); |
|
|
|
getLives().forEach(item -> item.setActivated(home)); |
|
|
|
if (App.activity() != null && App.activity() instanceof LiveActivity) return; |
|
|
|
if (!save && (home.isBoot() || Setting.isBootLive())) RefreshEvent.boot(); |
|
|
|
if (!save && (home.isBoot() || Setting.isBootLive())) App.post(this::bootLive); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|