parent
3007a2c25d
commit
9919ae4a35
@ -0,0 +1,94 @@ |
||||
package com.github.catvod.bean.live; |
||||
|
||||
import android.text.TextUtils; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.JsonElement; |
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class Channel { |
||||
|
||||
@SerializedName("urls") |
||||
private List<String> urls; |
||||
@SerializedName("tvgName") |
||||
private String tvgName; |
||||
@SerializedName("number") |
||||
private String number; |
||||
@SerializedName("logo") |
||||
private String logo; |
||||
@SerializedName("name") |
||||
private String name; |
||||
@SerializedName("epg") |
||||
private String epg; |
||||
@SerializedName("ua") |
||||
private String ua; |
||||
@SerializedName("referer") |
||||
private String referer; |
||||
|
||||
public static Channel objectFrom(JsonElement element) { |
||||
return new Gson().fromJson(element, Channel.class); |
||||
} |
||||
|
||||
public static Channel create(String name) { |
||||
return new Channel(name); |
||||
} |
||||
|
||||
public Channel(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getNumber() { |
||||
return TextUtils.isEmpty(number) ? "" : number; |
||||
} |
||||
|
||||
public String getName() { |
||||
return TextUtils.isEmpty(name) ? "" : name; |
||||
} |
||||
|
||||
public List<String> getUrls() { |
||||
return urls = urls == null ? new ArrayList<>() : urls; |
||||
} |
||||
|
||||
public void setUrls(List<String> urls) { |
||||
this.urls = urls; |
||||
} |
||||
|
||||
public void setTvgName(String tvgName) { |
||||
this.tvgName = tvgName; |
||||
} |
||||
|
||||
public void setNumber(String number) { |
||||
this.number = number; |
||||
} |
||||
|
||||
public void setLogo(String logo) { |
||||
this.logo = logo; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public void setEpg(String epg) { |
||||
this.epg = epg; |
||||
} |
||||
|
||||
public void setUa(String ua) { |
||||
this.ua = ua; |
||||
} |
||||
|
||||
public void setReferer(String referer) { |
||||
this.referer = referer; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) return true; |
||||
if (!(obj instanceof Channel)) return false; |
||||
Channel it = (Channel) obj; |
||||
return getName().equals(it.getName()) || (!getNumber().isEmpty() && getNumber().equals(it.getNumber())); |
||||
} |
||||
} |
||||
@ -0,0 +1,69 @@ |
||||
package com.github.catvod.bean.live; |
||||
|
||||
import android.text.TextUtils; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.annotations.SerializedName; |
||||
import com.google.gson.reflect.TypeToken; |
||||
|
||||
import java.lang.reflect.Type; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
public class Group { |
||||
|
||||
@SerializedName("channel") |
||||
private List<Channel> channel; |
||||
@SerializedName("name") |
||||
private String name; |
||||
|
||||
public static List<Group> arrayFrom(String str) { |
||||
Type listType = new TypeToken<List<Group>>() {}.getType(); |
||||
List<Group> items = new Gson().fromJson(str, listType); |
||||
return items == null ? Collections.emptyList() : items; |
||||
} |
||||
|
||||
public static Group find(List<Group> items, Group item) { |
||||
for (Group group : items) if (group.getName().equals(item.getName())) return group; |
||||
items.add(item); |
||||
return item; |
||||
} |
||||
|
||||
public static Group create(String name) { |
||||
return new Group(name); |
||||
} |
||||
|
||||
public Group(String name) { |
||||
this.name = name; |
||||
if (name.contains("_")) setName(name.split("_")[0]); |
||||
} |
||||
|
||||
public List<Channel> getChannel() { |
||||
return channel = channel == null ? new ArrayList<>() : channel; |
||||
} |
||||
|
||||
public String getName() { |
||||
return TextUtils.isEmpty(name) ? "" : name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public Channel find(Channel channel) { |
||||
int index = getChannel().indexOf(channel); |
||||
if (index != -1) return getChannel().get(index); |
||||
getChannel().add(channel); |
||||
return channel; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (obj == null) return false; |
||||
if (this == obj) return true; |
||||
if (!(obj instanceof Group)) return false; |
||||
Group it = (Group) obj; |
||||
return getName().equals(it.getName()) && getChannel().size() == it.getChannel().size(); |
||||
} |
||||
} |
||||
@ -0,0 +1,50 @@ |
||||
package com.github.catvod.bean.xc; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
public class Config { |
||||
|
||||
@SerializedName("name") |
||||
private String name; |
||||
@SerializedName("pass") |
||||
private String pass; |
||||
@SerializedName("vod") |
||||
private boolean vod; |
||||
@SerializedName("formats") |
||||
private List<String> formats; |
||||
|
||||
private String url; |
||||
|
||||
public static Config objectFrom(String str) { |
||||
Config item = new Gson().fromJson(str, Config.class); |
||||
return item == null ? new Config() : item; |
||||
} |
||||
|
||||
public void setUrl(String url) { |
||||
this.url = url; |
||||
} |
||||
|
||||
public String getUrl() { |
||||
return url; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public String getPass() { |
||||
return pass; |
||||
} |
||||
|
||||
public boolean isVod() { |
||||
return vod; |
||||
} |
||||
|
||||
public List<String> getFormats() { |
||||
return formats == null ? Arrays.asList("ts") : formats; |
||||
} |
||||
} |
||||
@ -0,0 +1,33 @@ |
||||
package com.github.catvod.bean.xc; |
||||
|
||||
import android.text.TextUtils; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.annotations.SerializedName; |
||||
import com.google.gson.reflect.TypeToken; |
||||
|
||||
import java.lang.reflect.Type; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
public class XCategory { |
||||
|
||||
@SerializedName("category_id") |
||||
private String categoryId; |
||||
@SerializedName("category_name") |
||||
private String categoryName; |
||||
|
||||
public static List<XCategory> arrayFrom(String str) { |
||||
Type listType = new TypeToken<List<XCategory>>() {}.getType(); |
||||
List<XCategory> items = new Gson().fromJson(str, listType); |
||||
return items == null ? Collections.emptyList() : items; |
||||
} |
||||
|
||||
public String getCategoryId() { |
||||
return TextUtils.isEmpty(categoryId) ? "" : categoryId; |
||||
} |
||||
|
||||
public String getCategoryName() { |
||||
return TextUtils.isEmpty(categoryName) ? "" : categoryName; |
||||
} |
||||
} |
||||
@ -0,0 +1,72 @@ |
||||
package com.github.catvod.bean.xc; |
||||
|
||||
import android.text.TextUtils; |
||||
|
||||
import com.github.catvod.spider.XtreamCode; |
||||
import com.google.gson.Gson; |
||||
import com.google.gson.annotations.SerializedName; |
||||
import com.google.gson.reflect.TypeToken; |
||||
|
||||
import java.lang.reflect.Type; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
public class XStream { |
||||
|
||||
@SerializedName("name") |
||||
private String name; |
||||
@SerializedName("stream_id") |
||||
private String streamId; |
||||
@SerializedName("stream_type") |
||||
private String streamType; |
||||
@SerializedName("stream_icon") |
||||
private String streamIcon; |
||||
@SerializedName("epg_channel_id") |
||||
private String epgChannelId; |
||||
@SerializedName("category_id") |
||||
private String categoryId; |
||||
@SerializedName("container_extension") |
||||
private String containerExtension; |
||||
|
||||
public static List<XStream> arrayFrom(String str) { |
||||
Type listType = new TypeToken<List<XStream>>() {}.getType(); |
||||
List<XStream> items = new Gson().fromJson(str, listType); |
||||
return items == null ? Collections.emptyList() : items; |
||||
} |
||||
|
||||
public String getName() { |
||||
return TextUtils.isEmpty(name) ? "" : name; |
||||
} |
||||
|
||||
public String getStreamId() { |
||||
return TextUtils.isEmpty(streamId) ? "" : streamId; |
||||
} |
||||
|
||||
public String getStreamType() { |
||||
return TextUtils.isEmpty(streamType) ? "" : streamType; |
||||
} |
||||
|
||||
public String getStreamIcon() { |
||||
return TextUtils.isEmpty(streamIcon) ? "" : streamIcon; |
||||
} |
||||
|
||||
public String getEpgChannelId() { |
||||
return TextUtils.isEmpty(epgChannelId) ? "" : epgChannelId; |
||||
} |
||||
|
||||
public String getCategoryId() { |
||||
return TextUtils.isEmpty(categoryId) ? "" : categoryId; |
||||
} |
||||
|
||||
public String getContainerExtension() { |
||||
return TextUtils.isEmpty(containerExtension) ? "" : containerExtension; |
||||
} |
||||
|
||||
public List<String> getPlayUrl(Config config) { |
||||
List<String> urls = new ArrayList<>(); |
||||
if (!getContainerExtension().isEmpty()) urls.add(XtreamCode.getBuilder(config).addPathSegment(getStreamType()).addPathSegment(config.getName()).addPathSegment(config.getPass()).addPathSegment(getStreamId() + "." + getContainerExtension()).build().toString()); |
||||
else for (String format : config.getFormats()) urls.add(XtreamCode.getBuilder(config).addPathSegment(getStreamType()).addPathSegment(config.getName()).addPathSegment(config.getPass()).addPathSegment(getStreamId() + "." + format + "$" + format.toUpperCase()).build().toString()); |
||||
return urls; |
||||
} |
||||
} |
||||
@ -1,100 +0,0 @@ |
||||
package com.github.catvod.spider; |
||||
|
||||
import android.content.Context; |
||||
import android.os.SystemClock; |
||||
|
||||
import com.github.catvod.crawler.Spider; |
||||
import com.github.catvod.net.OkHttp; |
||||
import com.github.catvod.utils.FileUtil; |
||||
import com.github.catvod.utils.Path; |
||||
import com.github.catvod.utils.Shell; |
||||
|
||||
import java.io.BufferedInputStream; |
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.InputStream; |
||||
|
||||
public class Feiyang extends Spider { |
||||
|
||||
private static final String URL = "http://127.0.0.1:35345/"; |
||||
private static final String AIO = "allinone-linux-musl"; |
||||
private static final String SHELL = "run-allinone.sh"; |
||||
private static final File f_shell = new File(Path.files(), SHELL); |
||||
private static final File f_aio = new File(Path.files(), AIO); |
||||
private static Thread thread; |
||||
|
||||
@Override |
||||
public void init(Context context, String extend) throws Exception { |
||||
createShell(); |
||||
checkExtend(extend); |
||||
findAIO(Path.tv().listFiles()); |
||||
findAIO(Path.download().listFiles()); |
||||
} |
||||
|
||||
@Override |
||||
public String liveContent(String url) { |
||||
int retry = 0; |
||||
while ((OkHttp.string(URL)).isEmpty() && retry++ < 20) SystemClock.sleep(250); |
||||
return OkHttp.string(url.startsWith("http") ? url : URL + url); |
||||
} |
||||
|
||||
private void createShell() { |
||||
File cache = Path.cache("allinone.cache"); |
||||
String cachePath = cache.getAbsolutePath(); |
||||
String shellPath = f_shell.getAbsolutePath(); |
||||
String aioPath = f_aio.getAbsolutePath(); |
||||
String script = "if [ -e " + shellPath + ".kill ]; then\n" + "sh " + shellPath + ".kill;\n" + "killall -9 " + AIO + ";\n" + "sleep 1;\n" + "rm -f " + shellPath + ".kill;\n" + "fi\n" + "echo \"kill -9 $$\" >> " + shellPath + ".kill;\n" + "while(true)\n" + "do\n" + "TMPDIR=" + cachePath + " " + aioPath + " -ipv6=true " + " -port 35345 " + " >/dev/null 2>&1\n" + "pidlist=$(ps -ef|grep " + SHELL + "|grep -v grep|awk '{print $2}')\n" + "selfpid=$$\n" + "for pid in $pidlist\n" + "do\n" + "if [[ $pid != \"$selfpid\" ]] then\n" + "kill -9 $pid\n" + "fi\n" + "done\n" + "killall -9 " + AIO + "\n" + "rm -rf \"" + cachePath + "\"/*\n" + "sleep 5;\n" + "done"; |
||||
Path.write(f_shell, script); |
||||
} |
||||
|
||||
private void checkExtend(String extend) { |
||||
if (!extend.contains(";md5;")) return; |
||||
String[] texts = extend.split(";md5;"); |
||||
String url = texts[0].trim(); |
||||
String md5 = texts[1].trim(); |
||||
if (md5.startsWith("http")) md5 = OkHttp.string(md5).trim(); |
||||
if (FileUtil.md5(f_aio).equals(md5)) return; |
||||
try { |
||||
File file = Path.create(new File(Path.download(), AIO)); |
||||
download(file, OkHttp.newCall(url).body().byteStream()); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
private void download(File file, InputStream is) throws Exception { |
||||
FileOutputStream os = new FileOutputStream(file); |
||||
try (BufferedInputStream input = new BufferedInputStream(is)) { |
||||
byte[] buffer = new byte[4096]; |
||||
int readBytes; |
||||
while ((readBytes = input.read(buffer)) != -1) { |
||||
os.write(buffer, 0, readBytes); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void findAIO(File[] files) { |
||||
if (files == null || thread != null) return; |
||||
for (File f : files) { |
||||
if (f.getName().equals("allinone") || f.getName().startsWith("allinone-linux")) { |
||||
Path.move(f, f_aio); |
||||
} |
||||
} |
||||
if (f_aio.exists()) { |
||||
thread = new Thread(() -> Shell.exec("nohup " + f_shell.getAbsolutePath() + " &")); |
||||
thread.start(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void destroy() { |
||||
try { |
||||
Shell.exec("killall -9 " + AIO); |
||||
if (thread != null) thread.interrupt(); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} finally { |
||||
thread = null; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,88 @@ |
||||
package com.github.catvod.spider; |
||||
|
||||
import android.content.Context; |
||||
|
||||
import com.github.catvod.bean.live.Channel; |
||||
import com.github.catvod.bean.live.Group; |
||||
import com.github.catvod.bean.xc.Config; |
||||
import com.github.catvod.bean.xc.XCategory; |
||||
import com.github.catvod.bean.xc.XStream; |
||||
import com.github.catvod.crawler.Spider; |
||||
import com.github.catvod.net.OkHttp; |
||||
import com.google.gson.Gson; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import okhttp3.HttpUrl; |
||||
|
||||
public class XtreamCode extends Spider { |
||||
|
||||
private List<Group> groups; |
||||
private Config config; |
||||
|
||||
@Override |
||||
public void init(Context context, String extend) throws Exception { |
||||
config = Config.objectFrom(extend); |
||||
groups = new ArrayList<>(); |
||||
} |
||||
|
||||
@Override |
||||
public String liveContent(String url) { |
||||
config.setUrl(url); |
||||
List<XCategory> categoryList = getCategoryList(config); |
||||
List<XStream> streamList = getStreamList(config); |
||||
Map<String, String> categoryMap = new HashMap<>(); |
||||
for (XCategory category : categoryList) { |
||||
categoryMap.put(category.getCategoryId(), category.getCategoryName()); |
||||
} |
||||
for (XStream stream : streamList) { |
||||
if (!categoryMap.containsKey(stream.getCategoryId())) continue; |
||||
Group group = Group.find(groups, Group.create(categoryMap.get(stream.getCategoryId()))); |
||||
Channel channel = group.find(Channel.create(stream.getName())); |
||||
if (!stream.getStreamIcon().isEmpty()) channel.setLogo(stream.getStreamIcon()); |
||||
if (!stream.getEpgChannelId().isEmpty()) channel.setTvgName(stream.getEpgChannelId()); |
||||
channel.getUrls().addAll(stream.getPlayUrl(config)); |
||||
} |
||||
return new Gson().toJson(groups); |
||||
} |
||||
|
||||
public static HttpUrl.Builder getBuilder(Config config) { |
||||
HttpUrl url = HttpUrl.parse(config.getUrl()); |
||||
return new HttpUrl.Builder().scheme(url.scheme()).host(url.host()).port(url.port()); |
||||
} |
||||
|
||||
private String getApiUrl(Config config, String action) { |
||||
return getBuilder(config).addPathSegment("player_api.php").addQueryParameter("username", config.getName()).addQueryParameter("password", config.getPass()).addQueryParameter("action", action).build().toString(); |
||||
} |
||||
|
||||
private List<XCategory> getLiveCategoryList(Config config) { |
||||
return XCategory.arrayFrom(OkHttp.string(getApiUrl(config, "get_live_categories"))); |
||||
} |
||||
|
||||
private List<XStream> getLiveStreamList(Config config) { |
||||
return XStream.arrayFrom(OkHttp.string(getApiUrl(config, "get_live_streams"))); |
||||
} |
||||
|
||||
private List<XCategory> getVodCategoryList(Config config) { |
||||
return XCategory.arrayFrom(OkHttp.string(getApiUrl(config, "get_vod_categories"))); |
||||
} |
||||
|
||||
private List<XStream> getVodStreamList(Config config) { |
||||
return XStream.arrayFrom(OkHttp.string(getApiUrl(config, "get_vod_streams"))); |
||||
} |
||||
|
||||
private List<XCategory> getCategoryList(Config config) { |
||||
List<XCategory> categoryList = getLiveCategoryList(config); |
||||
if (config.isVod()) categoryList.addAll(getVodCategoryList(config)); |
||||
return categoryList; |
||||
} |
||||
|
||||
private List<XStream> getStreamList(Config config) { |
||||
List<XStream> streamList = getLiveStreamList(config); |
||||
if (config.isVod()) streamList.addAll(getVodStreamList(config)); |
||||
return streamList; |
||||
} |
||||
} |
||||
Binary file not shown.
@ -1 +1 @@ |
||||
91086bebb3dee1e2e8caf7d18c9a6c13 |
||||
90fd2379b3fb688bf7f56c442c78c6b3 |
||||
|
||||
Loading…
Reference in new issue